Completed
Branch sideload-incorrect-upload-from (f67182)
by
unknown
75:25 queued 67:12
created
core/admin/EE_Admin_Page_CPT.core.php 1 patch
Indentation   +1464 added lines, -1464 removed lines patch added patch discarded remove patch
@@ -28,492 +28,492 @@  discard block
 block discarded – undo
28 28
 {
29 29
 
30 30
 
31
-    /**
32
-     * This gets set in _setup_cpt
33
-     * It will contain the object for the custom post type.
34
-     *
35
-     * @var EE_CPT_Base
36
-     */
37
-    protected $_cpt_object;
38
-
39
-
40
-    /**
41
-     * a boolean flag to set whether the current route is a cpt route or not.
42
-     *
43
-     * @var bool
44
-     */
45
-    protected $_cpt_route = false;
46
-
47
-
48
-    /**
49
-     * This property allows cpt classes to define multiple routes as cpt routes.
50
-     * //in this array we define what the custom post type for this route is.
51
-     * array(
52
-     * 'route_name' => 'custom_post_type_slug'
53
-     * )
54
-     *
55
-     * @var array
56
-     */
57
-    protected $_cpt_routes = array();
58
-
59
-
60
-    /**
61
-     * This simply defines what the corresponding routes WP will be redirected to after completing a post save/update.
62
-     * in this format:
63
-     * array(
64
-     * 'post_type_slug' => 'edit_route'
65
-     * )
66
-     *
67
-     * @var array
68
-     */
69
-    protected $_cpt_edit_routes = array();
70
-
71
-
72
-    /**
73
-     * If child classes set the name of their main model via the $_cpt_obj_models property, EE_Admin_Page_CPT will
74
-     * attempt to retrieve the related object model for the edit pages and assign it to _cpt_page_object. the
75
-     * _cpt_model_names property should be in the following format: array(
76
-     * 'route_defined_by_action_param' => 'Model_Name')
77
-     *
78
-     * @var array $_cpt_model_names
79
-     */
80
-    protected $_cpt_model_names = array();
81
-
82
-
83
-    /**
84
-     * @var EE_CPT_Base
85
-     */
86
-    protected $_cpt_model_obj = false;
87
-
88
-    /**
89
-     * @var LoaderInterface $loader ;
90
-     */
91
-    protected $loader;
92
-
93
-    /**
94
-     * This will hold an array of autosave containers that will be used to obtain input values and hook into the WP
95
-     * autosave so we can save our inputs on the save_post hook!  Children classes should add to this array by using
96
-     * the _register_autosave_containers() method so that we don't override any other containers already registered.
97
-     * Registration of containers should be done before load_page_dependencies() is run.
98
-     *
99
-     * @var array()
100
-     */
101
-    protected $_autosave_containers = array();
102
-    protected $_autosave_fields = array();
103
-
104
-    /**
105
-     * Array mapping from admin actions to their equivalent wp core pages for custom post types. So when a user visits
106
-     * a page for an action, it will appear as if they were visiting the wp core page for that custom post type
107
-     *
108
-     * @var array
109
-     */
110
-    protected $_pagenow_map;
111
-
112
-
113
-    /**
114
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
115
-     * saved.  Child classes are required to declare this method.  Typically you would use this to save any additional
116
-     * data. Keep in mind also that "save_post" runs on EVERY post update to the database. ALSO very important.  When a
117
-     * post transitions from scheduled to published, the save_post action is fired but you will NOT have any _POST data
118
-     * containing any extra info you may have from other meta saves.  So MAKE sure that you handle this accordingly.
119
-     *
120
-     * @access protected
121
-     * @abstract
122
-     * @param  string      $post_id The ID of the cpt that was saved (so you can link relationally)
123
-     * @param  EE_CPT_Base $post    The post object of the cpt that was saved.
124
-     * @return void
125
-     */
126
-    abstract protected function _insert_update_cpt_item($post_id, $post);
127
-
128
-
129
-    /**
130
-     * This is hooked into the WordPress do_action('trashed_post') hook and runs after a cpt has been trashed.
131
-     *
132
-     * @abstract
133
-     * @access public
134
-     * @param  string $post_id The ID of the cpt that was trashed
135
-     * @return void
136
-     */
137
-    abstract public function trash_cpt_item($post_id);
138
-
139
-
140
-    /**
141
-     * This is hooked into the WordPress do_action('untrashed_post') hook and runs after a cpt has been untrashed
142
-     *
143
-     * @param  string $post_id theID of the cpt that was untrashed
144
-     * @return void
145
-     */
146
-    abstract public function restore_cpt_item($post_id);
147
-
148
-
149
-    /**
150
-     * This is hooked into the WordPress do_action('delete_cpt_item') hook and runs after a cpt has been fully deleted
151
-     * from the db
152
-     *
153
-     * @param  string $post_id the ID of the cpt that was deleted
154
-     * @return void
155
-     */
156
-    abstract public function delete_cpt_item($post_id);
157
-
158
-
159
-    /**
160
-     * @return LoaderInterface
161
-     * @throws InvalidArgumentException
162
-     * @throws InvalidDataTypeException
163
-     * @throws InvalidInterfaceException
164
-     */
165
-    protected function getLoader()
166
-    {
167
-        if (! $this->loader instanceof LoaderInterface) {
168
-            $this->loader = LoaderFactory::getLoader();
169
-        }
170
-        return $this->loader;
171
-    }
172
-
173
-    /**
174
-     * Just utilizing the method EE_Admin exposes for doing things before page setup.
175
-     *
176
-     * @access protected
177
-     * @return void
178
-     */
179
-    protected function _before_page_setup()
180
-    {
181
-        $page = isset($this->_req_data['page']) ? $this->_req_data['page'] : $this->page_slug;
182
-        $this->_cpt_routes = array_merge(
183
-            array(
184
-                'create_new' => $this->page_slug,
185
-                'edit'       => $this->page_slug,
186
-                'trash'      => $this->page_slug,
187
-            ),
188
-            $this->_cpt_routes
189
-        );
190
-        // let's see if the current route has a value for cpt_object_slug if it does we use that instead of the page
191
-        $this->_cpt_object = isset($this->_req_data['action']) && isset($this->_cpt_routes[ $this->_req_data['action'] ])
192
-            ? get_post_type_object($this->_cpt_routes[ $this->_req_data['action'] ])
193
-            : get_post_type_object($page);
194
-        // tweak pagenow for page loading.
195
-        if (! $this->_pagenow_map) {
196
-            $this->_pagenow_map = array(
197
-                'create_new' => 'post-new.php',
198
-                'edit'       => 'post.php',
199
-                'trash'      => 'post.php',
200
-            );
201
-        }
202
-        add_action('current_screen', array($this, 'modify_pagenow'));
203
-        // TODO the below will need to be reworked to account for the cpt routes that are NOT based off of page but action param.
204
-        // get current page from autosave
205
-        $current_page = isset($this->_req_data['ee_autosave_data']['ee-cpt-hidden-inputs']['current_page'])
206
-            ? $this->_req_data['ee_autosave_data']['ee-cpt-hidden-inputs']['current_page']
207
-            : null;
208
-        $this->_current_page = isset($this->_req_data['current_page'])
209
-            ? $this->_req_data['current_page']
210
-            : $current_page;
211
-        // autosave... make sure its only for the correct page
212
-        // if ( ! empty($this->_current_page) && $this->_current_page == $this->page_slug) {
213
-        // setup autosave ajax hook
214
-        // add_action('wp_ajax_ee-autosave', array( $this, 'do_extra_autosave_stuff' ), 10 ); //TODO reactivate when 4.2 autosave is implemented
215
-        // }
216
-    }
217
-
218
-
219
-    /**
220
-     * Simply ensure that we simulate the correct post route for cpt screens
221
-     *
222
-     * @param WP_Screen $current_screen
223
-     * @return void
224
-     */
225
-    public function modify_pagenow($current_screen)
226
-    {
227
-        global $pagenow, $hook_suffix;
228
-        // possibly reset pagenow.
229
-        if (! empty($this->_req_data['page'])
230
-            && $this->_req_data['page'] == $this->page_slug
231
-            && ! empty($this->_req_data['action'])
232
-            && isset($this->_pagenow_map[ $this->_req_data['action'] ])
233
-        ) {
234
-            $pagenow = $this->_pagenow_map[ $this->_req_data['action'] ];
235
-            $hook_suffix = $pagenow;
236
-        }
237
-    }
238
-
239
-
240
-    /**
241
-     * This method is used to register additional autosave containers to the _autosave_containers property.
242
-     *
243
-     * @todo We should automate this at some point by creating a wrapper for add_post_metabox and in our wrapper we
244
-     *       automatically register the id for the post metabox as a container.
245
-     * @param  array $ids an array of ids for containers that hold form inputs we want autosave to pickup.  Typically
246
-     *                    you would send along the id of a metabox container.
247
-     * @return void
248
-     */
249
-    protected function _register_autosave_containers($ids)
250
-    {
251
-        $this->_autosave_containers = array_merge($this->_autosave_fields, (array) $ids);
252
-    }
253
-
254
-
255
-    /**
256
-     * Something nifty.  We're going to loop through all the registered metaboxes and if the CALLBACK is an instance of
257
-     * EE_Admin_Page OR EE_Admin_Hooks, then we'll add the id to our _autosave_containers array.
258
-     */
259
-    protected function _set_autosave_containers()
260
-    {
261
-        global $wp_meta_boxes;
262
-        $containers = array();
263
-        if (empty($wp_meta_boxes)) {
264
-            return;
265
-        }
266
-        $current_metaboxes = isset($wp_meta_boxes[ $this->page_slug ]) ? $wp_meta_boxes[ $this->page_slug ] : array();
267
-        foreach ($current_metaboxes as $box_context) {
268
-            foreach ($box_context as $box_details) {
269
-                foreach ($box_details as $box) {
270
-                    if (is_array($box) && is_array($box['callback'])
271
-                        && (
272
-                            $box['callback'][0] instanceof EE_Admin_Page
273
-                            || $box['callback'][0] instanceof EE_Admin_Hooks
274
-                        )
275
-                    ) {
276
-                        $containers[] = $box['id'];
277
-                    }
278
-                }
279
-            }
280
-        }
281
-        $this->_autosave_containers = array_merge($this->_autosave_containers, $containers);
282
-        // add hidden inputs container
283
-        $this->_autosave_containers[] = 'ee-cpt-hidden-inputs';
284
-    }
285
-
286
-
287
-    protected function _load_autosave_scripts_styles()
288
-    {
289
-        /*wp_register_script('cpt-autosave', EE_ADMIN_URL . 'assets/ee-cpt-autosave.js', array('ee-serialize-full-array', 'event_editor_js'), EVENT_ESPRESSO_VERSION, TRUE );
31
+	/**
32
+	 * This gets set in _setup_cpt
33
+	 * It will contain the object for the custom post type.
34
+	 *
35
+	 * @var EE_CPT_Base
36
+	 */
37
+	protected $_cpt_object;
38
+
39
+
40
+	/**
41
+	 * a boolean flag to set whether the current route is a cpt route or not.
42
+	 *
43
+	 * @var bool
44
+	 */
45
+	protected $_cpt_route = false;
46
+
47
+
48
+	/**
49
+	 * This property allows cpt classes to define multiple routes as cpt routes.
50
+	 * //in this array we define what the custom post type for this route is.
51
+	 * array(
52
+	 * 'route_name' => 'custom_post_type_slug'
53
+	 * )
54
+	 *
55
+	 * @var array
56
+	 */
57
+	protected $_cpt_routes = array();
58
+
59
+
60
+	/**
61
+	 * This simply defines what the corresponding routes WP will be redirected to after completing a post save/update.
62
+	 * in this format:
63
+	 * array(
64
+	 * 'post_type_slug' => 'edit_route'
65
+	 * )
66
+	 *
67
+	 * @var array
68
+	 */
69
+	protected $_cpt_edit_routes = array();
70
+
71
+
72
+	/**
73
+	 * If child classes set the name of their main model via the $_cpt_obj_models property, EE_Admin_Page_CPT will
74
+	 * attempt to retrieve the related object model for the edit pages and assign it to _cpt_page_object. the
75
+	 * _cpt_model_names property should be in the following format: array(
76
+	 * 'route_defined_by_action_param' => 'Model_Name')
77
+	 *
78
+	 * @var array $_cpt_model_names
79
+	 */
80
+	protected $_cpt_model_names = array();
81
+
82
+
83
+	/**
84
+	 * @var EE_CPT_Base
85
+	 */
86
+	protected $_cpt_model_obj = false;
87
+
88
+	/**
89
+	 * @var LoaderInterface $loader ;
90
+	 */
91
+	protected $loader;
92
+
93
+	/**
94
+	 * This will hold an array of autosave containers that will be used to obtain input values and hook into the WP
95
+	 * autosave so we can save our inputs on the save_post hook!  Children classes should add to this array by using
96
+	 * the _register_autosave_containers() method so that we don't override any other containers already registered.
97
+	 * Registration of containers should be done before load_page_dependencies() is run.
98
+	 *
99
+	 * @var array()
100
+	 */
101
+	protected $_autosave_containers = array();
102
+	protected $_autosave_fields = array();
103
+
104
+	/**
105
+	 * Array mapping from admin actions to their equivalent wp core pages for custom post types. So when a user visits
106
+	 * a page for an action, it will appear as if they were visiting the wp core page for that custom post type
107
+	 *
108
+	 * @var array
109
+	 */
110
+	protected $_pagenow_map;
111
+
112
+
113
+	/**
114
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
115
+	 * saved.  Child classes are required to declare this method.  Typically you would use this to save any additional
116
+	 * data. Keep in mind also that "save_post" runs on EVERY post update to the database. ALSO very important.  When a
117
+	 * post transitions from scheduled to published, the save_post action is fired but you will NOT have any _POST data
118
+	 * containing any extra info you may have from other meta saves.  So MAKE sure that you handle this accordingly.
119
+	 *
120
+	 * @access protected
121
+	 * @abstract
122
+	 * @param  string      $post_id The ID of the cpt that was saved (so you can link relationally)
123
+	 * @param  EE_CPT_Base $post    The post object of the cpt that was saved.
124
+	 * @return void
125
+	 */
126
+	abstract protected function _insert_update_cpt_item($post_id, $post);
127
+
128
+
129
+	/**
130
+	 * This is hooked into the WordPress do_action('trashed_post') hook and runs after a cpt has been trashed.
131
+	 *
132
+	 * @abstract
133
+	 * @access public
134
+	 * @param  string $post_id The ID of the cpt that was trashed
135
+	 * @return void
136
+	 */
137
+	abstract public function trash_cpt_item($post_id);
138
+
139
+
140
+	/**
141
+	 * This is hooked into the WordPress do_action('untrashed_post') hook and runs after a cpt has been untrashed
142
+	 *
143
+	 * @param  string $post_id theID of the cpt that was untrashed
144
+	 * @return void
145
+	 */
146
+	abstract public function restore_cpt_item($post_id);
147
+
148
+
149
+	/**
150
+	 * This is hooked into the WordPress do_action('delete_cpt_item') hook and runs after a cpt has been fully deleted
151
+	 * from the db
152
+	 *
153
+	 * @param  string $post_id the ID of the cpt that was deleted
154
+	 * @return void
155
+	 */
156
+	abstract public function delete_cpt_item($post_id);
157
+
158
+
159
+	/**
160
+	 * @return LoaderInterface
161
+	 * @throws InvalidArgumentException
162
+	 * @throws InvalidDataTypeException
163
+	 * @throws InvalidInterfaceException
164
+	 */
165
+	protected function getLoader()
166
+	{
167
+		if (! $this->loader instanceof LoaderInterface) {
168
+			$this->loader = LoaderFactory::getLoader();
169
+		}
170
+		return $this->loader;
171
+	}
172
+
173
+	/**
174
+	 * Just utilizing the method EE_Admin exposes for doing things before page setup.
175
+	 *
176
+	 * @access protected
177
+	 * @return void
178
+	 */
179
+	protected function _before_page_setup()
180
+	{
181
+		$page = isset($this->_req_data['page']) ? $this->_req_data['page'] : $this->page_slug;
182
+		$this->_cpt_routes = array_merge(
183
+			array(
184
+				'create_new' => $this->page_slug,
185
+				'edit'       => $this->page_slug,
186
+				'trash'      => $this->page_slug,
187
+			),
188
+			$this->_cpt_routes
189
+		);
190
+		// let's see if the current route has a value for cpt_object_slug if it does we use that instead of the page
191
+		$this->_cpt_object = isset($this->_req_data['action']) && isset($this->_cpt_routes[ $this->_req_data['action'] ])
192
+			? get_post_type_object($this->_cpt_routes[ $this->_req_data['action'] ])
193
+			: get_post_type_object($page);
194
+		// tweak pagenow for page loading.
195
+		if (! $this->_pagenow_map) {
196
+			$this->_pagenow_map = array(
197
+				'create_new' => 'post-new.php',
198
+				'edit'       => 'post.php',
199
+				'trash'      => 'post.php',
200
+			);
201
+		}
202
+		add_action('current_screen', array($this, 'modify_pagenow'));
203
+		// TODO the below will need to be reworked to account for the cpt routes that are NOT based off of page but action param.
204
+		// get current page from autosave
205
+		$current_page = isset($this->_req_data['ee_autosave_data']['ee-cpt-hidden-inputs']['current_page'])
206
+			? $this->_req_data['ee_autosave_data']['ee-cpt-hidden-inputs']['current_page']
207
+			: null;
208
+		$this->_current_page = isset($this->_req_data['current_page'])
209
+			? $this->_req_data['current_page']
210
+			: $current_page;
211
+		// autosave... make sure its only for the correct page
212
+		// if ( ! empty($this->_current_page) && $this->_current_page == $this->page_slug) {
213
+		// setup autosave ajax hook
214
+		// add_action('wp_ajax_ee-autosave', array( $this, 'do_extra_autosave_stuff' ), 10 ); //TODO reactivate when 4.2 autosave is implemented
215
+		// }
216
+	}
217
+
218
+
219
+	/**
220
+	 * Simply ensure that we simulate the correct post route for cpt screens
221
+	 *
222
+	 * @param WP_Screen $current_screen
223
+	 * @return void
224
+	 */
225
+	public function modify_pagenow($current_screen)
226
+	{
227
+		global $pagenow, $hook_suffix;
228
+		// possibly reset pagenow.
229
+		if (! empty($this->_req_data['page'])
230
+			&& $this->_req_data['page'] == $this->page_slug
231
+			&& ! empty($this->_req_data['action'])
232
+			&& isset($this->_pagenow_map[ $this->_req_data['action'] ])
233
+		) {
234
+			$pagenow = $this->_pagenow_map[ $this->_req_data['action'] ];
235
+			$hook_suffix = $pagenow;
236
+		}
237
+	}
238
+
239
+
240
+	/**
241
+	 * This method is used to register additional autosave containers to the _autosave_containers property.
242
+	 *
243
+	 * @todo We should automate this at some point by creating a wrapper for add_post_metabox and in our wrapper we
244
+	 *       automatically register the id for the post metabox as a container.
245
+	 * @param  array $ids an array of ids for containers that hold form inputs we want autosave to pickup.  Typically
246
+	 *                    you would send along the id of a metabox container.
247
+	 * @return void
248
+	 */
249
+	protected function _register_autosave_containers($ids)
250
+	{
251
+		$this->_autosave_containers = array_merge($this->_autosave_fields, (array) $ids);
252
+	}
253
+
254
+
255
+	/**
256
+	 * Something nifty.  We're going to loop through all the registered metaboxes and if the CALLBACK is an instance of
257
+	 * EE_Admin_Page OR EE_Admin_Hooks, then we'll add the id to our _autosave_containers array.
258
+	 */
259
+	protected function _set_autosave_containers()
260
+	{
261
+		global $wp_meta_boxes;
262
+		$containers = array();
263
+		if (empty($wp_meta_boxes)) {
264
+			return;
265
+		}
266
+		$current_metaboxes = isset($wp_meta_boxes[ $this->page_slug ]) ? $wp_meta_boxes[ $this->page_slug ] : array();
267
+		foreach ($current_metaboxes as $box_context) {
268
+			foreach ($box_context as $box_details) {
269
+				foreach ($box_details as $box) {
270
+					if (is_array($box) && is_array($box['callback'])
271
+						&& (
272
+							$box['callback'][0] instanceof EE_Admin_Page
273
+							|| $box['callback'][0] instanceof EE_Admin_Hooks
274
+						)
275
+					) {
276
+						$containers[] = $box['id'];
277
+					}
278
+				}
279
+			}
280
+		}
281
+		$this->_autosave_containers = array_merge($this->_autosave_containers, $containers);
282
+		// add hidden inputs container
283
+		$this->_autosave_containers[] = 'ee-cpt-hidden-inputs';
284
+	}
285
+
286
+
287
+	protected function _load_autosave_scripts_styles()
288
+	{
289
+		/*wp_register_script('cpt-autosave', EE_ADMIN_URL . 'assets/ee-cpt-autosave.js', array('ee-serialize-full-array', 'event_editor_js'), EVENT_ESPRESSO_VERSION, TRUE );
290 290
         wp_enqueue_script('cpt-autosave');/**/ // todo re-enable when we start doing autosave again in 4.2
291 291
 
292
-        // filter _autosave_containers
293
-        $containers = apply_filters(
294
-            'FHEE__EE_Admin_Page_CPT___load_autosave_scripts_styles__containers',
295
-            $this->_autosave_containers,
296
-            $this
297
-        );
298
-        $containers = apply_filters(
299
-            'FHEE__EE_Admin_Page_CPT__' . get_class($this) . '___load_autosave_scripts_styles__containers',
300
-            $containers,
301
-            $this
302
-        );
303
-
304
-        wp_localize_script(
305
-            'event_editor_js',
306
-            'EE_AUTOSAVE_IDS',
307
-            $containers
308
-        ); // todo once we enable autosaves, this needs to be switched to localize with "cpt-autosave"
309
-
310
-        $unsaved_data_msg = array(
311
-            'eventmsg'     => sprintf(
312
-                __(
313
-                    "The changes you made to this %s will be lost if you navigate away from this page.",
314
-                    'event_espresso'
315
-                ),
316
-                $this->_cpt_object->labels->singular_name
317
-            ),
318
-            'inputChanged' => 0,
319
-        );
320
-        wp_localize_script('event_editor_js', 'UNSAVED_DATA_MSG', $unsaved_data_msg);
321
-    }
322
-
323
-
324
-    public function load_page_dependencies()
325
-    {
326
-        try {
327
-            $this->_load_page_dependencies();
328
-        } catch (EE_Error $e) {
329
-            $e->get_error();
330
-        }
331
-    }
332
-
333
-
334
-    /**
335
-     * overloading the EE_Admin_Page parent load_page_dependencies so we can get the cpt stuff added in appropriately
336
-     *
337
-     * @access protected
338
-     * @return void
339
-     */
340
-    protected function _load_page_dependencies()
341
-    {
342
-        // we only add stuff if this is a cpt_route!
343
-        if (! $this->_cpt_route) {
344
-            parent::_load_page_dependencies();
345
-            return;
346
-        }
347
-        // now let's do some automatic filters into the wp_system
348
-        // and we'll check to make sure the CHILD class
349
-        // automatically has the required methods in place.
350
-        // the following filters are for setting all the redirects
351
-        // on DEFAULT WP custom post type actions
352
-        // let's add a hidden input to the post-edit form
353
-        // so we know when we have to trigger our custom redirects!
354
-        // Otherwise the redirects will happen on ALL post saves which wouldn't be good of course!
355
-        add_action('edit_form_after_title', array($this, 'cpt_post_form_hidden_input'));
356
-        // inject our Admin page nav tabs...
357
-        // let's make sure the nav tabs are set if they aren't already
358
-        // if ( empty( $this->_nav_tabs ) ) $this->_set_nav_tabs();
359
-        add_action('post_edit_form_tag', array($this, 'inject_nav_tabs'));
360
-        // modify the post_updated messages array
361
-        add_action('post_updated_messages', array($this, 'post_update_messages'), 10);
362
-        // add shortlink button to cpt edit screens.  We can do this as a universal thing BECAUSE,
363
-        // cpts use the same format for shortlinks as posts!
364
-        add_filter('pre_get_shortlink', array($this, 'add_shortlink_button_to_editor'), 10, 4);
365
-        // This basically allows us to change the title of the "publish" metabox area
366
-        // on CPT pages by setting a 'publishbox' value in the $_labels property array in the child class.
367
-        if (! empty($this->_labels['publishbox'])) {
368
-            $box_label = is_array($this->_labels['publishbox'])
369
-                         && isset($this->_labels['publishbox'][ $this->_req_action ])
370
-                ? $this->_labels['publishbox'][ $this->_req_action ]
371
-                : $this->_labels['publishbox'];
372
-            add_meta_box(
373
-                'submitdiv',
374
-                $box_label,
375
-                'post_submit_meta_box',
376
-                $this->_cpt_routes[ $this->_req_action ],
377
-                'side',
378
-                'core'
379
-            );
380
-        }
381
-        // let's add page_templates metabox if this cpt added support for it.
382
-        if ($this->_supports_page_templates($this->_cpt_object->name)) {
383
-            add_meta_box(
384
-                'page_templates',
385
-                __('Page Template', 'event_espresso'),
386
-                array($this, 'page_template_meta_box'),
387
-                $this->_cpt_routes[ $this->_req_action ],
388
-                'side',
389
-                'default'
390
-            );
391
-        }
392
-        // this is a filter that allows the addition of extra html after the permalink field on the wp post edit-form
393
-        if (method_exists($this, 'extra_permalink_field_buttons')) {
394
-            add_filter('get_sample_permalink_html', array($this, 'extra_permalink_field_buttons'), 10, 4);
395
-        }
396
-        // add preview button
397
-        add_filter('get_sample_permalink_html', array($this, 'preview_button_html'), 5, 4);
398
-        // insert our own post_stati dropdown
399
-        add_action('post_submitbox_misc_actions', array($this, 'custom_post_stati_dropdown'), 10);
400
-        // This allows adding additional information to the publish post submitbox on the wp post edit form
401
-        if (method_exists($this, 'extra_misc_actions_publish_box')) {
402
-            add_action('post_submitbox_misc_actions', array($this, 'extra_misc_actions_publish_box'), 10);
403
-        }
404
-        // This allows for adding additional stuff after the title field on the wp post edit form.
405
-        // This is also before the wp_editor for post description field.
406
-        if (method_exists($this, 'edit_form_after_title')) {
407
-            add_action('edit_form_after_title', array($this, 'edit_form_after_title'), 10);
408
-        }
409
-        /**
410
-         * Filtering WP's esc_url to capture urls pointing to core wp routes so they point to our route.
411
-         */
412
-        add_filter('clean_url', array($this, 'switch_core_wp_urls_with_ours'), 10, 3);
413
-        parent::_load_page_dependencies();
414
-        // notice we are ALSO going to load the pagenow hook set for this route
415
-        // (see _before_page_setup for the reset of the pagenow global ).
416
-        // This is for any plugins that are doing things properly
417
-        // and hooking into the load page hook for core wp cpt routes.
418
-        global $pagenow;
419
-        add_action('load-' . $pagenow, array($this, 'modify_current_screen'), 20);
420
-        do_action('load-' . $pagenow);
421
-        add_action('admin_enqueue_scripts', array($this, 'setup_autosave_hooks'), 30);
422
-        // we route REALLY early.
423
-        try {
424
-            $this->_route_admin_request();
425
-        } catch (EE_Error $e) {
426
-            $e->get_error();
427
-        }
428
-    }
429
-
430
-
431
-    /**
432
-     * Since we don't want users going to default core wp routes, this will check any wp urls run through the
433
-     * esc_url() method and if we see a url matching a pattern for our routes, we'll modify it to point to OUR
434
-     * route instead.
435
-     *
436
-     * @param string $good_protocol_url The escaped url.
437
-     * @param string $original_url      The original url.
438
-     * @param string $_context          The context sent to the esc_url method.
439
-     * @return string possibly a new url for our route.
440
-     */
441
-    public function switch_core_wp_urls_with_ours($good_protocol_url, $original_url, $_context)
442
-    {
443
-        $routes_to_match = array(
444
-            0 => array(
445
-                'edit.php?post_type=espresso_attendees',
446
-                'admin.php?page=espresso_registrations&action=contact_list',
447
-            ),
448
-            1 => array(
449
-                'edit.php?post_type=' . $this->_cpt_object->name,
450
-                'admin.php?page=' . $this->_cpt_object->name,
451
-            ),
452
-        );
453
-        foreach ($routes_to_match as $route_matches) {
454
-            if (strpos($good_protocol_url, $route_matches[0]) !== false) {
455
-                return str_replace($route_matches[0], $route_matches[1], $good_protocol_url);
456
-            }
457
-        }
458
-        return $good_protocol_url;
459
-    }
460
-
461
-
462
-    /**
463
-     * Determine whether the current cpt supports page templates or not.
464
-     *
465
-     * @since %VER%
466
-     * @param string $cpt_name The cpt slug we're checking on.
467
-     * @return bool True supported, false not.
468
-     * @throws InvalidArgumentException
469
-     * @throws InvalidDataTypeException
470
-     * @throws InvalidInterfaceException
471
-     */
472
-    private function _supports_page_templates($cpt_name)
473
-    {
474
-        /** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_types */
475
-        $custom_post_types = $this->getLoader()->getShared(
476
-            'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
477
-        );
478
-        $cpt_args = $custom_post_types->getDefinitions();
479
-        $cpt_args = isset($cpt_args[ $cpt_name ]) ? $cpt_args[ $cpt_name ]['args'] : array();
480
-        $cpt_has_support = ! empty($cpt_args['page_templates']);
481
-
482
-        // if the installed version of WP is > 4.7 we do some additional checks.
483
-        if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
484
-            $post_templates = wp_get_theme()->get_post_templates();
485
-            // if there are $post_templates for this cpt, then we return false for this method because
486
-            // that means we aren't going to load our page template manager and leave that up to the native
487
-            // cpt template manager.
488
-            $cpt_has_support = ! isset($post_templates[ $cpt_name ]) ? $cpt_has_support : false;
489
-        }
490
-
491
-        return $cpt_has_support;
492
-    }
493
-
494
-
495
-    /**
496
-     * Callback for the page_templates metabox selector.
497
-     *
498
-     * @since %VER%
499
-     * @return void
500
-     */
501
-    public function page_template_meta_box()
502
-    {
503
-        global $post;
504
-        $template = '';
505
-
506
-        if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
507
-            $page_template_count = count(get_page_templates());
508
-        } else {
509
-            $page_template_count = count(get_page_templates($post));
510
-        };
511
-
512
-        if ($page_template_count) {
513
-            $page_template = get_post_meta($post->ID, '_wp_page_template', true);
514
-            $template = ! empty($page_template) ? $page_template : '';
515
-        }
516
-        ?>
292
+		// filter _autosave_containers
293
+		$containers = apply_filters(
294
+			'FHEE__EE_Admin_Page_CPT___load_autosave_scripts_styles__containers',
295
+			$this->_autosave_containers,
296
+			$this
297
+		);
298
+		$containers = apply_filters(
299
+			'FHEE__EE_Admin_Page_CPT__' . get_class($this) . '___load_autosave_scripts_styles__containers',
300
+			$containers,
301
+			$this
302
+		);
303
+
304
+		wp_localize_script(
305
+			'event_editor_js',
306
+			'EE_AUTOSAVE_IDS',
307
+			$containers
308
+		); // todo once we enable autosaves, this needs to be switched to localize with "cpt-autosave"
309
+
310
+		$unsaved_data_msg = array(
311
+			'eventmsg'     => sprintf(
312
+				__(
313
+					"The changes you made to this %s will be lost if you navigate away from this page.",
314
+					'event_espresso'
315
+				),
316
+				$this->_cpt_object->labels->singular_name
317
+			),
318
+			'inputChanged' => 0,
319
+		);
320
+		wp_localize_script('event_editor_js', 'UNSAVED_DATA_MSG', $unsaved_data_msg);
321
+	}
322
+
323
+
324
+	public function load_page_dependencies()
325
+	{
326
+		try {
327
+			$this->_load_page_dependencies();
328
+		} catch (EE_Error $e) {
329
+			$e->get_error();
330
+		}
331
+	}
332
+
333
+
334
+	/**
335
+	 * overloading the EE_Admin_Page parent load_page_dependencies so we can get the cpt stuff added in appropriately
336
+	 *
337
+	 * @access protected
338
+	 * @return void
339
+	 */
340
+	protected function _load_page_dependencies()
341
+	{
342
+		// we only add stuff if this is a cpt_route!
343
+		if (! $this->_cpt_route) {
344
+			parent::_load_page_dependencies();
345
+			return;
346
+		}
347
+		// now let's do some automatic filters into the wp_system
348
+		// and we'll check to make sure the CHILD class
349
+		// automatically has the required methods in place.
350
+		// the following filters are for setting all the redirects
351
+		// on DEFAULT WP custom post type actions
352
+		// let's add a hidden input to the post-edit form
353
+		// so we know when we have to trigger our custom redirects!
354
+		// Otherwise the redirects will happen on ALL post saves which wouldn't be good of course!
355
+		add_action('edit_form_after_title', array($this, 'cpt_post_form_hidden_input'));
356
+		// inject our Admin page nav tabs...
357
+		// let's make sure the nav tabs are set if they aren't already
358
+		// if ( empty( $this->_nav_tabs ) ) $this->_set_nav_tabs();
359
+		add_action('post_edit_form_tag', array($this, 'inject_nav_tabs'));
360
+		// modify the post_updated messages array
361
+		add_action('post_updated_messages', array($this, 'post_update_messages'), 10);
362
+		// add shortlink button to cpt edit screens.  We can do this as a universal thing BECAUSE,
363
+		// cpts use the same format for shortlinks as posts!
364
+		add_filter('pre_get_shortlink', array($this, 'add_shortlink_button_to_editor'), 10, 4);
365
+		// This basically allows us to change the title of the "publish" metabox area
366
+		// on CPT pages by setting a 'publishbox' value in the $_labels property array in the child class.
367
+		if (! empty($this->_labels['publishbox'])) {
368
+			$box_label = is_array($this->_labels['publishbox'])
369
+						 && isset($this->_labels['publishbox'][ $this->_req_action ])
370
+				? $this->_labels['publishbox'][ $this->_req_action ]
371
+				: $this->_labels['publishbox'];
372
+			add_meta_box(
373
+				'submitdiv',
374
+				$box_label,
375
+				'post_submit_meta_box',
376
+				$this->_cpt_routes[ $this->_req_action ],
377
+				'side',
378
+				'core'
379
+			);
380
+		}
381
+		// let's add page_templates metabox if this cpt added support for it.
382
+		if ($this->_supports_page_templates($this->_cpt_object->name)) {
383
+			add_meta_box(
384
+				'page_templates',
385
+				__('Page Template', 'event_espresso'),
386
+				array($this, 'page_template_meta_box'),
387
+				$this->_cpt_routes[ $this->_req_action ],
388
+				'side',
389
+				'default'
390
+			);
391
+		}
392
+		// this is a filter that allows the addition of extra html after the permalink field on the wp post edit-form
393
+		if (method_exists($this, 'extra_permalink_field_buttons')) {
394
+			add_filter('get_sample_permalink_html', array($this, 'extra_permalink_field_buttons'), 10, 4);
395
+		}
396
+		// add preview button
397
+		add_filter('get_sample_permalink_html', array($this, 'preview_button_html'), 5, 4);
398
+		// insert our own post_stati dropdown
399
+		add_action('post_submitbox_misc_actions', array($this, 'custom_post_stati_dropdown'), 10);
400
+		// This allows adding additional information to the publish post submitbox on the wp post edit form
401
+		if (method_exists($this, 'extra_misc_actions_publish_box')) {
402
+			add_action('post_submitbox_misc_actions', array($this, 'extra_misc_actions_publish_box'), 10);
403
+		}
404
+		// This allows for adding additional stuff after the title field on the wp post edit form.
405
+		// This is also before the wp_editor for post description field.
406
+		if (method_exists($this, 'edit_form_after_title')) {
407
+			add_action('edit_form_after_title', array($this, 'edit_form_after_title'), 10);
408
+		}
409
+		/**
410
+		 * Filtering WP's esc_url to capture urls pointing to core wp routes so they point to our route.
411
+		 */
412
+		add_filter('clean_url', array($this, 'switch_core_wp_urls_with_ours'), 10, 3);
413
+		parent::_load_page_dependencies();
414
+		// notice we are ALSO going to load the pagenow hook set for this route
415
+		// (see _before_page_setup for the reset of the pagenow global ).
416
+		// This is for any plugins that are doing things properly
417
+		// and hooking into the load page hook for core wp cpt routes.
418
+		global $pagenow;
419
+		add_action('load-' . $pagenow, array($this, 'modify_current_screen'), 20);
420
+		do_action('load-' . $pagenow);
421
+		add_action('admin_enqueue_scripts', array($this, 'setup_autosave_hooks'), 30);
422
+		// we route REALLY early.
423
+		try {
424
+			$this->_route_admin_request();
425
+		} catch (EE_Error $e) {
426
+			$e->get_error();
427
+		}
428
+	}
429
+
430
+
431
+	/**
432
+	 * Since we don't want users going to default core wp routes, this will check any wp urls run through the
433
+	 * esc_url() method and if we see a url matching a pattern for our routes, we'll modify it to point to OUR
434
+	 * route instead.
435
+	 *
436
+	 * @param string $good_protocol_url The escaped url.
437
+	 * @param string $original_url      The original url.
438
+	 * @param string $_context          The context sent to the esc_url method.
439
+	 * @return string possibly a new url for our route.
440
+	 */
441
+	public function switch_core_wp_urls_with_ours($good_protocol_url, $original_url, $_context)
442
+	{
443
+		$routes_to_match = array(
444
+			0 => array(
445
+				'edit.php?post_type=espresso_attendees',
446
+				'admin.php?page=espresso_registrations&action=contact_list',
447
+			),
448
+			1 => array(
449
+				'edit.php?post_type=' . $this->_cpt_object->name,
450
+				'admin.php?page=' . $this->_cpt_object->name,
451
+			),
452
+		);
453
+		foreach ($routes_to_match as $route_matches) {
454
+			if (strpos($good_protocol_url, $route_matches[0]) !== false) {
455
+				return str_replace($route_matches[0], $route_matches[1], $good_protocol_url);
456
+			}
457
+		}
458
+		return $good_protocol_url;
459
+	}
460
+
461
+
462
+	/**
463
+	 * Determine whether the current cpt supports page templates or not.
464
+	 *
465
+	 * @since %VER%
466
+	 * @param string $cpt_name The cpt slug we're checking on.
467
+	 * @return bool True supported, false not.
468
+	 * @throws InvalidArgumentException
469
+	 * @throws InvalidDataTypeException
470
+	 * @throws InvalidInterfaceException
471
+	 */
472
+	private function _supports_page_templates($cpt_name)
473
+	{
474
+		/** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_types */
475
+		$custom_post_types = $this->getLoader()->getShared(
476
+			'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
477
+		);
478
+		$cpt_args = $custom_post_types->getDefinitions();
479
+		$cpt_args = isset($cpt_args[ $cpt_name ]) ? $cpt_args[ $cpt_name ]['args'] : array();
480
+		$cpt_has_support = ! empty($cpt_args['page_templates']);
481
+
482
+		// if the installed version of WP is > 4.7 we do some additional checks.
483
+		if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
484
+			$post_templates = wp_get_theme()->get_post_templates();
485
+			// if there are $post_templates for this cpt, then we return false for this method because
486
+			// that means we aren't going to load our page template manager and leave that up to the native
487
+			// cpt template manager.
488
+			$cpt_has_support = ! isset($post_templates[ $cpt_name ]) ? $cpt_has_support : false;
489
+		}
490
+
491
+		return $cpt_has_support;
492
+	}
493
+
494
+
495
+	/**
496
+	 * Callback for the page_templates metabox selector.
497
+	 *
498
+	 * @since %VER%
499
+	 * @return void
500
+	 */
501
+	public function page_template_meta_box()
502
+	{
503
+		global $post;
504
+		$template = '';
505
+
506
+		if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
507
+			$page_template_count = count(get_page_templates());
508
+		} else {
509
+			$page_template_count = count(get_page_templates($post));
510
+		};
511
+
512
+		if ($page_template_count) {
513
+			$page_template = get_post_meta($post->ID, '_wp_page_template', true);
514
+			$template = ! empty($page_template) ? $page_template : '';
515
+		}
516
+		?>
517 517
         <p><strong><?php _e('Template', 'event_espresso') ?></strong></p>
518 518
         <label class="screen-reader-text" for="page_template"><?php _e('Page Template', 'event_espresso') ?></label><select
519 519
         name="page_template" id="page_template">
@@ -521,468 +521,468 @@  discard block
 block discarded – undo
521 521
         <?php page_template_dropdown($template); ?>
522 522
     </select>
523 523
         <?php
524
-    }
525
-
526
-
527
-    /**
528
-     * if this post is a draft or scheduled post then we provide a preview button for user to click
529
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
530
-     *
531
-     * @param  string $return    the current html
532
-     * @param  int    $id        the post id for the page
533
-     * @param  string $new_title What the title is
534
-     * @param  string $new_slug  what the slug is
535
-     * @return string            The new html string for the permalink area
536
-     */
537
-    public function preview_button_html($return, $id, $new_title, $new_slug)
538
-    {
539
-        $post = get_post($id);
540
-        if ('publish' !== get_post_status($post)) {
541
-            $return .= '<span_id="view-post-btn"><a target="_blank" href="'
542
-                       . get_preview_post_link($id)
543
-                       . '" class="button button-small">'
544
-                       . __('Preview', 'event_espresso')
545
-                       . '</a></span>'
546
-                       . "\n";
547
-        }
548
-        return $return;
549
-    }
550
-
551
-
552
-    /**
553
-     * add our custom post stati dropdown on the wp post page for this cpt
554
-     *
555
-     * @return void
556
-     */
557
-    public function custom_post_stati_dropdown()
558
-    {
559
-
560
-        $statuses = $this->_cpt_model_obj->get_custom_post_statuses();
561
-        $cur_status_label = array_key_exists($this->_cpt_model_obj->status(), $statuses)
562
-            ? $statuses[ $this->_cpt_model_obj->status() ]
563
-            : '';
564
-        $template_args = array(
565
-            'cur_status'            => $this->_cpt_model_obj->status(),
566
-            'statuses'              => $statuses,
567
-            'cur_status_label'      => $cur_status_label,
568
-            'localized_status_save' => sprintf(__('Save %s', 'event_espresso'), $cur_status_label),
569
-        );
570
-        // we'll add a trash post status (WP doesn't add one for some reason)
571
-        if ($this->_cpt_model_obj->status() === 'trash') {
572
-            $template_args['cur_status_label'] = __('Trashed', 'event_espresso');
573
-            $statuses['trash'] = __('Trashed', 'event_espresso');
574
-            $template_args['statuses'] = $statuses;
575
-        }
576
-
577
-        $template = EE_ADMIN_TEMPLATE . 'status_dropdown.template.php';
578
-        EEH_Template::display_template($template, $template_args);
579
-    }
580
-
581
-
582
-    public function setup_autosave_hooks()
583
-    {
584
-        $this->_set_autosave_containers();
585
-        $this->_load_autosave_scripts_styles();
586
-    }
587
-
588
-
589
-    /**
590
-     * This is run on all WordPress autosaves AFTER the autosave is complete and sends along a $_POST object (available
591
-     * in $this->_req_data) containing: post_ID of the saved post autosavenonce for the saved post We'll do the check
592
-     * for the nonce in here, but then this method looks for two things:
593
-     * 1. Execute a method (if exists) matching 'ee_autosave_' and appended with the given route. OR
594
-     * 2. do_actions() for global or class specific actions that have been registered (for plugins/addons not in an
595
-     * EE_Admin_Page class. PLEASE NOTE: Data will be returned using the _return_json() object and so the
596
-     * $_template_args property should be used to hold the $data array.  We're expecting the following things set in
597
-     * template args.
598
-     *    1. $template_args['error'] = IF there is an error you can add the message in here.
599
-     *    2. $template_args['data']['items'] = an array of items that are setup in key index pairs of 'where_values_go'
600
-     *    => 'values_to_add'.  In other words, for the datetime metabox we'll have something like
601
-     *    $this->_template_args['data']['items'] = array(
602
-     *        'event-datetime-ids' => '1,2,3';
603
-     *    );
604
-     *    Keep in mind the following things:
605
-     *    - "where" index is for the input with the id as that string.
606
-     *    - "what" index is what will be used for the value of that input.
607
-     *
608
-     * @return void
609
-     */
610
-    public function do_extra_autosave_stuff()
611
-    {
612
-        // next let's check for the autosave nonce (we'll use _verify_nonce )
613
-        $nonce = isset($this->_req_data['autosavenonce'])
614
-            ? $this->_req_data['autosavenonce']
615
-            : null;
616
-        $this->_verify_nonce($nonce, 'autosave');
617
-        // make sure we define doing autosave (cause WP isn't triggering this we want to make sure we define it)
618
-        if (! defined('DOING_AUTOSAVE')) {
619
-            define('DOING_AUTOSAVE', true);
620
-        }
621
-        // if we made it here then the nonce checked out.  Let's run our methods and actions
622
-        $autosave = "_ee_autosave_{$this->_current_view}";
623
-        if (method_exists($this, $autosave)) {
624
-            $this->$autosave();
625
-        } else {
626
-            $this->_template_args['success'] = true;
627
-        }
628
-        do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__global_after', $this);
629
-        do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_' . get_class($this), $this);
630
-        // now let's return json
631
-        $this->_return_json();
632
-    }
633
-
634
-
635
-    /**
636
-     * This takes care of setting up default routes and pages that utilize the core WP admin pages.
637
-     * Child classes can override the defaults (in cases for adding metaboxes etc.)
638
-     * but take care that you include the defaults here otherwise your core WP admin pages for the cpt won't work!
639
-     *
640
-     * @access protected
641
-     * @throws EE_Error
642
-     * @return void
643
-     */
644
-    protected function _extend_page_config_for_cpt()
645
-    {
646
-        // before doing anything we need to make sure this runs ONLY when the loaded page matches the set page_slug
647
-        if (isset($this->_req_data['page']) && $this->_req_data['page'] !== $this->page_slug) {
648
-            return;
649
-        }
650
-        // set page routes and page config but ONLY if we're not viewing a custom setup cpt route as defined in _cpt_routes
651
-        if (! empty($this->_cpt_object)) {
652
-            $this->_page_routes = array_merge(
653
-                array(
654
-                    'create_new' => '_create_new_cpt_item',
655
-                    'edit'       => '_edit_cpt_item',
656
-                ),
657
-                $this->_page_routes
658
-            );
659
-            $this->_page_config = array_merge(
660
-                array(
661
-                    'create_new' => array(
662
-                        'nav'           => array(
663
-                            'label' => $this->_cpt_object->labels->add_new_item,
664
-                            'order' => 5,
665
-                        ),
666
-                        'require_nonce' => false,
667
-                    ),
668
-                    'edit'       => array(
669
-                        'nav'           => array(
670
-                            'label'      => $this->_cpt_object->labels->edit_item,
671
-                            'order'      => 5,
672
-                            'persistent' => false,
673
-                            'url'        => '',
674
-                        ),
675
-                        'require_nonce' => false,
676
-                    ),
677
-                ),
678
-                $this->_page_config
679
-            );
680
-        }
681
-        // load the next section only if this is a matching cpt route as set in the cpt routes array.
682
-        if (! isset($this->_cpt_routes[ $this->_req_action ])) {
683
-            return;
684
-        }
685
-        $this->_cpt_route = isset($this->_cpt_routes[ $this->_req_action ]) ? true : false;
686
-        // add_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', array( $this, 'modify_current_screen') );
687
-        if (empty($this->_cpt_object)) {
688
-            $msg = sprintf(
689
-                __(
690
-                    'This page has been set as being related to a registered custom post type, however, the custom post type object could not be retrieved. There are two possible reasons for this:  1. The "%s" does not match a registered post type. or 2. The custom post type is not registered for the "%s" action as indexed in the "$_cpt_routes" property on this class (%s).',
691
-                    'event_espresso'
692
-                ),
693
-                $this->page_slug,
694
-                $this->_req_action,
695
-                get_class($this)
696
-            );
697
-            throw new EE_Error($msg);
698
-        }
699
-        if ($this->_cpt_route) {
700
-            $id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
701
-            $this->_set_model_object($id);
702
-        }
703
-    }
704
-
705
-
706
-    /**
707
-     * Sets the _cpt_model_object property using what has been set for the _cpt_model_name and a given id.
708
-     *
709
-     * @access protected
710
-     * @param int    $id       The id to retrieve the model object for. If empty we set a default object.
711
-     * @param bool   $ignore_route_check
712
-     * @param string $req_type whether the current route is for inserting, updating, or deleting the CPT
713
-     * @throws EE_Error
714
-     * @throws InvalidArgumentException
715
-     * @throws InvalidDataTypeException
716
-     * @throws InvalidInterfaceException
717
-     * @throws ReflectionException
718
-     */
719
-    protected function _set_model_object($id = null, $ignore_route_check = false, $req_type = '')
720
-    {
721
-        $model = null;
722
-        if (empty($this->_cpt_model_names)
723
-            || (
724
-                ! $ignore_route_check
725
-                && ! isset($this->_cpt_routes[ $this->_req_action ])
726
-            ) || (
727
-                $this->_cpt_model_obj instanceof EE_CPT_Base
728
-                && $this->_cpt_model_obj->ID() === $id
729
-            )
730
-        ) {
731
-            // get out cuz we either don't have a model name OR the object has already been set and it has the same id as what has been sent.
732
-            return;
733
-        }
734
-        // if ignore_route_check is true, then get the model name via CustomPostTypeDefinitions
735
-        if ($ignore_route_check) {
736
-            $post_type = get_post_type($id);
737
-            /** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_types */
738
-            $custom_post_types = $this->getLoader()->getShared(
739
-                'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
740
-            );
741
-            $model_names = $custom_post_types->getCustomPostTypeModelNames($post_type);
742
-            if (isset($model_names[ $post_type ])) {
743
-                $model = EE_Registry::instance()->load_model($model_names[ $post_type ]);
744
-            }
745
-        } else {
746
-            $model = EE_Registry::instance()->load_model($this->_cpt_model_names[ $this->_req_action ]);
747
-        }
748
-        if ($model instanceof EEM_Base) {
749
-            $this->_cpt_model_obj = ! empty($id) ? $model->get_one_by_ID($id) : $model->create_default_object();
750
-        }
751
-        do_action(
752
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
753
-            $this->_cpt_model_obj,
754
-            $req_type
755
-        );
756
-    }
757
-
758
-
759
-    /**
760
-     * admin_init_global
761
-     * This runs all the code that we want executed within the WP admin_init hook.
762
-     * This method executes for ALL EE Admin pages.
763
-     *
764
-     * @access public
765
-     * @return void
766
-     */
767
-    public function admin_init_global()
768
-    {
769
-        $post = isset($this->_req_data['post']) ? get_post($this->_req_data['post']) : null;
770
-        // its possible this is a new save so let's catch that instead
771
-        $post = isset($this->_req_data['post_ID']) ? get_post($this->_req_data['post_ID']) : $post;
772
-        $post_type = $post ? $post->post_type : false;
773
-        $current_route = isset($this->_req_data['current_route'])
774
-            ? $this->_req_data['current_route']
775
-            : 'shouldneverwork';
776
-        $route_to_check = $post_type && isset($this->_cpt_routes[ $current_route ])
777
-            ? $this->_cpt_routes[ $current_route ]
778
-            : '';
779
-        add_filter('get_delete_post_link', array($this, 'modify_delete_post_link'), 10, 3);
780
-        add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 3);
781
-        if ($post_type === $route_to_check) {
782
-            add_filter('redirect_post_location', array($this, 'cpt_post_location_redirect'), 10, 2);
783
-        }
784
-        // now let's filter redirect if we're on a revision page and the revision is for an event CPT.
785
-        $revision = isset($this->_req_data['revision']) ? $this->_req_data['revision'] : null;
786
-        if (! empty($revision)) {
787
-            $action = isset($this->_req_data['action']) ? $this->_req_data['action'] : null;
788
-            // doing a restore?
789
-            if (! empty($action) && $action === 'restore') {
790
-                // get post for revision
791
-                $rev_post = get_post($revision);
792
-                $rev_parent = get_post($rev_post->post_parent);
793
-                // only do our redirect filter AND our restore revision action if the post_type for the parent is one of our cpts.
794
-                if ($rev_parent && $rev_parent->post_type === $this->page_slug) {
795
-                    add_filter('wp_redirect', array($this, 'revision_redirect'), 10, 2);
796
-                    // restores of revisions
797
-                    add_action('wp_restore_post_revision', array($this, 'restore_revision'), 10, 2);
798
-                }
799
-            }
800
-        }
801
-        // NOTE we ONLY want to run these hooks if we're on the right class for the given post type.  Otherwise we could see some really freaky things happen!
802
-        if ($post_type && $post_type === $route_to_check) {
803
-            // $post_id, $post
804
-            add_action('save_post', array($this, 'insert_update'), 10, 3);
805
-            // $post_id
806
-            add_action('trashed_post', array($this, 'before_trash_cpt_item'), 10);
807
-            add_action('trashed_post', array($this, 'dont_permanently_delete_ee_cpts'), 10);
808
-            add_action('untrashed_post', array($this, 'before_restore_cpt_item'), 10);
809
-            add_action('after_delete_post', array($this, 'before_delete_cpt_item'), 10);
810
-        }
811
-    }
812
-
813
-
814
-    /**
815
-     * Callback for the WordPress trashed_post hook.
816
-     * Execute some basic checks before calling the trash_cpt_item declared in the child class.
817
-     *
818
-     * @param int $post_id
819
-     * @throws \EE_Error
820
-     */
821
-    public function before_trash_cpt_item($post_id)
822
-    {
823
-        $this->_set_model_object($post_id, true, 'trash');
824
-        // if our cpt object isn't existent then get out immediately.
825
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
826
-            return;
827
-        }
828
-        $this->trash_cpt_item($post_id);
829
-    }
830
-
831
-
832
-    /**
833
-     * Callback for the WordPress untrashed_post hook.
834
-     * Execute some basic checks before calling the restore_cpt_method in the child class.
835
-     *
836
-     * @param $post_id
837
-     * @throws \EE_Error
838
-     */
839
-    public function before_restore_cpt_item($post_id)
840
-    {
841
-        $this->_set_model_object($post_id, true, 'restore');
842
-        // if our cpt object isn't existent then get out immediately.
843
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
844
-            return;
845
-        }
846
-        $this->restore_cpt_item($post_id);
847
-    }
848
-
849
-
850
-    /**
851
-     * Callback for the WordPress after_delete_post hook.
852
-     * Execute some basic checks before calling the delete_cpt_item method in the child class.
853
-     *
854
-     * @param $post_id
855
-     * @throws \EE_Error
856
-     */
857
-    public function before_delete_cpt_item($post_id)
858
-    {
859
-        $this->_set_model_object($post_id, true, 'delete');
860
-        // if our cpt object isn't existent then get out immediately.
861
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
862
-            return;
863
-        }
864
-        $this->delete_cpt_item($post_id);
865
-    }
866
-
867
-
868
-    /**
869
-     * This simply verifies if the cpt_model_object is instantiated for the given page and throws an error message
870
-     * accordingly.
871
-     *
872
-     * @access public
873
-     * @throws EE_Error
874
-     * @return void
875
-     */
876
-    public function verify_cpt_object()
877
-    {
878
-        $label = ! empty($this->_cpt_object) ? $this->_cpt_object->labels->singular_name : $this->page_label;
879
-        // verify event object
880
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base) {
881
-            throw new EE_Error(
882
-                sprintf(
883
-                    __(
884
-                        'Something has gone wrong with the page load because we are unable to set up the object for the %1$s.  This usually happens when the given id for the page route is NOT for the correct custom post type for this page',
885
-                        'event_espresso'
886
-                    ),
887
-                    $label
888
-                )
889
-            );
890
-        }
891
-        // if auto-draft then throw an error
892
-        if ($this->_cpt_model_obj->get('status') === 'auto-draft') {
893
-            EE_Error::overwrite_errors();
894
-            EE_Error::add_error(
895
-                sprintf(
896
-                    __(
897
-                        'This %1$s was saved without a title, description, or excerpt which means that none of the extra details you added were saved properly.  All autodrafts will show up in the "draft" view of your event list table.  You can delete them from there. Please click the "Add %1$s" button to refresh and restart.',
898
-                        'event_espresso'
899
-                    ),
900
-                    $label
901
-                ),
902
-                __FILE__,
903
-                __FUNCTION__,
904
-                __LINE__
905
-            );
906
-        }
907
-    }
908
-
909
-
910
-    /**
911
-     * admin_footer_scripts_global
912
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
913
-     * will apply on ALL EE_Admin pages.
914
-     *
915
-     * @access public
916
-     * @return void
917
-     */
918
-    public function admin_footer_scripts_global()
919
-    {
920
-        $this->_add_admin_page_ajax_loading_img();
921
-        $this->_add_admin_page_overlay();
922
-    }
923
-
924
-
925
-    /**
926
-     * add in any global scripts for cpt routes
927
-     *
928
-     * @return void
929
-     */
930
-    public function load_global_scripts_styles()
931
-    {
932
-        parent::load_global_scripts_styles();
933
-        if ($this->_cpt_model_obj instanceof EE_CPT_Base) {
934
-            // setup custom post status object for localize script but only if we've got a cpt object
935
-            $statuses = $this->_cpt_model_obj->get_custom_post_statuses();
936
-            if (! empty($statuses)) {
937
-                // get ALL statuses!
938
-                $statuses = $this->_cpt_model_obj->get_all_post_statuses();
939
-                // setup object
940
-                $ee_cpt_statuses = array();
941
-                foreach ($statuses as $status => $label) {
942
-                    $ee_cpt_statuses[ $status ] = array(
943
-                        'label'      => $label,
944
-                        'save_label' => sprintf(__('Save as %s', 'event_espresso'), $label),
945
-                    );
946
-                }
947
-                wp_localize_script('ee_admin_js', 'eeCPTstatuses', $ee_cpt_statuses);
948
-            }
949
-        }
950
-    }
951
-
952
-
953
-    /**
954
-     * This is a wrapper for the insert/update routes for cpt items so we can add things that are common to ALL
955
-     * insert/updates
956
-     *
957
-     * @param  int     $post_id ID of post being updated
958
-     * @param  WP_Post $post    Post object from WP
959
-     * @param  bool    $update  Whether this is an update or a new save.
960
-     * @return void
961
-     * @throws \EE_Error
962
-     */
963
-    public function insert_update($post_id, $post, $update)
964
-    {
965
-        // make sure that if this is a revision OR trash action that we don't do any updates!
966
-        if (isset($this->_req_data['action'])
967
-            && (
968
-                $this->_req_data['action'] === 'restore'
969
-                || $this->_req_data['action'] === 'trash'
970
-            )
971
-        ) {
972
-            return;
973
-        }
974
-        $this->_set_model_object($post_id, true, 'insert_update');
975
-        // if our cpt object is not instantiated and its NOT the same post_id as what is triggering this callback, then exit.
976
-        if ($update
977
-            && (
978
-                ! $this->_cpt_model_obj instanceof EE_CPT_Base
979
-                || $this->_cpt_model_obj->ID() !== $post_id
980
-            )
981
-        ) {
982
-            return;
983
-        }
984
-        // check for autosave and update our req_data property accordingly.
985
-        /*if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE && isset( $this->_req_data['ee_autosave_data'] ) ) {
524
+	}
525
+
526
+
527
+	/**
528
+	 * if this post is a draft or scheduled post then we provide a preview button for user to click
529
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
530
+	 *
531
+	 * @param  string $return    the current html
532
+	 * @param  int    $id        the post id for the page
533
+	 * @param  string $new_title What the title is
534
+	 * @param  string $new_slug  what the slug is
535
+	 * @return string            The new html string for the permalink area
536
+	 */
537
+	public function preview_button_html($return, $id, $new_title, $new_slug)
538
+	{
539
+		$post = get_post($id);
540
+		if ('publish' !== get_post_status($post)) {
541
+			$return .= '<span_id="view-post-btn"><a target="_blank" href="'
542
+					   . get_preview_post_link($id)
543
+					   . '" class="button button-small">'
544
+					   . __('Preview', 'event_espresso')
545
+					   . '</a></span>'
546
+					   . "\n";
547
+		}
548
+		return $return;
549
+	}
550
+
551
+
552
+	/**
553
+	 * add our custom post stati dropdown on the wp post page for this cpt
554
+	 *
555
+	 * @return void
556
+	 */
557
+	public function custom_post_stati_dropdown()
558
+	{
559
+
560
+		$statuses = $this->_cpt_model_obj->get_custom_post_statuses();
561
+		$cur_status_label = array_key_exists($this->_cpt_model_obj->status(), $statuses)
562
+			? $statuses[ $this->_cpt_model_obj->status() ]
563
+			: '';
564
+		$template_args = array(
565
+			'cur_status'            => $this->_cpt_model_obj->status(),
566
+			'statuses'              => $statuses,
567
+			'cur_status_label'      => $cur_status_label,
568
+			'localized_status_save' => sprintf(__('Save %s', 'event_espresso'), $cur_status_label),
569
+		);
570
+		// we'll add a trash post status (WP doesn't add one for some reason)
571
+		if ($this->_cpt_model_obj->status() === 'trash') {
572
+			$template_args['cur_status_label'] = __('Trashed', 'event_espresso');
573
+			$statuses['trash'] = __('Trashed', 'event_espresso');
574
+			$template_args['statuses'] = $statuses;
575
+		}
576
+
577
+		$template = EE_ADMIN_TEMPLATE . 'status_dropdown.template.php';
578
+		EEH_Template::display_template($template, $template_args);
579
+	}
580
+
581
+
582
+	public function setup_autosave_hooks()
583
+	{
584
+		$this->_set_autosave_containers();
585
+		$this->_load_autosave_scripts_styles();
586
+	}
587
+
588
+
589
+	/**
590
+	 * This is run on all WordPress autosaves AFTER the autosave is complete and sends along a $_POST object (available
591
+	 * in $this->_req_data) containing: post_ID of the saved post autosavenonce for the saved post We'll do the check
592
+	 * for the nonce in here, but then this method looks for two things:
593
+	 * 1. Execute a method (if exists) matching 'ee_autosave_' and appended with the given route. OR
594
+	 * 2. do_actions() for global or class specific actions that have been registered (for plugins/addons not in an
595
+	 * EE_Admin_Page class. PLEASE NOTE: Data will be returned using the _return_json() object and so the
596
+	 * $_template_args property should be used to hold the $data array.  We're expecting the following things set in
597
+	 * template args.
598
+	 *    1. $template_args['error'] = IF there is an error you can add the message in here.
599
+	 *    2. $template_args['data']['items'] = an array of items that are setup in key index pairs of 'where_values_go'
600
+	 *    => 'values_to_add'.  In other words, for the datetime metabox we'll have something like
601
+	 *    $this->_template_args['data']['items'] = array(
602
+	 *        'event-datetime-ids' => '1,2,3';
603
+	 *    );
604
+	 *    Keep in mind the following things:
605
+	 *    - "where" index is for the input with the id as that string.
606
+	 *    - "what" index is what will be used for the value of that input.
607
+	 *
608
+	 * @return void
609
+	 */
610
+	public function do_extra_autosave_stuff()
611
+	{
612
+		// next let's check for the autosave nonce (we'll use _verify_nonce )
613
+		$nonce = isset($this->_req_data['autosavenonce'])
614
+			? $this->_req_data['autosavenonce']
615
+			: null;
616
+		$this->_verify_nonce($nonce, 'autosave');
617
+		// make sure we define doing autosave (cause WP isn't triggering this we want to make sure we define it)
618
+		if (! defined('DOING_AUTOSAVE')) {
619
+			define('DOING_AUTOSAVE', true);
620
+		}
621
+		// if we made it here then the nonce checked out.  Let's run our methods and actions
622
+		$autosave = "_ee_autosave_{$this->_current_view}";
623
+		if (method_exists($this, $autosave)) {
624
+			$this->$autosave();
625
+		} else {
626
+			$this->_template_args['success'] = true;
627
+		}
628
+		do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__global_after', $this);
629
+		do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_' . get_class($this), $this);
630
+		// now let's return json
631
+		$this->_return_json();
632
+	}
633
+
634
+
635
+	/**
636
+	 * This takes care of setting up default routes and pages that utilize the core WP admin pages.
637
+	 * Child classes can override the defaults (in cases for adding metaboxes etc.)
638
+	 * but take care that you include the defaults here otherwise your core WP admin pages for the cpt won't work!
639
+	 *
640
+	 * @access protected
641
+	 * @throws EE_Error
642
+	 * @return void
643
+	 */
644
+	protected function _extend_page_config_for_cpt()
645
+	{
646
+		// before doing anything we need to make sure this runs ONLY when the loaded page matches the set page_slug
647
+		if (isset($this->_req_data['page']) && $this->_req_data['page'] !== $this->page_slug) {
648
+			return;
649
+		}
650
+		// set page routes and page config but ONLY if we're not viewing a custom setup cpt route as defined in _cpt_routes
651
+		if (! empty($this->_cpt_object)) {
652
+			$this->_page_routes = array_merge(
653
+				array(
654
+					'create_new' => '_create_new_cpt_item',
655
+					'edit'       => '_edit_cpt_item',
656
+				),
657
+				$this->_page_routes
658
+			);
659
+			$this->_page_config = array_merge(
660
+				array(
661
+					'create_new' => array(
662
+						'nav'           => array(
663
+							'label' => $this->_cpt_object->labels->add_new_item,
664
+							'order' => 5,
665
+						),
666
+						'require_nonce' => false,
667
+					),
668
+					'edit'       => array(
669
+						'nav'           => array(
670
+							'label'      => $this->_cpt_object->labels->edit_item,
671
+							'order'      => 5,
672
+							'persistent' => false,
673
+							'url'        => '',
674
+						),
675
+						'require_nonce' => false,
676
+					),
677
+				),
678
+				$this->_page_config
679
+			);
680
+		}
681
+		// load the next section only if this is a matching cpt route as set in the cpt routes array.
682
+		if (! isset($this->_cpt_routes[ $this->_req_action ])) {
683
+			return;
684
+		}
685
+		$this->_cpt_route = isset($this->_cpt_routes[ $this->_req_action ]) ? true : false;
686
+		// add_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', array( $this, 'modify_current_screen') );
687
+		if (empty($this->_cpt_object)) {
688
+			$msg = sprintf(
689
+				__(
690
+					'This page has been set as being related to a registered custom post type, however, the custom post type object could not be retrieved. There are two possible reasons for this:  1. The "%s" does not match a registered post type. or 2. The custom post type is not registered for the "%s" action as indexed in the "$_cpt_routes" property on this class (%s).',
691
+					'event_espresso'
692
+				),
693
+				$this->page_slug,
694
+				$this->_req_action,
695
+				get_class($this)
696
+			);
697
+			throw new EE_Error($msg);
698
+		}
699
+		if ($this->_cpt_route) {
700
+			$id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
701
+			$this->_set_model_object($id);
702
+		}
703
+	}
704
+
705
+
706
+	/**
707
+	 * Sets the _cpt_model_object property using what has been set for the _cpt_model_name and a given id.
708
+	 *
709
+	 * @access protected
710
+	 * @param int    $id       The id to retrieve the model object for. If empty we set a default object.
711
+	 * @param bool   $ignore_route_check
712
+	 * @param string $req_type whether the current route is for inserting, updating, or deleting the CPT
713
+	 * @throws EE_Error
714
+	 * @throws InvalidArgumentException
715
+	 * @throws InvalidDataTypeException
716
+	 * @throws InvalidInterfaceException
717
+	 * @throws ReflectionException
718
+	 */
719
+	protected function _set_model_object($id = null, $ignore_route_check = false, $req_type = '')
720
+	{
721
+		$model = null;
722
+		if (empty($this->_cpt_model_names)
723
+			|| (
724
+				! $ignore_route_check
725
+				&& ! isset($this->_cpt_routes[ $this->_req_action ])
726
+			) || (
727
+				$this->_cpt_model_obj instanceof EE_CPT_Base
728
+				&& $this->_cpt_model_obj->ID() === $id
729
+			)
730
+		) {
731
+			// get out cuz we either don't have a model name OR the object has already been set and it has the same id as what has been sent.
732
+			return;
733
+		}
734
+		// if ignore_route_check is true, then get the model name via CustomPostTypeDefinitions
735
+		if ($ignore_route_check) {
736
+			$post_type = get_post_type($id);
737
+			/** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_types */
738
+			$custom_post_types = $this->getLoader()->getShared(
739
+				'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
740
+			);
741
+			$model_names = $custom_post_types->getCustomPostTypeModelNames($post_type);
742
+			if (isset($model_names[ $post_type ])) {
743
+				$model = EE_Registry::instance()->load_model($model_names[ $post_type ]);
744
+			}
745
+		} else {
746
+			$model = EE_Registry::instance()->load_model($this->_cpt_model_names[ $this->_req_action ]);
747
+		}
748
+		if ($model instanceof EEM_Base) {
749
+			$this->_cpt_model_obj = ! empty($id) ? $model->get_one_by_ID($id) : $model->create_default_object();
750
+		}
751
+		do_action(
752
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
753
+			$this->_cpt_model_obj,
754
+			$req_type
755
+		);
756
+	}
757
+
758
+
759
+	/**
760
+	 * admin_init_global
761
+	 * This runs all the code that we want executed within the WP admin_init hook.
762
+	 * This method executes for ALL EE Admin pages.
763
+	 *
764
+	 * @access public
765
+	 * @return void
766
+	 */
767
+	public function admin_init_global()
768
+	{
769
+		$post = isset($this->_req_data['post']) ? get_post($this->_req_data['post']) : null;
770
+		// its possible this is a new save so let's catch that instead
771
+		$post = isset($this->_req_data['post_ID']) ? get_post($this->_req_data['post_ID']) : $post;
772
+		$post_type = $post ? $post->post_type : false;
773
+		$current_route = isset($this->_req_data['current_route'])
774
+			? $this->_req_data['current_route']
775
+			: 'shouldneverwork';
776
+		$route_to_check = $post_type && isset($this->_cpt_routes[ $current_route ])
777
+			? $this->_cpt_routes[ $current_route ]
778
+			: '';
779
+		add_filter('get_delete_post_link', array($this, 'modify_delete_post_link'), 10, 3);
780
+		add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 3);
781
+		if ($post_type === $route_to_check) {
782
+			add_filter('redirect_post_location', array($this, 'cpt_post_location_redirect'), 10, 2);
783
+		}
784
+		// now let's filter redirect if we're on a revision page and the revision is for an event CPT.
785
+		$revision = isset($this->_req_data['revision']) ? $this->_req_data['revision'] : null;
786
+		if (! empty($revision)) {
787
+			$action = isset($this->_req_data['action']) ? $this->_req_data['action'] : null;
788
+			// doing a restore?
789
+			if (! empty($action) && $action === 'restore') {
790
+				// get post for revision
791
+				$rev_post = get_post($revision);
792
+				$rev_parent = get_post($rev_post->post_parent);
793
+				// only do our redirect filter AND our restore revision action if the post_type for the parent is one of our cpts.
794
+				if ($rev_parent && $rev_parent->post_type === $this->page_slug) {
795
+					add_filter('wp_redirect', array($this, 'revision_redirect'), 10, 2);
796
+					// restores of revisions
797
+					add_action('wp_restore_post_revision', array($this, 'restore_revision'), 10, 2);
798
+				}
799
+			}
800
+		}
801
+		// NOTE we ONLY want to run these hooks if we're on the right class for the given post type.  Otherwise we could see some really freaky things happen!
802
+		if ($post_type && $post_type === $route_to_check) {
803
+			// $post_id, $post
804
+			add_action('save_post', array($this, 'insert_update'), 10, 3);
805
+			// $post_id
806
+			add_action('trashed_post', array($this, 'before_trash_cpt_item'), 10);
807
+			add_action('trashed_post', array($this, 'dont_permanently_delete_ee_cpts'), 10);
808
+			add_action('untrashed_post', array($this, 'before_restore_cpt_item'), 10);
809
+			add_action('after_delete_post', array($this, 'before_delete_cpt_item'), 10);
810
+		}
811
+	}
812
+
813
+
814
+	/**
815
+	 * Callback for the WordPress trashed_post hook.
816
+	 * Execute some basic checks before calling the trash_cpt_item declared in the child class.
817
+	 *
818
+	 * @param int $post_id
819
+	 * @throws \EE_Error
820
+	 */
821
+	public function before_trash_cpt_item($post_id)
822
+	{
823
+		$this->_set_model_object($post_id, true, 'trash');
824
+		// if our cpt object isn't existent then get out immediately.
825
+		if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
826
+			return;
827
+		}
828
+		$this->trash_cpt_item($post_id);
829
+	}
830
+
831
+
832
+	/**
833
+	 * Callback for the WordPress untrashed_post hook.
834
+	 * Execute some basic checks before calling the restore_cpt_method in the child class.
835
+	 *
836
+	 * @param $post_id
837
+	 * @throws \EE_Error
838
+	 */
839
+	public function before_restore_cpt_item($post_id)
840
+	{
841
+		$this->_set_model_object($post_id, true, 'restore');
842
+		// if our cpt object isn't existent then get out immediately.
843
+		if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
844
+			return;
845
+		}
846
+		$this->restore_cpt_item($post_id);
847
+	}
848
+
849
+
850
+	/**
851
+	 * Callback for the WordPress after_delete_post hook.
852
+	 * Execute some basic checks before calling the delete_cpt_item method in the child class.
853
+	 *
854
+	 * @param $post_id
855
+	 * @throws \EE_Error
856
+	 */
857
+	public function before_delete_cpt_item($post_id)
858
+	{
859
+		$this->_set_model_object($post_id, true, 'delete');
860
+		// if our cpt object isn't existent then get out immediately.
861
+		if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
862
+			return;
863
+		}
864
+		$this->delete_cpt_item($post_id);
865
+	}
866
+
867
+
868
+	/**
869
+	 * This simply verifies if the cpt_model_object is instantiated for the given page and throws an error message
870
+	 * accordingly.
871
+	 *
872
+	 * @access public
873
+	 * @throws EE_Error
874
+	 * @return void
875
+	 */
876
+	public function verify_cpt_object()
877
+	{
878
+		$label = ! empty($this->_cpt_object) ? $this->_cpt_object->labels->singular_name : $this->page_label;
879
+		// verify event object
880
+		if (! $this->_cpt_model_obj instanceof EE_CPT_Base) {
881
+			throw new EE_Error(
882
+				sprintf(
883
+					__(
884
+						'Something has gone wrong with the page load because we are unable to set up the object for the %1$s.  This usually happens when the given id for the page route is NOT for the correct custom post type for this page',
885
+						'event_espresso'
886
+					),
887
+					$label
888
+				)
889
+			);
890
+		}
891
+		// if auto-draft then throw an error
892
+		if ($this->_cpt_model_obj->get('status') === 'auto-draft') {
893
+			EE_Error::overwrite_errors();
894
+			EE_Error::add_error(
895
+				sprintf(
896
+					__(
897
+						'This %1$s was saved without a title, description, or excerpt which means that none of the extra details you added were saved properly.  All autodrafts will show up in the "draft" view of your event list table.  You can delete them from there. Please click the "Add %1$s" button to refresh and restart.',
898
+						'event_espresso'
899
+					),
900
+					$label
901
+				),
902
+				__FILE__,
903
+				__FUNCTION__,
904
+				__LINE__
905
+			);
906
+		}
907
+	}
908
+
909
+
910
+	/**
911
+	 * admin_footer_scripts_global
912
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
913
+	 * will apply on ALL EE_Admin pages.
914
+	 *
915
+	 * @access public
916
+	 * @return void
917
+	 */
918
+	public function admin_footer_scripts_global()
919
+	{
920
+		$this->_add_admin_page_ajax_loading_img();
921
+		$this->_add_admin_page_overlay();
922
+	}
923
+
924
+
925
+	/**
926
+	 * add in any global scripts for cpt routes
927
+	 *
928
+	 * @return void
929
+	 */
930
+	public function load_global_scripts_styles()
931
+	{
932
+		parent::load_global_scripts_styles();
933
+		if ($this->_cpt_model_obj instanceof EE_CPT_Base) {
934
+			// setup custom post status object for localize script but only if we've got a cpt object
935
+			$statuses = $this->_cpt_model_obj->get_custom_post_statuses();
936
+			if (! empty($statuses)) {
937
+				// get ALL statuses!
938
+				$statuses = $this->_cpt_model_obj->get_all_post_statuses();
939
+				// setup object
940
+				$ee_cpt_statuses = array();
941
+				foreach ($statuses as $status => $label) {
942
+					$ee_cpt_statuses[ $status ] = array(
943
+						'label'      => $label,
944
+						'save_label' => sprintf(__('Save as %s', 'event_espresso'), $label),
945
+					);
946
+				}
947
+				wp_localize_script('ee_admin_js', 'eeCPTstatuses', $ee_cpt_statuses);
948
+			}
949
+		}
950
+	}
951
+
952
+
953
+	/**
954
+	 * This is a wrapper for the insert/update routes for cpt items so we can add things that are common to ALL
955
+	 * insert/updates
956
+	 *
957
+	 * @param  int     $post_id ID of post being updated
958
+	 * @param  WP_Post $post    Post object from WP
959
+	 * @param  bool    $update  Whether this is an update or a new save.
960
+	 * @return void
961
+	 * @throws \EE_Error
962
+	 */
963
+	public function insert_update($post_id, $post, $update)
964
+	{
965
+		// make sure that if this is a revision OR trash action that we don't do any updates!
966
+		if (isset($this->_req_data['action'])
967
+			&& (
968
+				$this->_req_data['action'] === 'restore'
969
+				|| $this->_req_data['action'] === 'trash'
970
+			)
971
+		) {
972
+			return;
973
+		}
974
+		$this->_set_model_object($post_id, true, 'insert_update');
975
+		// if our cpt object is not instantiated and its NOT the same post_id as what is triggering this callback, then exit.
976
+		if ($update
977
+			&& (
978
+				! $this->_cpt_model_obj instanceof EE_CPT_Base
979
+				|| $this->_cpt_model_obj->ID() !== $post_id
980
+			)
981
+		) {
982
+			return;
983
+		}
984
+		// check for autosave and update our req_data property accordingly.
985
+		/*if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE && isset( $this->_req_data['ee_autosave_data'] ) ) {
986 986
             foreach( (array) $this->_req_data['ee_autosave_data'] as $id => $values ) {
987 987
 
988 988
                 foreach ( (array) $values as $key => $value ) {
@@ -992,532 +992,532 @@  discard block
 block discarded – undo
992 992
 
993 993
         }/**/ // TODO reactivate after autosave is implemented in 4.2
994 994
 
995
-        // take care of updating any selected page_template IF this cpt supports it.
996
-        if ($this->_supports_page_templates($post->post_type) && ! empty($this->_req_data['page_template'])) {
997
-            // wp version aware.
998
-            if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
999
-                $page_templates = wp_get_theme()->get_page_templates();
1000
-            } else {
1001
-                $post->page_template = $this->_req_data['page_template'];
1002
-                $page_templates = wp_get_theme()->get_page_templates($post);
1003
-            }
1004
-            if ('default' != $this->_req_data['page_template'] && ! isset($page_templates[ $this->_req_data['page_template'] ])) {
1005
-                EE_Error::add_error(__('Invalid Page Template.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
1006
-            } else {
1007
-                update_post_meta($post_id, '_wp_page_template', $this->_req_data['page_template']);
1008
-            }
1009
-        }
1010
-        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
1011
-            return;
1012
-        } //TODO we'll remove this after reimplementing autosave in 4.2
1013
-        $this->_insert_update_cpt_item($post_id, $post);
1014
-    }
1015
-
1016
-
1017
-    /**
1018
-     * This hooks into the wp_trash_post() function and removes the `_wp_trash_meta_status` and `_wp_trash_meta_time`
1019
-     * post meta IF the trashed post is one of our CPT's - note this method should only be called with our cpt routes
1020
-     * so we don't have to check for our CPT.
1021
-     *
1022
-     * @param  int $post_id ID of the post
1023
-     * @return void
1024
-     */
1025
-    public function dont_permanently_delete_ee_cpts($post_id)
1026
-    {
1027
-        // only do this if we're actually processing one of our CPTs
1028
-        // if our cpt object isn't existent then get out immediately.
1029
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base) {
1030
-            return;
1031
-        }
1032
-        delete_post_meta($post_id, '_wp_trash_meta_status');
1033
-        delete_post_meta($post_id, '_wp_trash_meta_time');
1034
-        // our cpts may have comments so let's take care of that too
1035
-        delete_post_meta($post_id, '_wp_trash_meta_comments_status');
1036
-    }
1037
-
1038
-
1039
-    /**
1040
-     * This is a wrapper for the restore_cpt_revision route for cpt items so we can make sure that when a revision is
1041
-     * triggered that we restore related items.  In order to work cpt classes MUST have a restore_cpt_revision method
1042
-     * in them. We also have our OWN action in here so addons can hook into the restore process easily.
1043
-     *
1044
-     * @param  int $post_id     ID of cpt item
1045
-     * @param  int $revision_id ID of revision being restored
1046
-     * @return void
1047
-     */
1048
-    public function restore_revision($post_id, $revision_id)
1049
-    {
1050
-        $this->_restore_cpt_item($post_id, $revision_id);
1051
-        // global action
1052
-        do_action('AHEE_EE_Admin_Page_CPT__restore_revision', $post_id, $revision_id);
1053
-        // class specific action so you can limit hooking into a specific page.
1054
-        do_action('AHEE_EE_Admin_Page_CPT_' . get_class($this) . '__restore_revision', $post_id, $revision_id);
1055
-    }
1056
-
1057
-
1058
-    /**
1059
-     * @see restore_revision() for details
1060
-     * @param  int $post_id     ID of cpt item
1061
-     * @param  int $revision_id ID of revision for item
1062
-     * @return void
1063
-     */
1064
-    abstract protected function _restore_cpt_item($post_id, $revision_id);
1065
-
1066
-
1067
-    /**
1068
-     * Execution of this method is added to the end of the load_page_dependencies method in the parent
1069
-     * so that we can fix a bug where default core metaboxes were not being called in the sidebar.
1070
-     * To fix we have to reset the current_screen using the page_slug
1071
-     * (which is identical - or should be - to our registered_post_type id.)
1072
-     * Also, since the core WP file loads the admin_header.php for WP
1073
-     * (and there are a bunch of other things edit-form-advanced.php loads that need to happen really early)
1074
-     * we need to load it NOW, hence our _route_admin_request in here. (Otherwise screen options won't be set).
1075
-     *
1076
-     * @return void
1077
-     */
1078
-    public function modify_current_screen()
1079
-    {
1080
-        // ONLY do this if the current page_route IS a cpt route
1081
-        if (! $this->_cpt_route) {
1082
-            return;
1083
-        }
1084
-        // routing things REALLY early b/c this is a cpt admin page
1085
-        set_current_screen($this->_cpt_routes[ $this->_req_action ]);
1086
-        $this->_current_screen = get_current_screen();
1087
-        $this->_current_screen->base = 'event-espresso';
1088
-        $this->_add_help_tabs(); // we make sure we add any help tabs back in!
1089
-        /*try {
995
+		// take care of updating any selected page_template IF this cpt supports it.
996
+		if ($this->_supports_page_templates($post->post_type) && ! empty($this->_req_data['page_template'])) {
997
+			// wp version aware.
998
+			if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
999
+				$page_templates = wp_get_theme()->get_page_templates();
1000
+			} else {
1001
+				$post->page_template = $this->_req_data['page_template'];
1002
+				$page_templates = wp_get_theme()->get_page_templates($post);
1003
+			}
1004
+			if ('default' != $this->_req_data['page_template'] && ! isset($page_templates[ $this->_req_data['page_template'] ])) {
1005
+				EE_Error::add_error(__('Invalid Page Template.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
1006
+			} else {
1007
+				update_post_meta($post_id, '_wp_page_template', $this->_req_data['page_template']);
1008
+			}
1009
+		}
1010
+		if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
1011
+			return;
1012
+		} //TODO we'll remove this after reimplementing autosave in 4.2
1013
+		$this->_insert_update_cpt_item($post_id, $post);
1014
+	}
1015
+
1016
+
1017
+	/**
1018
+	 * This hooks into the wp_trash_post() function and removes the `_wp_trash_meta_status` and `_wp_trash_meta_time`
1019
+	 * post meta IF the trashed post is one of our CPT's - note this method should only be called with our cpt routes
1020
+	 * so we don't have to check for our CPT.
1021
+	 *
1022
+	 * @param  int $post_id ID of the post
1023
+	 * @return void
1024
+	 */
1025
+	public function dont_permanently_delete_ee_cpts($post_id)
1026
+	{
1027
+		// only do this if we're actually processing one of our CPTs
1028
+		// if our cpt object isn't existent then get out immediately.
1029
+		if (! $this->_cpt_model_obj instanceof EE_CPT_Base) {
1030
+			return;
1031
+		}
1032
+		delete_post_meta($post_id, '_wp_trash_meta_status');
1033
+		delete_post_meta($post_id, '_wp_trash_meta_time');
1034
+		// our cpts may have comments so let's take care of that too
1035
+		delete_post_meta($post_id, '_wp_trash_meta_comments_status');
1036
+	}
1037
+
1038
+
1039
+	/**
1040
+	 * This is a wrapper for the restore_cpt_revision route for cpt items so we can make sure that when a revision is
1041
+	 * triggered that we restore related items.  In order to work cpt classes MUST have a restore_cpt_revision method
1042
+	 * in them. We also have our OWN action in here so addons can hook into the restore process easily.
1043
+	 *
1044
+	 * @param  int $post_id     ID of cpt item
1045
+	 * @param  int $revision_id ID of revision being restored
1046
+	 * @return void
1047
+	 */
1048
+	public function restore_revision($post_id, $revision_id)
1049
+	{
1050
+		$this->_restore_cpt_item($post_id, $revision_id);
1051
+		// global action
1052
+		do_action('AHEE_EE_Admin_Page_CPT__restore_revision', $post_id, $revision_id);
1053
+		// class specific action so you can limit hooking into a specific page.
1054
+		do_action('AHEE_EE_Admin_Page_CPT_' . get_class($this) . '__restore_revision', $post_id, $revision_id);
1055
+	}
1056
+
1057
+
1058
+	/**
1059
+	 * @see restore_revision() for details
1060
+	 * @param  int $post_id     ID of cpt item
1061
+	 * @param  int $revision_id ID of revision for item
1062
+	 * @return void
1063
+	 */
1064
+	abstract protected function _restore_cpt_item($post_id, $revision_id);
1065
+
1066
+
1067
+	/**
1068
+	 * Execution of this method is added to the end of the load_page_dependencies method in the parent
1069
+	 * so that we can fix a bug where default core metaboxes were not being called in the sidebar.
1070
+	 * To fix we have to reset the current_screen using the page_slug
1071
+	 * (which is identical - or should be - to our registered_post_type id.)
1072
+	 * Also, since the core WP file loads the admin_header.php for WP
1073
+	 * (and there are a bunch of other things edit-form-advanced.php loads that need to happen really early)
1074
+	 * we need to load it NOW, hence our _route_admin_request in here. (Otherwise screen options won't be set).
1075
+	 *
1076
+	 * @return void
1077
+	 */
1078
+	public function modify_current_screen()
1079
+	{
1080
+		// ONLY do this if the current page_route IS a cpt route
1081
+		if (! $this->_cpt_route) {
1082
+			return;
1083
+		}
1084
+		// routing things REALLY early b/c this is a cpt admin page
1085
+		set_current_screen($this->_cpt_routes[ $this->_req_action ]);
1086
+		$this->_current_screen = get_current_screen();
1087
+		$this->_current_screen->base = 'event-espresso';
1088
+		$this->_add_help_tabs(); // we make sure we add any help tabs back in!
1089
+		/*try {
1090 1090
             $this->_route_admin_request();
1091 1091
         } catch ( EE_Error $e ) {
1092 1092
             $e->get_error();
1093 1093
         }/**/
1094
-    }
1095
-
1096
-
1097
-    /**
1098
-     * This allows child classes to modify the default editor title that appears when people add a new or edit an
1099
-     * existing CPT item.     * This uses the _labels property set by the child class via _define_page_props. Just make
1100
-     * sure you have a key in _labels property that equals 'editor_title' and the value can be whatever you want the
1101
-     * default to be.
1102
-     *
1103
-     * @param string $title The new title (or existing if there is no editor_title defined)
1104
-     * @return string
1105
-     */
1106
-    public function add_custom_editor_default_title($title)
1107
-    {
1108
-        return isset($this->_labels['editor_title'][ $this->_cpt_routes[ $this->_req_action ] ])
1109
-            ? $this->_labels['editor_title'][ $this->_cpt_routes[ $this->_req_action ] ]
1110
-            : $title;
1111
-    }
1112
-
1113
-
1114
-    /**
1115
-     * hooks into the wp_get_shortlink button and makes sure that the shortlink gets generated
1116
-     *
1117
-     * @param string $shortlink   The already generated shortlink
1118
-     * @param int    $id          Post ID for this item
1119
-     * @param string $context     The context for the link
1120
-     * @param bool   $allow_slugs Whether to allow post slugs in the shortlink.
1121
-     * @return string
1122
-     */
1123
-    public function add_shortlink_button_to_editor($shortlink, $id, $context, $allow_slugs)
1124
-    {
1125
-        if (! empty($id) && get_option('permalink_structure') !== '') {
1126
-            $post = get_post($id);
1127
-            if (isset($post->post_type) && $this->page_slug === $post->post_type) {
1128
-                $shortlink = home_url('?p=' . $post->ID);
1129
-            }
1130
-        }
1131
-        return $shortlink;
1132
-    }
1133
-
1134
-
1135
-    /**
1136
-     * overriding the parent route_admin_request method so we DON'T run the route twice on cpt core page loads (it's
1137
-     * already run in modify_current_screen())
1138
-     *
1139
-     * @return void
1140
-     */
1141
-    public function route_admin_request()
1142
-    {
1143
-        if ($this->_cpt_route) {
1144
-            return;
1145
-        }
1146
-        try {
1147
-            $this->_route_admin_request();
1148
-        } catch (EE_Error $e) {
1149
-            $e->get_error();
1150
-        }
1151
-    }
1152
-
1153
-
1154
-    /**
1155
-     * Add a hidden form input to cpt core pages so that we know to do redirects to our routes on saves
1156
-     *
1157
-     * @return void
1158
-     */
1159
-    public function cpt_post_form_hidden_input()
1160
-    {
1161
-        echo '<input type="hidden" name="ee_cpt_item_redirect_url" value="' . $this->_admin_base_url . '" />';
1162
-        // we're also going to add the route value and the current page so we can direct autosave parsing correctly
1163
-        echo '<div id="ee-cpt-hidden-inputs">';
1164
-        echo '<input type="hidden" id="current_route" name="current_route" value="' . $this->_current_view . '" />';
1165
-        echo '<input type="hidden" id="current_page" name="current_page" value="' . $this->page_slug . '" />';
1166
-        echo '</div>';
1167
-    }
1168
-
1169
-
1170
-    /**
1171
-     * This allows us to redirect the location of revision restores when they happen so it goes to our CPT routes.
1172
-     *
1173
-     * @param  string $location Original location url
1174
-     * @param  int    $status   Status for http header
1175
-     * @return string           new (or original) url to redirect to.
1176
-     */
1177
-    public function revision_redirect($location, $status)
1178
-    {
1179
-        // get revision
1180
-        $rev_id = isset($this->_req_data['revision']) ? $this->_req_data['revision'] : null;
1181
-        // can't do anything without revision so let's get out if not present
1182
-        if (empty($rev_id)) {
1183
-            return $location;
1184
-        }
1185
-        // get rev_post_data
1186
-        $rev = get_post($rev_id);
1187
-        $admin_url = $this->_admin_base_url;
1188
-        $query_args = array(
1189
-            'action'   => 'edit',
1190
-            'post'     => $rev->post_parent,
1191
-            'revision' => $rev_id,
1192
-            'message'  => 5,
1193
-        );
1194
-        $this->_process_notices($query_args, true);
1195
-        return self::add_query_args_and_nonce($query_args, $admin_url);
1196
-    }
1197
-
1198
-
1199
-    /**
1200
-     * Modify the edit post link generated by wp core function so that EE CPTs get setup differently.
1201
-     *
1202
-     * @param  string $link    the original generated link
1203
-     * @param  int    $id      post id
1204
-     * @param  string $context optional, defaults to display.  How to write the '&'
1205
-     * @return string          the link
1206
-     */
1207
-    public function modify_edit_post_link($link, $id, $context)
1208
-    {
1209
-        $post = get_post($id);
1210
-        if (! isset($this->_req_data['action'])
1211
-            || ! isset($this->_cpt_routes[ $this->_req_data['action'] ])
1212
-            || $post->post_type !== $this->_cpt_routes[ $this->_req_data['action'] ]
1213
-        ) {
1214
-            return $link;
1215
-        }
1216
-        $query_args = array(
1217
-            'action' => isset($this->_cpt_edit_routes[ $post->post_type ])
1218
-                ? $this->_cpt_edit_routes[ $post->post_type ]
1219
-                : 'edit',
1220
-            'post'   => $id,
1221
-        );
1222
-        return self::add_query_args_and_nonce($query_args, $this->_admin_base_url);
1223
-    }
1224
-
1225
-
1226
-    /**
1227
-     * Modify the trash link on our cpt edit pages so it has the required query var for triggering redirect properly on
1228
-     * our routes.
1229
-     *
1230
-     * @param  string $delete_link  original delete link
1231
-     * @param  int    $post_id      id of cpt object
1232
-     * @param  bool   $force_delete whether this is forcing a hard delete instead of trash
1233
-     * @return string new delete link
1234
-     * @throws EE_Error
1235
-     */
1236
-    public function modify_delete_post_link($delete_link, $post_id, $force_delete)
1237
-    {
1238
-        $post = get_post($post_id);
1239
-
1240
-        if (empty($this->_req_data['action'])
1241
-            || ! isset($this->_cpt_routes[ $this->_req_data['action'] ])
1242
-            || ! $post instanceof WP_Post
1243
-            || $post->post_type !== $this->_cpt_routes[ $this->_req_data['action'] ]
1244
-        ) {
1245
-            return $delete_link;
1246
-        }
1247
-        $this->_set_model_object($post->ID, true);
1248
-
1249
-        // returns something like `trash_event` or `trash_attendee` or `trash_venue`
1250
-        $action = 'trash_' . str_replace('ee_', '', strtolower(get_class($this->_cpt_model_obj)));
1251
-
1252
-        return EE_Admin_Page::add_query_args_and_nonce(
1253
-            array(
1254
-                'page'   => $this->_req_data['page'],
1255
-                'action' => $action,
1256
-                $this->_cpt_model_obj->get_model()->get_primary_key_field()->get_name()
1257
-                         => $post->ID,
1258
-            ),
1259
-            admin_url()
1260
-        );
1261
-    }
1262
-
1263
-
1264
-    /**
1265
-     * This is the callback for the 'redirect_post_location' filter in wp-admin/post.php
1266
-     * so that we can hijack the default redirect locations for wp custom post types
1267
-     * that WE'RE using and send back to OUR routes.  This should only be hooked in on the right route.
1268
-     *
1269
-     * @param  string $location This is the incoming currently set redirect location
1270
-     * @param  string $post_id  This is the 'ID' value of the wp_posts table
1271
-     * @return string           the new location to redirect to
1272
-     */
1273
-    public function cpt_post_location_redirect($location, $post_id)
1274
-    {
1275
-        // we DO have a match so let's setup the url
1276
-        // we have to get the post to determine our route
1277
-        $post = get_post($post_id);
1278
-        $edit_route = $this->_cpt_edit_routes[ $post->post_type ];
1279
-        // shared query_args
1280
-        $query_args = array('action' => $edit_route, 'post' => $post_id);
1281
-        $admin_url = $this->_admin_base_url;
1282
-        if (isset($this->_req_data['save']) || isset($this->_req_data['publish'])) {
1283
-            $status = get_post_status($post_id);
1284
-            if (isset($this->_req_data['publish'])) {
1285
-                switch ($status) {
1286
-                    case 'pending':
1287
-                        $message = 8;
1288
-                        break;
1289
-                    case 'future':
1290
-                        $message = 9;
1291
-                        break;
1292
-                    default:
1293
-                        $message = 6;
1294
-                }
1295
-            } else {
1296
-                $message = 'draft' === $status ? 10 : 1;
1297
-            }
1298
-        } elseif (isset($this->_req_data['addmeta']) && $this->_req_data['addmeta']) {
1299
-            $message = 2;
1300
-        } elseif (isset($this->_req_data['deletemeta']) && $this->_req_data['deletemeta']) {
1301
-            $message = 3;
1302
-        } elseif ($this->_req_data['action'] === 'post-quickpress-save-cont') {
1303
-            $message = 7;
1304
-        } else {
1305
-            $message = 4;
1306
-        }
1307
-        // change the message if the post type is not viewable on the frontend
1308
-        $this->_cpt_object = get_post_type_object($post->post_type);
1309
-        $message = $message === 1 && ! $this->_cpt_object->publicly_queryable ? 4 : $message;
1310
-        $query_args = array_merge(array('message' => $message), $query_args);
1311
-        $this->_process_notices($query_args, true);
1312
-        return self::add_query_args_and_nonce($query_args, $admin_url);
1313
-    }
1314
-
1315
-
1316
-    /**
1317
-     * This method is called to inject nav tabs on core WP cpt pages
1318
-     *
1319
-     * @access public
1320
-     * @return void
1321
-     */
1322
-    public function inject_nav_tabs()
1323
-    {
1324
-        // can we hijack and insert the nav_tabs?
1325
-        $nav_tabs = $this->_get_main_nav_tabs();
1326
-        // first close off existing form tag
1327
-        $html = '>';
1328
-        $html .= $nav_tabs;
1329
-        // now let's handle the remaining tag ( missing ">" is CORRECT )
1330
-        $html .= '<span></span';
1331
-        echo $html;
1332
-    }
1333
-
1334
-
1335
-    /**
1336
-     * This just sets up the post update messages when an update form is loaded
1337
-     *
1338
-     * @access public
1339
-     * @param  array $messages the original messages array
1340
-     * @return array           the new messages array
1341
-     */
1342
-    public function post_update_messages($messages)
1343
-    {
1344
-        global $post;
1345
-        $id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
1346
-        $id = empty($id) && is_object($post) ? $post->ID : null;
1347
-        /*$current_route = isset($this->_req_data['current_route']) ? $this->_req_data['current_route'] : 'shouldneverwork';
1094
+	}
1095
+
1096
+
1097
+	/**
1098
+	 * This allows child classes to modify the default editor title that appears when people add a new or edit an
1099
+	 * existing CPT item.     * This uses the _labels property set by the child class via _define_page_props. Just make
1100
+	 * sure you have a key in _labels property that equals 'editor_title' and the value can be whatever you want the
1101
+	 * default to be.
1102
+	 *
1103
+	 * @param string $title The new title (or existing if there is no editor_title defined)
1104
+	 * @return string
1105
+	 */
1106
+	public function add_custom_editor_default_title($title)
1107
+	{
1108
+		return isset($this->_labels['editor_title'][ $this->_cpt_routes[ $this->_req_action ] ])
1109
+			? $this->_labels['editor_title'][ $this->_cpt_routes[ $this->_req_action ] ]
1110
+			: $title;
1111
+	}
1112
+
1113
+
1114
+	/**
1115
+	 * hooks into the wp_get_shortlink button and makes sure that the shortlink gets generated
1116
+	 *
1117
+	 * @param string $shortlink   The already generated shortlink
1118
+	 * @param int    $id          Post ID for this item
1119
+	 * @param string $context     The context for the link
1120
+	 * @param bool   $allow_slugs Whether to allow post slugs in the shortlink.
1121
+	 * @return string
1122
+	 */
1123
+	public function add_shortlink_button_to_editor($shortlink, $id, $context, $allow_slugs)
1124
+	{
1125
+		if (! empty($id) && get_option('permalink_structure') !== '') {
1126
+			$post = get_post($id);
1127
+			if (isset($post->post_type) && $this->page_slug === $post->post_type) {
1128
+				$shortlink = home_url('?p=' . $post->ID);
1129
+			}
1130
+		}
1131
+		return $shortlink;
1132
+	}
1133
+
1134
+
1135
+	/**
1136
+	 * overriding the parent route_admin_request method so we DON'T run the route twice on cpt core page loads (it's
1137
+	 * already run in modify_current_screen())
1138
+	 *
1139
+	 * @return void
1140
+	 */
1141
+	public function route_admin_request()
1142
+	{
1143
+		if ($this->_cpt_route) {
1144
+			return;
1145
+		}
1146
+		try {
1147
+			$this->_route_admin_request();
1148
+		} catch (EE_Error $e) {
1149
+			$e->get_error();
1150
+		}
1151
+	}
1152
+
1153
+
1154
+	/**
1155
+	 * Add a hidden form input to cpt core pages so that we know to do redirects to our routes on saves
1156
+	 *
1157
+	 * @return void
1158
+	 */
1159
+	public function cpt_post_form_hidden_input()
1160
+	{
1161
+		echo '<input type="hidden" name="ee_cpt_item_redirect_url" value="' . $this->_admin_base_url . '" />';
1162
+		// we're also going to add the route value and the current page so we can direct autosave parsing correctly
1163
+		echo '<div id="ee-cpt-hidden-inputs">';
1164
+		echo '<input type="hidden" id="current_route" name="current_route" value="' . $this->_current_view . '" />';
1165
+		echo '<input type="hidden" id="current_page" name="current_page" value="' . $this->page_slug . '" />';
1166
+		echo '</div>';
1167
+	}
1168
+
1169
+
1170
+	/**
1171
+	 * This allows us to redirect the location of revision restores when they happen so it goes to our CPT routes.
1172
+	 *
1173
+	 * @param  string $location Original location url
1174
+	 * @param  int    $status   Status for http header
1175
+	 * @return string           new (or original) url to redirect to.
1176
+	 */
1177
+	public function revision_redirect($location, $status)
1178
+	{
1179
+		// get revision
1180
+		$rev_id = isset($this->_req_data['revision']) ? $this->_req_data['revision'] : null;
1181
+		// can't do anything without revision so let's get out if not present
1182
+		if (empty($rev_id)) {
1183
+			return $location;
1184
+		}
1185
+		// get rev_post_data
1186
+		$rev = get_post($rev_id);
1187
+		$admin_url = $this->_admin_base_url;
1188
+		$query_args = array(
1189
+			'action'   => 'edit',
1190
+			'post'     => $rev->post_parent,
1191
+			'revision' => $rev_id,
1192
+			'message'  => 5,
1193
+		);
1194
+		$this->_process_notices($query_args, true);
1195
+		return self::add_query_args_and_nonce($query_args, $admin_url);
1196
+	}
1197
+
1198
+
1199
+	/**
1200
+	 * Modify the edit post link generated by wp core function so that EE CPTs get setup differently.
1201
+	 *
1202
+	 * @param  string $link    the original generated link
1203
+	 * @param  int    $id      post id
1204
+	 * @param  string $context optional, defaults to display.  How to write the '&'
1205
+	 * @return string          the link
1206
+	 */
1207
+	public function modify_edit_post_link($link, $id, $context)
1208
+	{
1209
+		$post = get_post($id);
1210
+		if (! isset($this->_req_data['action'])
1211
+			|| ! isset($this->_cpt_routes[ $this->_req_data['action'] ])
1212
+			|| $post->post_type !== $this->_cpt_routes[ $this->_req_data['action'] ]
1213
+		) {
1214
+			return $link;
1215
+		}
1216
+		$query_args = array(
1217
+			'action' => isset($this->_cpt_edit_routes[ $post->post_type ])
1218
+				? $this->_cpt_edit_routes[ $post->post_type ]
1219
+				: 'edit',
1220
+			'post'   => $id,
1221
+		);
1222
+		return self::add_query_args_and_nonce($query_args, $this->_admin_base_url);
1223
+	}
1224
+
1225
+
1226
+	/**
1227
+	 * Modify the trash link on our cpt edit pages so it has the required query var for triggering redirect properly on
1228
+	 * our routes.
1229
+	 *
1230
+	 * @param  string $delete_link  original delete link
1231
+	 * @param  int    $post_id      id of cpt object
1232
+	 * @param  bool   $force_delete whether this is forcing a hard delete instead of trash
1233
+	 * @return string new delete link
1234
+	 * @throws EE_Error
1235
+	 */
1236
+	public function modify_delete_post_link($delete_link, $post_id, $force_delete)
1237
+	{
1238
+		$post = get_post($post_id);
1239
+
1240
+		if (empty($this->_req_data['action'])
1241
+			|| ! isset($this->_cpt_routes[ $this->_req_data['action'] ])
1242
+			|| ! $post instanceof WP_Post
1243
+			|| $post->post_type !== $this->_cpt_routes[ $this->_req_data['action'] ]
1244
+		) {
1245
+			return $delete_link;
1246
+		}
1247
+		$this->_set_model_object($post->ID, true);
1248
+
1249
+		// returns something like `trash_event` or `trash_attendee` or `trash_venue`
1250
+		$action = 'trash_' . str_replace('ee_', '', strtolower(get_class($this->_cpt_model_obj)));
1251
+
1252
+		return EE_Admin_Page::add_query_args_and_nonce(
1253
+			array(
1254
+				'page'   => $this->_req_data['page'],
1255
+				'action' => $action,
1256
+				$this->_cpt_model_obj->get_model()->get_primary_key_field()->get_name()
1257
+						 => $post->ID,
1258
+			),
1259
+			admin_url()
1260
+		);
1261
+	}
1262
+
1263
+
1264
+	/**
1265
+	 * This is the callback for the 'redirect_post_location' filter in wp-admin/post.php
1266
+	 * so that we can hijack the default redirect locations for wp custom post types
1267
+	 * that WE'RE using and send back to OUR routes.  This should only be hooked in on the right route.
1268
+	 *
1269
+	 * @param  string $location This is the incoming currently set redirect location
1270
+	 * @param  string $post_id  This is the 'ID' value of the wp_posts table
1271
+	 * @return string           the new location to redirect to
1272
+	 */
1273
+	public function cpt_post_location_redirect($location, $post_id)
1274
+	{
1275
+		// we DO have a match so let's setup the url
1276
+		// we have to get the post to determine our route
1277
+		$post = get_post($post_id);
1278
+		$edit_route = $this->_cpt_edit_routes[ $post->post_type ];
1279
+		// shared query_args
1280
+		$query_args = array('action' => $edit_route, 'post' => $post_id);
1281
+		$admin_url = $this->_admin_base_url;
1282
+		if (isset($this->_req_data['save']) || isset($this->_req_data['publish'])) {
1283
+			$status = get_post_status($post_id);
1284
+			if (isset($this->_req_data['publish'])) {
1285
+				switch ($status) {
1286
+					case 'pending':
1287
+						$message = 8;
1288
+						break;
1289
+					case 'future':
1290
+						$message = 9;
1291
+						break;
1292
+					default:
1293
+						$message = 6;
1294
+				}
1295
+			} else {
1296
+				$message = 'draft' === $status ? 10 : 1;
1297
+			}
1298
+		} elseif (isset($this->_req_data['addmeta']) && $this->_req_data['addmeta']) {
1299
+			$message = 2;
1300
+		} elseif (isset($this->_req_data['deletemeta']) && $this->_req_data['deletemeta']) {
1301
+			$message = 3;
1302
+		} elseif ($this->_req_data['action'] === 'post-quickpress-save-cont') {
1303
+			$message = 7;
1304
+		} else {
1305
+			$message = 4;
1306
+		}
1307
+		// change the message if the post type is not viewable on the frontend
1308
+		$this->_cpt_object = get_post_type_object($post->post_type);
1309
+		$message = $message === 1 && ! $this->_cpt_object->publicly_queryable ? 4 : $message;
1310
+		$query_args = array_merge(array('message' => $message), $query_args);
1311
+		$this->_process_notices($query_args, true);
1312
+		return self::add_query_args_and_nonce($query_args, $admin_url);
1313
+	}
1314
+
1315
+
1316
+	/**
1317
+	 * This method is called to inject nav tabs on core WP cpt pages
1318
+	 *
1319
+	 * @access public
1320
+	 * @return void
1321
+	 */
1322
+	public function inject_nav_tabs()
1323
+	{
1324
+		// can we hijack and insert the nav_tabs?
1325
+		$nav_tabs = $this->_get_main_nav_tabs();
1326
+		// first close off existing form tag
1327
+		$html = '>';
1328
+		$html .= $nav_tabs;
1329
+		// now let's handle the remaining tag ( missing ">" is CORRECT )
1330
+		$html .= '<span></span';
1331
+		echo $html;
1332
+	}
1333
+
1334
+
1335
+	/**
1336
+	 * This just sets up the post update messages when an update form is loaded
1337
+	 *
1338
+	 * @access public
1339
+	 * @param  array $messages the original messages array
1340
+	 * @return array           the new messages array
1341
+	 */
1342
+	public function post_update_messages($messages)
1343
+	{
1344
+		global $post;
1345
+		$id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
1346
+		$id = empty($id) && is_object($post) ? $post->ID : null;
1347
+		/*$current_route = isset($this->_req_data['current_route']) ? $this->_req_data['current_route'] : 'shouldneverwork';
1348 1348
 
1349 1349
         $route_to_check = $post_type && isset( $this->_cpt_routes[$current_route]) ? $this->_cpt_routes[$current_route] : '';/**/
1350
-        $messages[ $post->post_type ] = array(
1351
-            0  => '', // Unused. Messages start at index 1.
1352
-            1  => sprintf(
1353
-                __('%1$s updated. %2$sView %1$s%3$s', 'event_espresso'),
1354
-                $this->_cpt_object->labels->singular_name,
1355
-                '<a href="' . esc_url(get_permalink($id)) . '">',
1356
-                '</a>'
1357
-            ),
1358
-            2  => __('Custom field updated', 'event_espresso'),
1359
-            3  => __('Custom field deleted.', 'event_espresso'),
1360
-            4  => sprintf(__('%1$s updated.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1361
-            5  => isset($_GET['revision']) ? sprintf(
1362
-                __('%s restored to revision from %s', 'event_espresso'),
1363
-                $this->_cpt_object->labels->singular_name,
1364
-                wp_post_revision_title((int) $_GET['revision'], false)
1365
-            )
1366
-                : false,
1367
-            6  => sprintf(
1368
-                __('%1$s published. %2$sView %1$s%3$s', 'event_espresso'),
1369
-                $this->_cpt_object->labels->singular_name,
1370
-                '<a href="' . esc_url(get_permalink($id)) . '">',
1371
-                '</a>'
1372
-            ),
1373
-            7  => sprintf(__('%1$s saved.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1374
-            8  => sprintf(
1375
-                __('%1$s submitted. %2$sPreview %1$s%3$s', 'event_espresso'),
1376
-                $this->_cpt_object->labels->singular_name,
1377
-                '<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))) . '">',
1378
-                '</a>'
1379
-            ),
1380
-            9  => sprintf(
1381
-                __('%1$s scheduled for: %2$s. %3$s">Preview %1$s%3$s', 'event_espresso'),
1382
-                $this->_cpt_object->labels->singular_name,
1383
-                '<strong>' . date_i18n('M j, Y @ G:i', strtotime($post->post_date)) . '</strong>',
1384
-                '<a target="_blank" href="' . esc_url(get_permalink($id)),
1385
-                '</a>'
1386
-            ),
1387
-            10 => sprintf(
1388
-                __('%1$s draft updated. %2$s">Preview page%3$s', 'event_espresso'),
1389
-                $this->_cpt_object->labels->singular_name,
1390
-                '<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))),
1391
-                '</a>'
1392
-            ),
1393
-        );
1394
-        return $messages;
1395
-    }
1396
-
1397
-
1398
-    /**
1399
-     * default method for the 'create_new' route for cpt admin pages.
1400
-     * For reference what to include in here, see wp-admin/post-new.php
1401
-     *
1402
-     * @access  protected
1403
-     * @return void
1404
-     */
1405
-    protected function _create_new_cpt_item()
1406
-    {
1407
-        // gather template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1408
-        global $post, $title, $is_IE, $post_type, $post_type_object;
1409
-        $post_type = $this->_cpt_routes[ $this->_req_action ];
1410
-        $post_type_object = $this->_cpt_object;
1411
-        $title = $post_type_object->labels->add_new_item;
1412
-        $post = $post = get_default_post_to_edit($this->_cpt_routes[ $this->_req_action ], true);
1413
-        add_action('admin_print_styles', array($this, 'add_new_admin_page_global'));
1414
-        // modify the default editor title field with default title.
1415
-        add_filter('enter_title_here', array($this, 'add_custom_editor_default_title'), 10);
1416
-        $this->loadEditorTemplate(true);
1417
-    }
1418
-
1419
-
1420
-    /**
1421
-     * Enqueues auto-save and loads the editor template
1422
-     *
1423
-     * @param bool $creating
1424
-     */
1425
-    private function loadEditorTemplate($creating = true)
1426
-    {
1427
-        global $post, $title, $is_IE, $post_type, $post_type_object;
1428
-        // these vars are used by the template
1429
-        $editing = true;
1430
-        $post_ID = $post->ID;
1431
-        if (apply_filters('FHEE__EE_Admin_Page_CPT___create_new_cpt_item__replace_editor', false, $post) === false) {
1432
-            // only enqueue autosave when creating event (necessary to get permalink/url generated)
1433
-            // otherwise EE doesn't support autosave fully, so to prevent user confusion we disable it in edit context.
1434
-            if ($creating) {
1435
-                wp_enqueue_script('autosave');
1436
-            } else {
1437
-                if (isset($this->_cpt_routes[ $this->_req_data['action'] ])
1438
-                    && ! isset($this->_labels['hide_add_button_on_cpt_route'][ $this->_req_data['action'] ])
1439
-                ) {
1440
-                    $create_new_action = apply_filters(
1441
-                        'FHEE__EE_Admin_Page_CPT___edit_cpt_item__create_new_action',
1442
-                        'create_new',
1443
-                        $this
1444
-                    );
1445
-                    $post_new_file = EE_Admin_Page::add_query_args_and_nonce(
1446
-                        array(
1447
-                            'action' => $create_new_action,
1448
-                            'page'   => $this->page_slug,
1449
-                        ),
1450
-                        'admin.php'
1451
-                    );
1452
-                }
1453
-            }
1454
-            include_once WP_ADMIN_PATH . 'edit-form-advanced.php';
1455
-        }
1456
-    }
1457
-
1458
-
1459
-    public function add_new_admin_page_global()
1460
-    {
1461
-        $admin_page = ! empty($this->_req_data['post']) ? 'post-php' : 'post-new-php';
1462
-        ?>
1350
+		$messages[ $post->post_type ] = array(
1351
+			0  => '', // Unused. Messages start at index 1.
1352
+			1  => sprintf(
1353
+				__('%1$s updated. %2$sView %1$s%3$s', 'event_espresso'),
1354
+				$this->_cpt_object->labels->singular_name,
1355
+				'<a href="' . esc_url(get_permalink($id)) . '">',
1356
+				'</a>'
1357
+			),
1358
+			2  => __('Custom field updated', 'event_espresso'),
1359
+			3  => __('Custom field deleted.', 'event_espresso'),
1360
+			4  => sprintf(__('%1$s updated.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1361
+			5  => isset($_GET['revision']) ? sprintf(
1362
+				__('%s restored to revision from %s', 'event_espresso'),
1363
+				$this->_cpt_object->labels->singular_name,
1364
+				wp_post_revision_title((int) $_GET['revision'], false)
1365
+			)
1366
+				: false,
1367
+			6  => sprintf(
1368
+				__('%1$s published. %2$sView %1$s%3$s', 'event_espresso'),
1369
+				$this->_cpt_object->labels->singular_name,
1370
+				'<a href="' . esc_url(get_permalink($id)) . '">',
1371
+				'</a>'
1372
+			),
1373
+			7  => sprintf(__('%1$s saved.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1374
+			8  => sprintf(
1375
+				__('%1$s submitted. %2$sPreview %1$s%3$s', 'event_espresso'),
1376
+				$this->_cpt_object->labels->singular_name,
1377
+				'<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))) . '">',
1378
+				'</a>'
1379
+			),
1380
+			9  => sprintf(
1381
+				__('%1$s scheduled for: %2$s. %3$s">Preview %1$s%3$s', 'event_espresso'),
1382
+				$this->_cpt_object->labels->singular_name,
1383
+				'<strong>' . date_i18n('M j, Y @ G:i', strtotime($post->post_date)) . '</strong>',
1384
+				'<a target="_blank" href="' . esc_url(get_permalink($id)),
1385
+				'</a>'
1386
+			),
1387
+			10 => sprintf(
1388
+				__('%1$s draft updated. %2$s">Preview page%3$s', 'event_espresso'),
1389
+				$this->_cpt_object->labels->singular_name,
1390
+				'<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))),
1391
+				'</a>'
1392
+			),
1393
+		);
1394
+		return $messages;
1395
+	}
1396
+
1397
+
1398
+	/**
1399
+	 * default method for the 'create_new' route for cpt admin pages.
1400
+	 * For reference what to include in here, see wp-admin/post-new.php
1401
+	 *
1402
+	 * @access  protected
1403
+	 * @return void
1404
+	 */
1405
+	protected function _create_new_cpt_item()
1406
+	{
1407
+		// gather template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1408
+		global $post, $title, $is_IE, $post_type, $post_type_object;
1409
+		$post_type = $this->_cpt_routes[ $this->_req_action ];
1410
+		$post_type_object = $this->_cpt_object;
1411
+		$title = $post_type_object->labels->add_new_item;
1412
+		$post = $post = get_default_post_to_edit($this->_cpt_routes[ $this->_req_action ], true);
1413
+		add_action('admin_print_styles', array($this, 'add_new_admin_page_global'));
1414
+		// modify the default editor title field with default title.
1415
+		add_filter('enter_title_here', array($this, 'add_custom_editor_default_title'), 10);
1416
+		$this->loadEditorTemplate(true);
1417
+	}
1418
+
1419
+
1420
+	/**
1421
+	 * Enqueues auto-save and loads the editor template
1422
+	 *
1423
+	 * @param bool $creating
1424
+	 */
1425
+	private function loadEditorTemplate($creating = true)
1426
+	{
1427
+		global $post, $title, $is_IE, $post_type, $post_type_object;
1428
+		// these vars are used by the template
1429
+		$editing = true;
1430
+		$post_ID = $post->ID;
1431
+		if (apply_filters('FHEE__EE_Admin_Page_CPT___create_new_cpt_item__replace_editor', false, $post) === false) {
1432
+			// only enqueue autosave when creating event (necessary to get permalink/url generated)
1433
+			// otherwise EE doesn't support autosave fully, so to prevent user confusion we disable it in edit context.
1434
+			if ($creating) {
1435
+				wp_enqueue_script('autosave');
1436
+			} else {
1437
+				if (isset($this->_cpt_routes[ $this->_req_data['action'] ])
1438
+					&& ! isset($this->_labels['hide_add_button_on_cpt_route'][ $this->_req_data['action'] ])
1439
+				) {
1440
+					$create_new_action = apply_filters(
1441
+						'FHEE__EE_Admin_Page_CPT___edit_cpt_item__create_new_action',
1442
+						'create_new',
1443
+						$this
1444
+					);
1445
+					$post_new_file = EE_Admin_Page::add_query_args_and_nonce(
1446
+						array(
1447
+							'action' => $create_new_action,
1448
+							'page'   => $this->page_slug,
1449
+						),
1450
+						'admin.php'
1451
+					);
1452
+				}
1453
+			}
1454
+			include_once WP_ADMIN_PATH . 'edit-form-advanced.php';
1455
+		}
1456
+	}
1457
+
1458
+
1459
+	public function add_new_admin_page_global()
1460
+	{
1461
+		$admin_page = ! empty($this->_req_data['post']) ? 'post-php' : 'post-new-php';
1462
+		?>
1463 1463
         <script type="text/javascript">
1464 1464
             adminpage = '<?php echo $admin_page; ?>';
1465 1465
         </script>
1466 1466
         <?php
1467
-    }
1468
-
1469
-
1470
-    /**
1471
-     * default method for the 'edit' route for cpt admin pages
1472
-     * For reference on what to put in here, refer to wp-admin/post.php
1473
-     *
1474
-     * @access protected
1475
-     * @return string   template for edit cpt form
1476
-     */
1477
-    protected function _edit_cpt_item()
1478
-    {
1479
-        global $post, $title, $is_IE, $post_type, $post_type_object;
1480
-        $post_id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
1481
-        $post = ! empty($post_id) ? get_post($post_id, OBJECT, 'edit') : null;
1482
-        if (empty($post)) {
1483
-            wp_die(__('You attempted to edit an item that doesn&#8217;t exist. Perhaps it was deleted?', 'event_espresso'));
1484
-        }
1485
-        if (! empty($_GET['get-post-lock'])) {
1486
-            wp_set_post_lock($post_id);
1487
-            wp_redirect(get_edit_post_link($post_id, 'url'));
1488
-            exit();
1489
-        }
1490
-
1491
-        // template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1492
-        $post_type = $this->_cpt_routes[ $this->_req_action ];
1493
-        $post_type_object = $this->_cpt_object;
1494
-
1495
-        if (! wp_check_post_lock($post->ID)) {
1496
-            wp_set_post_lock($post->ID);
1497
-        }
1498
-        add_action('admin_footer', '_admin_notice_post_locked');
1499
-        if (post_type_supports($this->_cpt_routes[ $this->_req_action ], 'comments')) {
1500
-            wp_enqueue_script('admin-comments');
1501
-            enqueue_comment_hotkeys_js();
1502
-        }
1503
-        add_action('admin_print_styles', array($this, 'add_new_admin_page_global'));
1504
-        // modify the default editor title field with default title.
1505
-        add_filter('enter_title_here', array($this, 'add_custom_editor_default_title'), 10);
1506
-        $this->loadEditorTemplate(false);
1507
-    }
1508
-
1509
-
1510
-
1511
-    /**
1512
-     * some getters
1513
-     */
1514
-    /**
1515
-     * This returns the protected _cpt_model_obj property
1516
-     *
1517
-     * @return EE_CPT_Base
1518
-     */
1519
-    public function get_cpt_model_obj()
1520
-    {
1521
-        return $this->_cpt_model_obj;
1522
-    }
1467
+	}
1468
+
1469
+
1470
+	/**
1471
+	 * default method for the 'edit' route for cpt admin pages
1472
+	 * For reference on what to put in here, refer to wp-admin/post.php
1473
+	 *
1474
+	 * @access protected
1475
+	 * @return string   template for edit cpt form
1476
+	 */
1477
+	protected function _edit_cpt_item()
1478
+	{
1479
+		global $post, $title, $is_IE, $post_type, $post_type_object;
1480
+		$post_id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
1481
+		$post = ! empty($post_id) ? get_post($post_id, OBJECT, 'edit') : null;
1482
+		if (empty($post)) {
1483
+			wp_die(__('You attempted to edit an item that doesn&#8217;t exist. Perhaps it was deleted?', 'event_espresso'));
1484
+		}
1485
+		if (! empty($_GET['get-post-lock'])) {
1486
+			wp_set_post_lock($post_id);
1487
+			wp_redirect(get_edit_post_link($post_id, 'url'));
1488
+			exit();
1489
+		}
1490
+
1491
+		// template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1492
+		$post_type = $this->_cpt_routes[ $this->_req_action ];
1493
+		$post_type_object = $this->_cpt_object;
1494
+
1495
+		if (! wp_check_post_lock($post->ID)) {
1496
+			wp_set_post_lock($post->ID);
1497
+		}
1498
+		add_action('admin_footer', '_admin_notice_post_locked');
1499
+		if (post_type_supports($this->_cpt_routes[ $this->_req_action ], 'comments')) {
1500
+			wp_enqueue_script('admin-comments');
1501
+			enqueue_comment_hotkeys_js();
1502
+		}
1503
+		add_action('admin_print_styles', array($this, 'add_new_admin_page_global'));
1504
+		// modify the default editor title field with default title.
1505
+		add_filter('enter_title_here', array($this, 'add_custom_editor_default_title'), 10);
1506
+		$this->loadEditorTemplate(false);
1507
+	}
1508
+
1509
+
1510
+
1511
+	/**
1512
+	 * some getters
1513
+	 */
1514
+	/**
1515
+	 * This returns the protected _cpt_model_obj property
1516
+	 *
1517
+	 * @return EE_CPT_Base
1518
+	 */
1519
+	public function get_cpt_model_obj()
1520
+	{
1521
+		return $this->_cpt_model_obj;
1522
+	}
1523 1523
 }
Please login to merge, or discard this patch.
core/EE_Error.core.php 1 patch
Indentation   +1126 added lines, -1126 removed lines patch added patch discarded remove patch
@@ -10,8 +10,8 @@  discard block
 block discarded – undo
10 10
 // if you're a dev and want to receive all errors via email
11 11
 // add this to your wp-config.php: define( 'EE_ERROR_EMAILS', TRUE );
12 12
 if (defined('WP_DEBUG') && WP_DEBUG === true && defined('EE_ERROR_EMAILS') && EE_ERROR_EMAILS === true) {
13
-    set_error_handler(array('EE_Error', 'error_handler'));
14
-    register_shutdown_function(array('EE_Error', 'fatal_error_handler'));
13
+	set_error_handler(array('EE_Error', 'error_handler'));
14
+	register_shutdown_function(array('EE_Error', 'fatal_error_handler'));
15 15
 }
16 16
 
17 17
 
@@ -25,251 +25,251 @@  discard block
 block discarded – undo
25 25
 class EE_Error extends Exception
26 26
 {
27 27
 
28
-    const OPTIONS_KEY_NOTICES = 'ee_notices';
29
-
30
-
31
-    /**
32
-     * name of the file to log exceptions to
33
-     *
34
-     * @var string
35
-     */
36
-    private static $_exception_log_file = 'espresso_error_log.txt';
37
-
38
-    /**
39
-     *    stores details for all exception
40
-     *
41
-     * @var array
42
-     */
43
-    private static $_all_exceptions = array();
44
-
45
-    /**
46
-     *    tracks number of errors
47
-     *
48
-     * @var int
49
-     */
50
-    private static $_error_count = 0;
51
-
52
-    /**
53
-     * @var array $_espresso_notices
54
-     */
55
-    private static $_espresso_notices = array('success' => false, 'errors' => false, 'attention' => false);
56
-
57
-
58
-    /**
59
-     * @override default exception handling
60
-     * @param string         $message
61
-     * @param int            $code
62
-     * @param Exception|null $previous
63
-     */
64
-    public function __construct($message, $code = 0, Exception $previous = null)
65
-    {
66
-        if (version_compare(PHP_VERSION, '5.3.0', '<')) {
67
-            parent::__construct($message, $code);
68
-        } else {
69
-            parent::__construct($message, $code, $previous);
70
-        }
71
-    }
72
-
73
-
74
-    /**
75
-     *    error_handler
76
-     *
77
-     * @param $code
78
-     * @param $message
79
-     * @param $file
80
-     * @param $line
81
-     * @return void
82
-     */
83
-    public static function error_handler($code, $message, $file, $line)
84
-    {
85
-        $type = EE_Error::error_type($code);
86
-        $site = site_url();
87
-        switch ($site) {
88
-            case 'http://ee4.eventespresso.com/':
89
-            case 'http://ee4decaf.eventespresso.com/':
90
-            case 'http://ee4hf.eventespresso.com/':
91
-            case 'http://ee4a.eventespresso.com/':
92
-            case 'http://ee4ad.eventespresso.com/':
93
-            case 'http://ee4b.eventespresso.com/':
94
-            case 'http://ee4bd.eventespresso.com/':
95
-            case 'http://ee4d.eventespresso.com/':
96
-            case 'http://ee4dd.eventespresso.com/':
97
-                $to = '[email protected]';
98
-                break;
99
-            default:
100
-                $to = get_option('admin_email');
101
-        }
102
-        $subject = $type . ' ' . $message . ' in ' . EVENT_ESPRESSO_VERSION . ' on ' . site_url();
103
-        $msg = EE_Error::_format_error($type, $message, $file, $line);
104
-        if (function_exists('wp_mail')) {
105
-            add_filter('wp_mail_content_type', array('EE_Error', 'set_content_type'));
106
-            wp_mail($to, $subject, $msg);
107
-        }
108
-        echo '<div id="message" class="espresso-notices error"><p>';
109
-        echo $type . ': ' . $message . '<br />' . $file . ' line ' . $line;
110
-        echo '<br /></p></div>';
111
-    }
112
-
113
-
114
-    /**
115
-     * error_type
116
-     * http://www.php.net/manual/en/errorfunc.constants.php#109430
117
-     *
118
-     * @param $code
119
-     * @return string
120
-     */
121
-    public static function error_type($code)
122
-    {
123
-        switch ($code) {
124
-            case E_ERROR: // 1 //
125
-                return 'E_ERROR';
126
-            case E_WARNING: // 2 //
127
-                return 'E_WARNING';
128
-            case E_PARSE: // 4 //
129
-                return 'E_PARSE';
130
-            case E_NOTICE: // 8 //
131
-                return 'E_NOTICE';
132
-            case E_CORE_ERROR: // 16 //
133
-                return 'E_CORE_ERROR';
134
-            case E_CORE_WARNING: // 32 //
135
-                return 'E_CORE_WARNING';
136
-            case E_COMPILE_ERROR: // 64 //
137
-                return 'E_COMPILE_ERROR';
138
-            case E_COMPILE_WARNING: // 128 //
139
-                return 'E_COMPILE_WARNING';
140
-            case E_USER_ERROR: // 256 //
141
-                return 'E_USER_ERROR';
142
-            case E_USER_WARNING: // 512 //
143
-                return 'E_USER_WARNING';
144
-            case E_USER_NOTICE: // 1024 //
145
-                return 'E_USER_NOTICE';
146
-            case E_STRICT: // 2048 //
147
-                return 'E_STRICT';
148
-            case E_RECOVERABLE_ERROR: // 4096 //
149
-                return 'E_RECOVERABLE_ERROR';
150
-            case E_DEPRECATED: // 8192 //
151
-                return 'E_DEPRECATED';
152
-            case E_USER_DEPRECATED: // 16384 //
153
-                return 'E_USER_DEPRECATED';
154
-            case E_ALL: // 16384 //
155
-                return 'E_ALL';
156
-        }
157
-        return '';
158
-    }
159
-
160
-
161
-    /**
162
-     *    fatal_error_handler
163
-     *
164
-     * @return void
165
-     */
166
-    public static function fatal_error_handler()
167
-    {
168
-        $last_error = error_get_last();
169
-        if ($last_error['type'] === E_ERROR) {
170
-            EE_Error::error_handler(E_ERROR, $last_error['message'], $last_error['file'], $last_error['line']);
171
-        }
172
-    }
173
-
174
-
175
-    /**
176
-     * _format_error
177
-     *
178
-     * @param $code
179
-     * @param $message
180
-     * @param $file
181
-     * @param $line
182
-     * @return string
183
-     */
184
-    private static function _format_error($code, $message, $file, $line)
185
-    {
186
-        $html = "<table cellpadding='5'><thead bgcolor='#f8f8f8'><th>Item</th><th align='left'>Details</th></thead><tbody>";
187
-        $html .= "<tr valign='top'><td><b>Code</b></td><td>$code</td></tr>";
188
-        $html .= "<tr valign='top'><td><b>Error</b></td><td>$message</td></tr>";
189
-        $html .= "<tr valign='top'><td><b>File</b></td><td>$file</td></tr>";
190
-        $html .= "<tr valign='top'><td><b>Line</b></td><td>$line</td></tr>";
191
-        $html .= '</tbody></table>';
192
-        return $html;
193
-    }
194
-
195
-
196
-    /**
197
-     * set_content_type
198
-     *
199
-     * @param $content_type
200
-     * @return string
201
-     */
202
-    public static function set_content_type($content_type)
203
-    {
204
-        return 'text/html';
205
-    }
206
-
207
-
208
-    /**
209
-     * @return void
210
-     * @throws EE_Error
211
-     * @throws ReflectionException
212
-     */
213
-    public function get_error()
214
-    {
215
-        if (apply_filters('FHEE__EE_Error__get_error__show_normal_exceptions', false)) {
216
-            throw $this;
217
-        }
218
-        // get separate user and developer messages if they exist
219
-        $msg = explode('||', $this->getMessage());
220
-        $user_msg = $msg[0];
221
-        $dev_msg = isset($msg[1]) ? $msg[1] : $msg[0];
222
-        $msg = WP_DEBUG ? $dev_msg : $user_msg;
223
-        // add details to _all_exceptions array
224
-        $x_time = time();
225
-        self::$_all_exceptions[ $x_time ]['name'] = get_class($this);
226
-        self::$_all_exceptions[ $x_time ]['file'] = $this->getFile();
227
-        self::$_all_exceptions[ $x_time ]['line'] = $this->getLine();
228
-        self::$_all_exceptions[ $x_time ]['msg'] = $msg;
229
-        self::$_all_exceptions[ $x_time ]['code'] = $this->getCode();
230
-        self::$_all_exceptions[ $x_time ]['trace'] = $this->getTrace();
231
-        self::$_all_exceptions[ $x_time ]['string'] = $this->getTraceAsString();
232
-        self::$_error_count++;
233
-        // add_action( 'shutdown', array( $this, 'display_errors' ));
234
-        $this->display_errors();
235
-    }
236
-
237
-
238
-    /**
239
-     * @param bool   $check_stored
240
-     * @param string $type_to_check
241
-     * @return bool
242
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
243
-     * @throws \InvalidArgumentException
244
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
245
-     * @throws InvalidInterfaceException
246
-     */
247
-    public static function has_error($check_stored = false, $type_to_check = 'errors')
248
-    {
249
-        $has_error = isset(self::$_espresso_notices[ $type_to_check ])
250
-                     && ! empty(self::$_espresso_notices[ $type_to_check ])
251
-            ? true
252
-            : false;
253
-        if ($check_stored && ! $has_error) {
254
-            $notices = EE_Error::getStoredNotices();
255
-            foreach ($notices as $type => $notice) {
256
-                if ($type === $type_to_check && $notice) {
257
-                    return true;
258
-                }
259
-            }
260
-        }
261
-        return $has_error;
262
-    }
263
-
264
-
265
-    /**
266
-     * @echo string
267
-     * @throws \ReflectionException
268
-     */
269
-    public function display_errors()
270
-    {
271
-        $trace_details = '';
272
-        $output = '
28
+	const OPTIONS_KEY_NOTICES = 'ee_notices';
29
+
30
+
31
+	/**
32
+	 * name of the file to log exceptions to
33
+	 *
34
+	 * @var string
35
+	 */
36
+	private static $_exception_log_file = 'espresso_error_log.txt';
37
+
38
+	/**
39
+	 *    stores details for all exception
40
+	 *
41
+	 * @var array
42
+	 */
43
+	private static $_all_exceptions = array();
44
+
45
+	/**
46
+	 *    tracks number of errors
47
+	 *
48
+	 * @var int
49
+	 */
50
+	private static $_error_count = 0;
51
+
52
+	/**
53
+	 * @var array $_espresso_notices
54
+	 */
55
+	private static $_espresso_notices = array('success' => false, 'errors' => false, 'attention' => false);
56
+
57
+
58
+	/**
59
+	 * @override default exception handling
60
+	 * @param string         $message
61
+	 * @param int            $code
62
+	 * @param Exception|null $previous
63
+	 */
64
+	public function __construct($message, $code = 0, Exception $previous = null)
65
+	{
66
+		if (version_compare(PHP_VERSION, '5.3.0', '<')) {
67
+			parent::__construct($message, $code);
68
+		} else {
69
+			parent::__construct($message, $code, $previous);
70
+		}
71
+	}
72
+
73
+
74
+	/**
75
+	 *    error_handler
76
+	 *
77
+	 * @param $code
78
+	 * @param $message
79
+	 * @param $file
80
+	 * @param $line
81
+	 * @return void
82
+	 */
83
+	public static function error_handler($code, $message, $file, $line)
84
+	{
85
+		$type = EE_Error::error_type($code);
86
+		$site = site_url();
87
+		switch ($site) {
88
+			case 'http://ee4.eventespresso.com/':
89
+			case 'http://ee4decaf.eventespresso.com/':
90
+			case 'http://ee4hf.eventespresso.com/':
91
+			case 'http://ee4a.eventespresso.com/':
92
+			case 'http://ee4ad.eventespresso.com/':
93
+			case 'http://ee4b.eventespresso.com/':
94
+			case 'http://ee4bd.eventespresso.com/':
95
+			case 'http://ee4d.eventespresso.com/':
96
+			case 'http://ee4dd.eventespresso.com/':
97
+				$to = '[email protected]';
98
+				break;
99
+			default:
100
+				$to = get_option('admin_email');
101
+		}
102
+		$subject = $type . ' ' . $message . ' in ' . EVENT_ESPRESSO_VERSION . ' on ' . site_url();
103
+		$msg = EE_Error::_format_error($type, $message, $file, $line);
104
+		if (function_exists('wp_mail')) {
105
+			add_filter('wp_mail_content_type', array('EE_Error', 'set_content_type'));
106
+			wp_mail($to, $subject, $msg);
107
+		}
108
+		echo '<div id="message" class="espresso-notices error"><p>';
109
+		echo $type . ': ' . $message . '<br />' . $file . ' line ' . $line;
110
+		echo '<br /></p></div>';
111
+	}
112
+
113
+
114
+	/**
115
+	 * error_type
116
+	 * http://www.php.net/manual/en/errorfunc.constants.php#109430
117
+	 *
118
+	 * @param $code
119
+	 * @return string
120
+	 */
121
+	public static function error_type($code)
122
+	{
123
+		switch ($code) {
124
+			case E_ERROR: // 1 //
125
+				return 'E_ERROR';
126
+			case E_WARNING: // 2 //
127
+				return 'E_WARNING';
128
+			case E_PARSE: // 4 //
129
+				return 'E_PARSE';
130
+			case E_NOTICE: // 8 //
131
+				return 'E_NOTICE';
132
+			case E_CORE_ERROR: // 16 //
133
+				return 'E_CORE_ERROR';
134
+			case E_CORE_WARNING: // 32 //
135
+				return 'E_CORE_WARNING';
136
+			case E_COMPILE_ERROR: // 64 //
137
+				return 'E_COMPILE_ERROR';
138
+			case E_COMPILE_WARNING: // 128 //
139
+				return 'E_COMPILE_WARNING';
140
+			case E_USER_ERROR: // 256 //
141
+				return 'E_USER_ERROR';
142
+			case E_USER_WARNING: // 512 //
143
+				return 'E_USER_WARNING';
144
+			case E_USER_NOTICE: // 1024 //
145
+				return 'E_USER_NOTICE';
146
+			case E_STRICT: // 2048 //
147
+				return 'E_STRICT';
148
+			case E_RECOVERABLE_ERROR: // 4096 //
149
+				return 'E_RECOVERABLE_ERROR';
150
+			case E_DEPRECATED: // 8192 //
151
+				return 'E_DEPRECATED';
152
+			case E_USER_DEPRECATED: // 16384 //
153
+				return 'E_USER_DEPRECATED';
154
+			case E_ALL: // 16384 //
155
+				return 'E_ALL';
156
+		}
157
+		return '';
158
+	}
159
+
160
+
161
+	/**
162
+	 *    fatal_error_handler
163
+	 *
164
+	 * @return void
165
+	 */
166
+	public static function fatal_error_handler()
167
+	{
168
+		$last_error = error_get_last();
169
+		if ($last_error['type'] === E_ERROR) {
170
+			EE_Error::error_handler(E_ERROR, $last_error['message'], $last_error['file'], $last_error['line']);
171
+		}
172
+	}
173
+
174
+
175
+	/**
176
+	 * _format_error
177
+	 *
178
+	 * @param $code
179
+	 * @param $message
180
+	 * @param $file
181
+	 * @param $line
182
+	 * @return string
183
+	 */
184
+	private static function _format_error($code, $message, $file, $line)
185
+	{
186
+		$html = "<table cellpadding='5'><thead bgcolor='#f8f8f8'><th>Item</th><th align='left'>Details</th></thead><tbody>";
187
+		$html .= "<tr valign='top'><td><b>Code</b></td><td>$code</td></tr>";
188
+		$html .= "<tr valign='top'><td><b>Error</b></td><td>$message</td></tr>";
189
+		$html .= "<tr valign='top'><td><b>File</b></td><td>$file</td></tr>";
190
+		$html .= "<tr valign='top'><td><b>Line</b></td><td>$line</td></tr>";
191
+		$html .= '</tbody></table>';
192
+		return $html;
193
+	}
194
+
195
+
196
+	/**
197
+	 * set_content_type
198
+	 *
199
+	 * @param $content_type
200
+	 * @return string
201
+	 */
202
+	public static function set_content_type($content_type)
203
+	{
204
+		return 'text/html';
205
+	}
206
+
207
+
208
+	/**
209
+	 * @return void
210
+	 * @throws EE_Error
211
+	 * @throws ReflectionException
212
+	 */
213
+	public function get_error()
214
+	{
215
+		if (apply_filters('FHEE__EE_Error__get_error__show_normal_exceptions', false)) {
216
+			throw $this;
217
+		}
218
+		// get separate user and developer messages if they exist
219
+		$msg = explode('||', $this->getMessage());
220
+		$user_msg = $msg[0];
221
+		$dev_msg = isset($msg[1]) ? $msg[1] : $msg[0];
222
+		$msg = WP_DEBUG ? $dev_msg : $user_msg;
223
+		// add details to _all_exceptions array
224
+		$x_time = time();
225
+		self::$_all_exceptions[ $x_time ]['name'] = get_class($this);
226
+		self::$_all_exceptions[ $x_time ]['file'] = $this->getFile();
227
+		self::$_all_exceptions[ $x_time ]['line'] = $this->getLine();
228
+		self::$_all_exceptions[ $x_time ]['msg'] = $msg;
229
+		self::$_all_exceptions[ $x_time ]['code'] = $this->getCode();
230
+		self::$_all_exceptions[ $x_time ]['trace'] = $this->getTrace();
231
+		self::$_all_exceptions[ $x_time ]['string'] = $this->getTraceAsString();
232
+		self::$_error_count++;
233
+		// add_action( 'shutdown', array( $this, 'display_errors' ));
234
+		$this->display_errors();
235
+	}
236
+
237
+
238
+	/**
239
+	 * @param bool   $check_stored
240
+	 * @param string $type_to_check
241
+	 * @return bool
242
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
243
+	 * @throws \InvalidArgumentException
244
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
245
+	 * @throws InvalidInterfaceException
246
+	 */
247
+	public static function has_error($check_stored = false, $type_to_check = 'errors')
248
+	{
249
+		$has_error = isset(self::$_espresso_notices[ $type_to_check ])
250
+					 && ! empty(self::$_espresso_notices[ $type_to_check ])
251
+			? true
252
+			: false;
253
+		if ($check_stored && ! $has_error) {
254
+			$notices = EE_Error::getStoredNotices();
255
+			foreach ($notices as $type => $notice) {
256
+				if ($type === $type_to_check && $notice) {
257
+					return true;
258
+				}
259
+			}
260
+		}
261
+		return $has_error;
262
+	}
263
+
264
+
265
+	/**
266
+	 * @echo string
267
+	 * @throws \ReflectionException
268
+	 */
269
+	public function display_errors()
270
+	{
271
+		$trace_details = '';
272
+		$output = '
273 273
 <style type="text/css">
274 274
 	#ee-error-message {
275 275
 		max-width:90% !important;
@@ -325,21 +325,21 @@  discard block
 block discarded – undo
325 325
 	}
326 326
 </style>
327 327
 <div id="ee-error-message" class="error">';
328
-        if (! WP_DEBUG) {
329
-            $output .= '
328
+		if (! WP_DEBUG) {
329
+			$output .= '
330 330
 	<p>';
331
-        }
332
-        // cycle thru errors
333
-        foreach (self::$_all_exceptions as $time => $ex) {
334
-            $error_code = '';
335
-            // process trace info
336
-            if (empty($ex['trace'])) {
337
-                $trace_details .= __(
338
-                    'Sorry, but no trace information was available for this exception.',
339
-                    'event_espresso'
340
-                );
341
-            } else {
342
-                $trace_details .= '
331
+		}
332
+		// cycle thru errors
333
+		foreach (self::$_all_exceptions as $time => $ex) {
334
+			$error_code = '';
335
+			// process trace info
336
+			if (empty($ex['trace'])) {
337
+				$trace_details .= __(
338
+					'Sorry, but no trace information was available for this exception.',
339
+					'event_espresso'
340
+				);
341
+			} else {
342
+				$trace_details .= '
343 343
 			<div id="ee-trace-details">
344 344
 			<table width="100%" border="0" cellpadding="5" cellspacing="0">
345 345
 				<tr>
@@ -349,43 +349,43 @@  discard block
 block discarded – undo
349 349
 					<th scope="col" align="left">Class</th>
350 350
 					<th scope="col" align="left">Method( arguments )</th>
351 351
 				</tr>';
352
-                $last_on_stack = count($ex['trace']) - 1;
353
-                // reverse array so that stack is in proper chronological order
354
-                $sorted_trace = array_reverse($ex['trace']);
355
-                foreach ($sorted_trace as $nmbr => $trace) {
356
-                    $file = isset($trace['file']) ? $trace['file'] : '';
357
-                    $class = isset($trace['class']) ? $trace['class'] : '';
358
-                    $type = isset($trace['type']) ? $trace['type'] : '';
359
-                    $function = isset($trace['function']) ? $trace['function'] : '';
360
-                    $args = isset($trace['args']) ? $this->_convert_args_to_string($trace['args']) : '';
361
-                    $line = isset($trace['line']) ? $trace['line'] : '';
362
-                    $zebra = ($nmbr % 2) ? ' odd' : '';
363
-                    if (empty($file) && ! empty($class)) {
364
-                        $a = new ReflectionClass($class);
365
-                        $file = $a->getFileName();
366
-                        if (empty($line) && ! empty($function)) {
367
-                            try {
368
-                                // if $function is a closure, this throws an exception
369
-                                $b = new ReflectionMethod($class, $function);
370
-                                $line = $b->getStartLine();
371
-                            } catch (Exception $closure_exception) {
372
-                                $line = 'unknown';
373
-                            }
374
-                        }
375
-                    }
376
-                    if ($nmbr === $last_on_stack) {
377
-                        $file = $ex['file'] !== '' ? $ex['file'] : $file;
378
-                        $line = $ex['line'] !== '' ? $ex['line'] : $line;
379
-                        $error_code = self::generate_error_code($file, $trace['function'], $line);
380
-                    }
381
-                    $nmbr_dsply = ! empty($nmbr) ? $nmbr : '&nbsp;';
382
-                    $line_dsply = ! empty($line) ? $line : '&nbsp;';
383
-                    $file_dsply = ! empty($file) ? $file : '&nbsp;';
384
-                    $class_dsply = ! empty($class) ? $class : '&nbsp;';
385
-                    $type_dsply = ! empty($type) ? $type : '&nbsp;';
386
-                    $function_dsply = ! empty($function) ? $function : '&nbsp;';
387
-                    $args_dsply = ! empty($args) ? '( ' . $args . ' )' : '';
388
-                    $trace_details .= '
352
+				$last_on_stack = count($ex['trace']) - 1;
353
+				// reverse array so that stack is in proper chronological order
354
+				$sorted_trace = array_reverse($ex['trace']);
355
+				foreach ($sorted_trace as $nmbr => $trace) {
356
+					$file = isset($trace['file']) ? $trace['file'] : '';
357
+					$class = isset($trace['class']) ? $trace['class'] : '';
358
+					$type = isset($trace['type']) ? $trace['type'] : '';
359
+					$function = isset($trace['function']) ? $trace['function'] : '';
360
+					$args = isset($trace['args']) ? $this->_convert_args_to_string($trace['args']) : '';
361
+					$line = isset($trace['line']) ? $trace['line'] : '';
362
+					$zebra = ($nmbr % 2) ? ' odd' : '';
363
+					if (empty($file) && ! empty($class)) {
364
+						$a = new ReflectionClass($class);
365
+						$file = $a->getFileName();
366
+						if (empty($line) && ! empty($function)) {
367
+							try {
368
+								// if $function is a closure, this throws an exception
369
+								$b = new ReflectionMethod($class, $function);
370
+								$line = $b->getStartLine();
371
+							} catch (Exception $closure_exception) {
372
+								$line = 'unknown';
373
+							}
374
+						}
375
+					}
376
+					if ($nmbr === $last_on_stack) {
377
+						$file = $ex['file'] !== '' ? $ex['file'] : $file;
378
+						$line = $ex['line'] !== '' ? $ex['line'] : $line;
379
+						$error_code = self::generate_error_code($file, $trace['function'], $line);
380
+					}
381
+					$nmbr_dsply = ! empty($nmbr) ? $nmbr : '&nbsp;';
382
+					$line_dsply = ! empty($line) ? $line : '&nbsp;';
383
+					$file_dsply = ! empty($file) ? $file : '&nbsp;';
384
+					$class_dsply = ! empty($class) ? $class : '&nbsp;';
385
+					$type_dsply = ! empty($type) ? $type : '&nbsp;';
386
+					$function_dsply = ! empty($function) ? $function : '&nbsp;';
387
+					$args_dsply = ! empty($args) ? '( ' . $args . ' )' : '';
388
+					$trace_details .= '
389 389
 					<tr>
390 390
 						<td align="right" class="' . $zebra . '">' . $nmbr_dsply . '</td>
391 391
 						<td align="right" class="' . $zebra . '">' . $line_dsply . '</td>
@@ -393,626 +393,626 @@  discard block
 block discarded – undo
393 393
 						<td align="left" class="' . $zebra . '">' . $class_dsply . '</td>
394 394
 						<td align="left" class="' . $zebra . '">' . $type_dsply . $function_dsply . $args_dsply . '</td>
395 395
 					</tr>';
396
-                }
397
-                $trace_details .= '
396
+				}
397
+				$trace_details .= '
398 398
 			 </table>
399 399
 			</div>';
400
-            }
401
-            $ex['code'] = $ex['code'] ? $ex['code'] : $error_code;
402
-            // add generic non-identifying messages for non-privileged users
403
-            if (! WP_DEBUG) {
404
-                $output .= '<span class="ee-error-user-msg-spn">'
405
-                           . trim($ex['msg'])
406
-                           . '</span> &nbsp; <sup>'
407
-                           . $ex['code']
408
-                           . '</sup><br />';
409
-            } else {
410
-                // or helpful developer messages if debugging is on
411
-                $output .= '
400
+			}
401
+			$ex['code'] = $ex['code'] ? $ex['code'] : $error_code;
402
+			// add generic non-identifying messages for non-privileged users
403
+			if (! WP_DEBUG) {
404
+				$output .= '<span class="ee-error-user-msg-spn">'
405
+						   . trim($ex['msg'])
406
+						   . '</span> &nbsp; <sup>'
407
+						   . $ex['code']
408
+						   . '</sup><br />';
409
+			} else {
410
+				// or helpful developer messages if debugging is on
411
+				$output .= '
412 412
 		<div class="ee-error-dev-msg-dv">
413 413
 			<p class="ee-error-dev-msg-pg">
414 414
 				<strong class="ee-error-dev-msg-str">An '
415
-                           . $ex['name']
416
-                           . ' exception was thrown!</strong>  &nbsp; <span>code: '
417
-                           . $ex['code']
418
-                           . '</span><br />
415
+						   . $ex['name']
416
+						   . ' exception was thrown!</strong>  &nbsp; <span>code: '
417
+						   . $ex['code']
418
+						   . '</span><br />
419 419
 				<span class="big-text">"'
420
-                           . trim($ex['msg'])
421
-                           . '"</span><br/>
420
+						   . trim($ex['msg'])
421
+						   . '"</span><br/>
422 422
 				<a id="display-ee-error-trace-'
423
-                           . self::$_error_count
424
-                           . $time
425
-                           . '" class="display-ee-error-trace-lnk small-text" rel="ee-error-trace-'
426
-                           . self::$_error_count
427
-                           . $time
428
-                           . '">
423
+						   . self::$_error_count
424
+						   . $time
425
+						   . '" class="display-ee-error-trace-lnk small-text" rel="ee-error-trace-'
426
+						   . self::$_error_count
427
+						   . $time
428
+						   . '">
429 429
 					'
430
-                           . __('click to view backtrace and class/method details', 'event_espresso')
431
-                           . '
430
+						   . __('click to view backtrace and class/method details', 'event_espresso')
431
+						   . '
432 432
 				</a><br />
433 433
 				<span class="small-text lt-grey-text">'
434
-                           . $ex['file']
435
-                           . ' &nbsp; ( line no: '
436
-                           . $ex['line']
437
-                           . ' )</span>
434
+						   . $ex['file']
435
+						   . ' &nbsp; ( line no: '
436
+						   . $ex['line']
437
+						   . ' )</span>
438 438
 			</p>
439 439
 			<div id="ee-error-trace-'
440
-                           . self::$_error_count
441
-                           . $time
442
-                           . '-dv" class="ee-error-trace-dv" style="display: none;">
440
+						   . self::$_error_count
441
+						   . $time
442
+						   . '-dv" class="ee-error-trace-dv" style="display: none;">
443 443
 				'
444
-                           . $trace_details;
445
-                if (! empty($class)) {
446
-                    $output .= '
444
+						   . $trace_details;
445
+				if (! empty($class)) {
446
+					$output .= '
447 447
 				<div style="padding:3px; margin:0 0 1em; border:1px solid #666; background:#fff; border-radius:3px;">
448 448
 					<div style="padding:1em 2em; border:1px solid #666; background:#f9f9f9;">
449 449
 						<h3>Class Details</h3>';
450
-                    $a = new ReflectionClass($class);
451
-                    $output .= '
450
+					$a = new ReflectionClass($class);
451
+					$output .= '
452 452
 						<pre>' . $a . '</pre>
453 453
 					</div>
454 454
 				</div>';
455
-                }
456
-                $output .= '
455
+				}
456
+				$output .= '
457 457
 			</div>
458 458
 		</div>
459 459
 		<br />';
460
-            }
461
-            $this->write_to_error_log($time, $ex);
462
-        }
463
-        // remove last linebreak
464
-        $output = substr($output, 0, -6);
465
-        if (! WP_DEBUG) {
466
-            $output .= '
460
+			}
461
+			$this->write_to_error_log($time, $ex);
462
+		}
463
+		// remove last linebreak
464
+		$output = substr($output, 0, -6);
465
+		if (! WP_DEBUG) {
466
+			$output .= '
467 467
 	</p>';
468
-        }
469
-        $output .= '
468
+		}
469
+		$output .= '
470 470
 </div>';
471
-        $output .= self::_print_scripts(true);
472
-        if (defined('DOING_AJAX')) {
473
-            echo wp_json_encode(array('error' => $output));
474
-            exit();
475
-        }
476
-        echo $output;
477
-        die();
478
-    }
479
-
480
-
481
-    /**
482
-     *    generate string from exception trace args
483
-     *
484
-     * @param array $arguments
485
-     * @param bool  $array
486
-     * @return string
487
-     */
488
-    private function _convert_args_to_string($arguments = array(), $array = false)
489
-    {
490
-        $arg_string = '';
491
-        if (! empty($arguments)) {
492
-            $args = array();
493
-            foreach ($arguments as $arg) {
494
-                if (! empty($arg)) {
495
-                    if (is_string($arg)) {
496
-                        $args[] = " '" . $arg . "'";
497
-                    } elseif (is_array($arg)) {
498
-                        $args[] = 'ARRAY(' . $this->_convert_args_to_string($arg, true);
499
-                    } elseif ($arg === null) {
500
-                        $args[] = ' NULL';
501
-                    } elseif (is_bool($arg)) {
502
-                        $args[] = ($arg) ? ' TRUE' : ' FALSE';
503
-                    } elseif (is_object($arg)) {
504
-                        $args[] = ' OBJECT ' . get_class($arg);
505
-                    } elseif (is_resource($arg)) {
506
-                        $args[] = get_resource_type($arg);
507
-                    } else {
508
-                        $args[] = $arg;
509
-                    }
510
-                }
511
-            }
512
-            $arg_string = implode(', ', $args);
513
-        }
514
-        if ($array) {
515
-            $arg_string .= ' )';
516
-        }
517
-        return $arg_string;
518
-    }
519
-
520
-
521
-    /**
522
-     *    add error message
523
-     *
524
-     * @param        string $msg  the message to display to users or developers - adding a double pipe || (OR) creates
525
-     *                            separate messages for user || dev
526
-     * @param        string $file the file that the error occurred in - just use __FILE__
527
-     * @param        string $func the function/method that the error occurred in - just use __FUNCTION__
528
-     * @param        string $line the line number where the error occurred - just use __LINE__
529
-     * @return        void
530
-     */
531
-    public static function add_error($msg = null, $file = null, $func = null, $line = null)
532
-    {
533
-        self::_add_notice('errors', $msg, $file, $func, $line);
534
-        self::$_error_count++;
535
-    }
536
-
537
-
538
-    /**
539
-     * If WP_DEBUG is active, throws an exception. If WP_DEBUG is off, just
540
-     * adds an error
541
-     *
542
-     * @param string $msg
543
-     * @param string $file
544
-     * @param string $func
545
-     * @param string $line
546
-     * @throws EE_Error
547
-     */
548
-    public static function throw_exception_if_debugging($msg = null, $file = null, $func = null, $line = null)
549
-    {
550
-        if (WP_DEBUG) {
551
-            throw new EE_Error($msg);
552
-        }
553
-        EE_Error::add_error($msg, $file, $func, $line);
554
-    }
555
-
556
-
557
-    /**
558
-     *    add success message
559
-     *
560
-     * @param        string $msg  the message to display to users or developers - adding a double pipe || (OR) creates
561
-     *                            separate messages for user || dev
562
-     * @param        string $file the file that the error occurred in - just use __FILE__
563
-     * @param        string $func the function/method that the error occurred in - just use __FUNCTION__
564
-     * @param        string $line the line number where the error occurred - just use __LINE__
565
-     * @return        void
566
-     */
567
-    public static function add_success($msg = null, $file = null, $func = null, $line = null)
568
-    {
569
-        self::_add_notice('success', $msg, $file, $func, $line);
570
-    }
571
-
572
-
573
-    /**
574
-     *    add attention message
575
-     *
576
-     * @param        string $msg  the message to display to users or developers - adding a double pipe || (OR) creates
577
-     *                            separate messages for user || dev
578
-     * @param        string $file the file that the error occurred in - just use __FILE__
579
-     * @param        string $func the function/method that the error occurred in - just use __FUNCTION__
580
-     * @param        string $line the line number where the error occurred - just use __LINE__
581
-     * @return        void
582
-     */
583
-    public static function add_attention($msg = null, $file = null, $func = null, $line = null)
584
-    {
585
-        self::_add_notice('attention', $msg, $file, $func, $line);
586
-    }
587
-
588
-
589
-    /**
590
-     * @param string $type whether the message is for a success or error notification
591
-     * @param string $msg  the message to display to users or developers
592
-     *                     - adding a double pipe || (OR) creates separate messages for user || dev
593
-     * @param string $file the file that the error occurred in - just use __FILE__
594
-     * @param string $func the function/method that the error occurred in - just use __FUNCTION__
595
-     * @param string $line the line number where the error occurred - just use __LINE__
596
-     * @return void
597
-     */
598
-    private static function _add_notice($type = 'success', $msg = '', $file = '', $func = '', $line = '')
599
-    {
600
-        if (empty($msg)) {
601
-            EE_Error::doing_it_wrong(
602
-                'EE_Error::add_' . $type . '()',
603
-                sprintf(
604
-                    __(
605
-                        'Notifications are not much use without a message! Please add a message to the EE_Error::add_%s() call made in %s on line %d',
606
-                        'event_espresso'
607
-                    ),
608
-                    $type,
609
-                    $file,
610
-                    $line
611
-                ),
612
-                EVENT_ESPRESSO_VERSION
613
-            );
614
-        }
615
-        if ($type === 'errors' && (empty($file) || empty($func) || empty($line))) {
616
-            EE_Error::doing_it_wrong(
617
-                'EE_Error::add_error()',
618
-                __(
619
-                    'You need to provide the file name, function name, and line number that the error occurred on in order to better assist with debugging.',
620
-                    'event_espresso'
621
-                ),
622
-                EVENT_ESPRESSO_VERSION
623
-            );
624
-        }
625
-        // get separate user and developer messages if they exist
626
-        $msg = explode('||', $msg);
627
-        $user_msg = $msg[0];
628
-        $dev_msg = isset($msg[1]) ? $msg[1] : $msg[0];
629
-        /**
630
-         * Do an action so other code can be triggered when a notice is created
631
-         *
632
-         * @param string $type     can be 'errors', 'attention', or 'success'
633
-         * @param string $user_msg message displayed to user when WP_DEBUG is off
634
-         * @param string $user_msg message displayed to user when WP_DEBUG is on
635
-         * @param string $file     file where error was generated
636
-         * @param string $func     function where error was generated
637
-         * @param string $line     line where error was generated
638
-         */
639
-        do_action('AHEE__EE_Error___add_notice', $type, $user_msg, $dev_msg, $file, $func, $line);
640
-        $msg = WP_DEBUG ? $dev_msg : $user_msg;
641
-        // add notice if message exists
642
-        if (! empty($msg)) {
643
-            // get error code
644
-            $notice_code = EE_Error::generate_error_code($file, $func, $line);
645
-            if (WP_DEBUG && $type === 'errors') {
646
-                $msg .= '<br/><span class="tiny-text">' . $notice_code . '</span>';
647
-            }
648
-            // add notice. Index by code if it's not blank
649
-            if ($notice_code) {
650
-                self::$_espresso_notices[ $type ][ $notice_code ] = $msg;
651
-            } else {
652
-                self::$_espresso_notices[ $type ][] = $msg;
653
-            }
654
-            add_action('wp_footer', array('EE_Error', 'enqueue_error_scripts'), 1);
655
-        }
656
-    }
657
-
658
-
659
-    /**
660
-     * in some case it may be necessary to overwrite the existing success messages
661
-     *
662
-     * @return        void
663
-     */
664
-    public static function overwrite_success()
665
-    {
666
-        self::$_espresso_notices['success'] = false;
667
-    }
668
-
669
-
670
-    /**
671
-     * in some case it may be necessary to overwrite the existing attention messages
672
-     *
673
-     * @return void
674
-     */
675
-    public static function overwrite_attention()
676
-    {
677
-        self::$_espresso_notices['attention'] = false;
678
-    }
679
-
680
-
681
-    /**
682
-     * in some case it may be necessary to overwrite the existing error messages
683
-     *
684
-     * @return void
685
-     */
686
-    public static function overwrite_errors()
687
-    {
688
-        self::$_espresso_notices['errors'] = false;
689
-    }
690
-
691
-
692
-    /**
693
-     * @return void
694
-     */
695
-    public static function reset_notices()
696
-    {
697
-        self::$_espresso_notices['success'] = false;
698
-        self::$_espresso_notices['attention'] = false;
699
-        self::$_espresso_notices['errors'] = false;
700
-    }
701
-
702
-
703
-    /**
704
-     * @return int
705
-     */
706
-    public static function has_notices()
707
-    {
708
-        $has_notices = 0;
709
-        // check for success messages
710
-        $has_notices = self::$_espresso_notices['success'] && ! empty(self::$_espresso_notices['success'])
711
-            ? 3
712
-            : $has_notices;
713
-        // check for attention messages
714
-        $has_notices = self::$_espresso_notices['attention'] && ! empty(self::$_espresso_notices['attention'])
715
-            ? 2
716
-            : $has_notices;
717
-        // check for error messages
718
-        $has_notices = self::$_espresso_notices['errors'] && ! empty(self::$_espresso_notices['errors'])
719
-            ? 1
720
-            : $has_notices;
721
-        return $has_notices;
722
-    }
723
-
724
-
725
-    /**
726
-     * This simply returns non formatted error notices as they were sent into the EE_Error object.
727
-     *
728
-     * @since 4.9.0
729
-     * @return array
730
-     */
731
-    public static function get_vanilla_notices()
732
-    {
733
-        return array(
734
-            'success'   => isset(self::$_espresso_notices['success'])
735
-                ? self::$_espresso_notices['success']
736
-                : array(),
737
-            'attention' => isset(self::$_espresso_notices['attention'])
738
-                ? self::$_espresso_notices['attention']
739
-                : array(),
740
-            'errors'    => isset(self::$_espresso_notices['errors'])
741
-                ? self::$_espresso_notices['errors']
742
-                : array(),
743
-        );
744
-    }
745
-
746
-
747
-    /**
748
-     * @return array
749
-     * @throws InvalidArgumentException
750
-     * @throws InvalidDataTypeException
751
-     * @throws InvalidInterfaceException
752
-     */
753
-    public static function getStoredNotices()
754
-    {
755
-        if ($user_id = get_current_user_id()) {
756
-            // get notices for logged in user
757
-            $notices = get_user_option(EE_Error::OPTIONS_KEY_NOTICES, $user_id);
758
-            return is_array($notices) ? $notices : array();
759
-        }
760
-        if (EE_Session::isLoadedAndActive()) {
761
-            // get notices for user currently engaged in a session
762
-            $session_data = EE_Session::instance()->get_session_data(EE_Error::OPTIONS_KEY_NOTICES);
763
-            return is_array($session_data) ? $session_data : array();
764
-        }
765
-        // get global notices and hope they apply to the current site visitor
766
-        $notices = get_option(EE_Error::OPTIONS_KEY_NOTICES, array());
767
-        return is_array($notices) ? $notices : array();
768
-    }
769
-
770
-
771
-    /**
772
-     * @param array $notices
773
-     * @return bool
774
-     * @throws InvalidArgumentException
775
-     * @throws InvalidDataTypeException
776
-     * @throws InvalidInterfaceException
777
-     */
778
-    public static function storeNotices(array $notices)
779
-    {
780
-        if ($user_id = get_current_user_id()) {
781
-            // store notices for logged in user
782
-            return (bool) update_user_option(
783
-                $user_id,
784
-                EE_Error::OPTIONS_KEY_NOTICES,
785
-                $notices
786
-            );
787
-        }
788
-        if (EE_Session::isLoadedAndActive()) {
789
-            // store notices for user currently engaged in a session
790
-            return EE_Session::instance()->set_session_data(
791
-                array(EE_Error::OPTIONS_KEY_NOTICES => $notices)
792
-            );
793
-        }
794
-        // store global notices and hope they apply to the same site visitor on the next request
795
-        return update_option(EE_Error::OPTIONS_KEY_NOTICES, $notices);
796
-    }
797
-
798
-
799
-    /**
800
-     * @return bool|TRUE
801
-     * @throws InvalidArgumentException
802
-     * @throws InvalidDataTypeException
803
-     * @throws InvalidInterfaceException
804
-     */
805
-    public static function clearNotices()
806
-    {
807
-        if ($user_id = get_current_user_id()) {
808
-            // clear notices for logged in user
809
-            return (bool) update_user_option(
810
-                $user_id,
811
-                EE_Error::OPTIONS_KEY_NOTICES,
812
-                array()
813
-            );
814
-        }
815
-        if (EE_Session::isLoadedAndActive()) {
816
-            // clear notices for user currently engaged in a session
817
-            return EE_Session::instance()->reset_data(EE_Error::OPTIONS_KEY_NOTICES);
818
-        }
819
-        // clear global notices and hope none belonged to some for some other site visitor
820
-        return update_option(EE_Error::OPTIONS_KEY_NOTICES, array());
821
-    }
822
-
823
-
824
-    /**
825
-     * saves notices to the db for retrieval on next request
826
-     *
827
-     * @return void
828
-     * @throws InvalidArgumentException
829
-     * @throws InvalidDataTypeException
830
-     * @throws InvalidInterfaceException
831
-     */
832
-    public static function stashNoticesBeforeRedirect()
833
-    {
834
-        EE_Error::get_notices(false, true);
835
-    }
836
-
837
-
838
-    /**
839
-     * compile all error or success messages into one string
840
-     *
841
-     * @see EE_Error::get_raw_notices if you want the raw notices without any preparations made to them
842
-     * @param boolean $format_output            whether or not to format the messages for display in the WP admin
843
-     * @param boolean $save_to_transient        whether or not to save notices to the db for retrieval on next request
844
-     *                                          - ONLY do this just before redirecting
845
-     * @param boolean $remove_empty             whether or not to unset empty messages
846
-     * @return array
847
-     * @throws InvalidArgumentException
848
-     * @throws InvalidDataTypeException
849
-     * @throws InvalidInterfaceException
850
-     */
851
-    public static function get_notices($format_output = true, $save_to_transient = false, $remove_empty = true)
852
-    {
853
-        $success_messages = '';
854
-        $attention_messages = '';
855
-        $error_messages = '';
856
-        // either save notices to the db
857
-        if ($save_to_transient || isset($_REQUEST['activate-selected'])) {
858
-            self::$_espresso_notices = array_merge(
859
-                EE_Error::getStoredNotices(),
860
-                self::$_espresso_notices
861
-            );
862
-            EE_Error::storeNotices(self::$_espresso_notices);
863
-            return array();
864
-        }
865
-        $print_scripts = EE_Error::combineExistingAndNewNotices();
866
-        // check for success messages
867
-        if (self::$_espresso_notices['success'] && ! empty(self::$_espresso_notices['success'])) {
868
-            // combine messages
869
-            $success_messages .= implode('<br />', self::$_espresso_notices['success']);
870
-            $print_scripts = true;
871
-        }
872
-        // check for attention messages
873
-        if (self::$_espresso_notices['attention'] && ! empty(self::$_espresso_notices['attention'])) {
874
-            // combine messages
875
-            $attention_messages .= implode('<br />', self::$_espresso_notices['attention']);
876
-            $print_scripts = true;
877
-        }
878
-        // check for error messages
879
-        if (self::$_espresso_notices['errors'] && ! empty(self::$_espresso_notices['errors'])) {
880
-            $error_messages .= count(self::$_espresso_notices['errors']) > 1
881
-                ? __('The following errors have occurred:<br />', 'event_espresso')
882
-                : __('An error has occurred:<br />', 'event_espresso');
883
-            // combine messages
884
-            $error_messages .= implode('<br />', self::$_espresso_notices['errors']);
885
-            $print_scripts = true;
886
-        }
887
-        if ($format_output) {
888
-            $notices = EE_Error::formatNoticesOutput(
889
-                $success_messages,
890
-                $attention_messages,
891
-                $error_messages
892
-            );
893
-        } else {
894
-            $notices = array(
895
-                'success'   => $success_messages,
896
-                'attention' => $attention_messages,
897
-                'errors'    => $error_messages,
898
-            );
899
-            if ($remove_empty) {
900
-                // remove empty notices
901
-                foreach ($notices as $type => $notice) {
902
-                    if (empty($notice)) {
903
-                        unset($notices[ $type ]);
904
-                    }
905
-                }
906
-            }
907
-        }
908
-        if ($print_scripts) {
909
-            self::_print_scripts();
910
-        }
911
-        return $notices;
912
-    }
913
-
914
-
915
-    /**
916
-     * @return bool
917
-     * @throws InvalidArgumentException
918
-     * @throws InvalidDataTypeException
919
-     * @throws InvalidInterfaceException
920
-     */
921
-    private static function combineExistingAndNewNotices()
922
-    {
923
-        $print_scripts = false;
924
-        // grab any notices that have been previously saved
925
-        $notices = EE_Error::getStoredNotices();
926
-        if (! empty($notices)) {
927
-            foreach ($notices as $type => $notice) {
928
-                if (is_array($notice) && ! empty($notice)) {
929
-                    // make sure that existing notice type is an array
930
-                    self::$_espresso_notices[ $type ] = is_array(self::$_espresso_notices[ $type ])
931
-                                                        && ! empty(self::$_espresso_notices[ $type ])
932
-                        ? self::$_espresso_notices[ $type ]
933
-                        : array();
934
-                    // add newly created notices to existing ones
935
-                    self::$_espresso_notices[ $type ] += $notice;
936
-                    $print_scripts = true;
937
-                }
938
-            }
939
-            // now clear any stored notices
940
-            EE_Error::clearNotices();
941
-        }
942
-        return $print_scripts;
943
-    }
944
-
945
-
946
-    /**
947
-     * @param string $success_messages
948
-     * @param string $attention_messages
949
-     * @param string $error_messages
950
-     * @return string
951
-     */
952
-    private static function formatNoticesOutput($success_messages, $attention_messages, $error_messages)
953
-    {
954
-        $notices = '<div id="espresso-notices">';
955
-        $close = is_admin()
956
-            ? ''
957
-            : '<a class="close-espresso-notice hide-if-no-js"><span class="dashicons dashicons-no"/></a>';
958
-        if ($success_messages !== '') {
959
-            $css_id = is_admin() ? 'ee-success-message' : 'espresso-notices-success';
960
-            $css_class = is_admin() ? 'updated fade' : 'success fade-away';
961
-            // showMessage( $success_messages );
962
-            $notices .= '<div id="' . $css_id . '" '
963
-                        . 'class="espresso-notices ' . $css_class . '" '
964
-                        . 'style="display:none;">'
965
-                        . '<p>' . $success_messages . '</p>'
966
-                        . $close
967
-                        . '</div>';
968
-        }
969
-        if ($attention_messages !== '') {
970
-            $css_id = is_admin() ? 'ee-attention-message' : 'espresso-notices-attention';
971
-            $css_class = is_admin() ? 'updated ee-notices-attention' : 'attention fade-away';
972
-            // showMessage( $error_messages, TRUE );
973
-            $notices .= '<div id="' . $css_id . '" '
974
-                        . 'class="espresso-notices ' . $css_class . '" '
975
-                        . 'style="display:none;">'
976
-                        . '<p>' . $attention_messages . '</p>'
977
-                        . $close
978
-                        . '</div>';
979
-        }
980
-        if ($error_messages !== '') {
981
-            $css_id = is_admin() ? 'ee-error-message' : 'espresso-notices-error';
982
-            $css_class = is_admin() ? 'error' : 'error fade-away';
983
-            // showMessage( $error_messages, TRUE );
984
-            $notices .= '<div id="' . $css_id . '" '
985
-                        . 'class="espresso-notices ' . $css_class . '" '
986
-                        . 'style="display:none;">'
987
-                        . '<p>' . $error_messages . '</p>'
988
-                        . $close
989
-                        . '</div>';
990
-        }
991
-        $notices .= '</div>';
992
-        return $notices;
993
-    }
994
-
995
-
996
-    /**
997
-     * _print_scripts
998
-     *
999
-     * @param    bool $force_print
1000
-     * @return    string
1001
-     */
1002
-    private static function _print_scripts($force_print = false)
1003
-    {
1004
-        if (! $force_print && (did_action('admin_enqueue_scripts') || did_action('wp_enqueue_scripts'))) {
1005
-            if (wp_script_is('ee_error_js', 'registered')) {
1006
-                wp_enqueue_style('espresso_default');
1007
-                wp_enqueue_style('espresso_custom_css');
1008
-                wp_enqueue_script('ee_error_js');
1009
-            }
1010
-            if (wp_script_is('ee_error_js', 'enqueued')) {
1011
-                wp_localize_script('ee_error_js', 'ee_settings', array('wp_debug' => WP_DEBUG));
1012
-                return '';
1013
-            }
1014
-        } else {
1015
-            return '
471
+		$output .= self::_print_scripts(true);
472
+		if (defined('DOING_AJAX')) {
473
+			echo wp_json_encode(array('error' => $output));
474
+			exit();
475
+		}
476
+		echo $output;
477
+		die();
478
+	}
479
+
480
+
481
+	/**
482
+	 *    generate string from exception trace args
483
+	 *
484
+	 * @param array $arguments
485
+	 * @param bool  $array
486
+	 * @return string
487
+	 */
488
+	private function _convert_args_to_string($arguments = array(), $array = false)
489
+	{
490
+		$arg_string = '';
491
+		if (! empty($arguments)) {
492
+			$args = array();
493
+			foreach ($arguments as $arg) {
494
+				if (! empty($arg)) {
495
+					if (is_string($arg)) {
496
+						$args[] = " '" . $arg . "'";
497
+					} elseif (is_array($arg)) {
498
+						$args[] = 'ARRAY(' . $this->_convert_args_to_string($arg, true);
499
+					} elseif ($arg === null) {
500
+						$args[] = ' NULL';
501
+					} elseif (is_bool($arg)) {
502
+						$args[] = ($arg) ? ' TRUE' : ' FALSE';
503
+					} elseif (is_object($arg)) {
504
+						$args[] = ' OBJECT ' . get_class($arg);
505
+					} elseif (is_resource($arg)) {
506
+						$args[] = get_resource_type($arg);
507
+					} else {
508
+						$args[] = $arg;
509
+					}
510
+				}
511
+			}
512
+			$arg_string = implode(', ', $args);
513
+		}
514
+		if ($array) {
515
+			$arg_string .= ' )';
516
+		}
517
+		return $arg_string;
518
+	}
519
+
520
+
521
+	/**
522
+	 *    add error message
523
+	 *
524
+	 * @param        string $msg  the message to display to users or developers - adding a double pipe || (OR) creates
525
+	 *                            separate messages for user || dev
526
+	 * @param        string $file the file that the error occurred in - just use __FILE__
527
+	 * @param        string $func the function/method that the error occurred in - just use __FUNCTION__
528
+	 * @param        string $line the line number where the error occurred - just use __LINE__
529
+	 * @return        void
530
+	 */
531
+	public static function add_error($msg = null, $file = null, $func = null, $line = null)
532
+	{
533
+		self::_add_notice('errors', $msg, $file, $func, $line);
534
+		self::$_error_count++;
535
+	}
536
+
537
+
538
+	/**
539
+	 * If WP_DEBUG is active, throws an exception. If WP_DEBUG is off, just
540
+	 * adds an error
541
+	 *
542
+	 * @param string $msg
543
+	 * @param string $file
544
+	 * @param string $func
545
+	 * @param string $line
546
+	 * @throws EE_Error
547
+	 */
548
+	public static function throw_exception_if_debugging($msg = null, $file = null, $func = null, $line = null)
549
+	{
550
+		if (WP_DEBUG) {
551
+			throw new EE_Error($msg);
552
+		}
553
+		EE_Error::add_error($msg, $file, $func, $line);
554
+	}
555
+
556
+
557
+	/**
558
+	 *    add success message
559
+	 *
560
+	 * @param        string $msg  the message to display to users or developers - adding a double pipe || (OR) creates
561
+	 *                            separate messages for user || dev
562
+	 * @param        string $file the file that the error occurred in - just use __FILE__
563
+	 * @param        string $func the function/method that the error occurred in - just use __FUNCTION__
564
+	 * @param        string $line the line number where the error occurred - just use __LINE__
565
+	 * @return        void
566
+	 */
567
+	public static function add_success($msg = null, $file = null, $func = null, $line = null)
568
+	{
569
+		self::_add_notice('success', $msg, $file, $func, $line);
570
+	}
571
+
572
+
573
+	/**
574
+	 *    add attention message
575
+	 *
576
+	 * @param        string $msg  the message to display to users or developers - adding a double pipe || (OR) creates
577
+	 *                            separate messages for user || dev
578
+	 * @param        string $file the file that the error occurred in - just use __FILE__
579
+	 * @param        string $func the function/method that the error occurred in - just use __FUNCTION__
580
+	 * @param        string $line the line number where the error occurred - just use __LINE__
581
+	 * @return        void
582
+	 */
583
+	public static function add_attention($msg = null, $file = null, $func = null, $line = null)
584
+	{
585
+		self::_add_notice('attention', $msg, $file, $func, $line);
586
+	}
587
+
588
+
589
+	/**
590
+	 * @param string $type whether the message is for a success or error notification
591
+	 * @param string $msg  the message to display to users or developers
592
+	 *                     - adding a double pipe || (OR) creates separate messages for user || dev
593
+	 * @param string $file the file that the error occurred in - just use __FILE__
594
+	 * @param string $func the function/method that the error occurred in - just use __FUNCTION__
595
+	 * @param string $line the line number where the error occurred - just use __LINE__
596
+	 * @return void
597
+	 */
598
+	private static function _add_notice($type = 'success', $msg = '', $file = '', $func = '', $line = '')
599
+	{
600
+		if (empty($msg)) {
601
+			EE_Error::doing_it_wrong(
602
+				'EE_Error::add_' . $type . '()',
603
+				sprintf(
604
+					__(
605
+						'Notifications are not much use without a message! Please add a message to the EE_Error::add_%s() call made in %s on line %d',
606
+						'event_espresso'
607
+					),
608
+					$type,
609
+					$file,
610
+					$line
611
+				),
612
+				EVENT_ESPRESSO_VERSION
613
+			);
614
+		}
615
+		if ($type === 'errors' && (empty($file) || empty($func) || empty($line))) {
616
+			EE_Error::doing_it_wrong(
617
+				'EE_Error::add_error()',
618
+				__(
619
+					'You need to provide the file name, function name, and line number that the error occurred on in order to better assist with debugging.',
620
+					'event_espresso'
621
+				),
622
+				EVENT_ESPRESSO_VERSION
623
+			);
624
+		}
625
+		// get separate user and developer messages if they exist
626
+		$msg = explode('||', $msg);
627
+		$user_msg = $msg[0];
628
+		$dev_msg = isset($msg[1]) ? $msg[1] : $msg[0];
629
+		/**
630
+		 * Do an action so other code can be triggered when a notice is created
631
+		 *
632
+		 * @param string $type     can be 'errors', 'attention', or 'success'
633
+		 * @param string $user_msg message displayed to user when WP_DEBUG is off
634
+		 * @param string $user_msg message displayed to user when WP_DEBUG is on
635
+		 * @param string $file     file where error was generated
636
+		 * @param string $func     function where error was generated
637
+		 * @param string $line     line where error was generated
638
+		 */
639
+		do_action('AHEE__EE_Error___add_notice', $type, $user_msg, $dev_msg, $file, $func, $line);
640
+		$msg = WP_DEBUG ? $dev_msg : $user_msg;
641
+		// add notice if message exists
642
+		if (! empty($msg)) {
643
+			// get error code
644
+			$notice_code = EE_Error::generate_error_code($file, $func, $line);
645
+			if (WP_DEBUG && $type === 'errors') {
646
+				$msg .= '<br/><span class="tiny-text">' . $notice_code . '</span>';
647
+			}
648
+			// add notice. Index by code if it's not blank
649
+			if ($notice_code) {
650
+				self::$_espresso_notices[ $type ][ $notice_code ] = $msg;
651
+			} else {
652
+				self::$_espresso_notices[ $type ][] = $msg;
653
+			}
654
+			add_action('wp_footer', array('EE_Error', 'enqueue_error_scripts'), 1);
655
+		}
656
+	}
657
+
658
+
659
+	/**
660
+	 * in some case it may be necessary to overwrite the existing success messages
661
+	 *
662
+	 * @return        void
663
+	 */
664
+	public static function overwrite_success()
665
+	{
666
+		self::$_espresso_notices['success'] = false;
667
+	}
668
+
669
+
670
+	/**
671
+	 * in some case it may be necessary to overwrite the existing attention messages
672
+	 *
673
+	 * @return void
674
+	 */
675
+	public static function overwrite_attention()
676
+	{
677
+		self::$_espresso_notices['attention'] = false;
678
+	}
679
+
680
+
681
+	/**
682
+	 * in some case it may be necessary to overwrite the existing error messages
683
+	 *
684
+	 * @return void
685
+	 */
686
+	public static function overwrite_errors()
687
+	{
688
+		self::$_espresso_notices['errors'] = false;
689
+	}
690
+
691
+
692
+	/**
693
+	 * @return void
694
+	 */
695
+	public static function reset_notices()
696
+	{
697
+		self::$_espresso_notices['success'] = false;
698
+		self::$_espresso_notices['attention'] = false;
699
+		self::$_espresso_notices['errors'] = false;
700
+	}
701
+
702
+
703
+	/**
704
+	 * @return int
705
+	 */
706
+	public static function has_notices()
707
+	{
708
+		$has_notices = 0;
709
+		// check for success messages
710
+		$has_notices = self::$_espresso_notices['success'] && ! empty(self::$_espresso_notices['success'])
711
+			? 3
712
+			: $has_notices;
713
+		// check for attention messages
714
+		$has_notices = self::$_espresso_notices['attention'] && ! empty(self::$_espresso_notices['attention'])
715
+			? 2
716
+			: $has_notices;
717
+		// check for error messages
718
+		$has_notices = self::$_espresso_notices['errors'] && ! empty(self::$_espresso_notices['errors'])
719
+			? 1
720
+			: $has_notices;
721
+		return $has_notices;
722
+	}
723
+
724
+
725
+	/**
726
+	 * This simply returns non formatted error notices as they were sent into the EE_Error object.
727
+	 *
728
+	 * @since 4.9.0
729
+	 * @return array
730
+	 */
731
+	public static function get_vanilla_notices()
732
+	{
733
+		return array(
734
+			'success'   => isset(self::$_espresso_notices['success'])
735
+				? self::$_espresso_notices['success']
736
+				: array(),
737
+			'attention' => isset(self::$_espresso_notices['attention'])
738
+				? self::$_espresso_notices['attention']
739
+				: array(),
740
+			'errors'    => isset(self::$_espresso_notices['errors'])
741
+				? self::$_espresso_notices['errors']
742
+				: array(),
743
+		);
744
+	}
745
+
746
+
747
+	/**
748
+	 * @return array
749
+	 * @throws InvalidArgumentException
750
+	 * @throws InvalidDataTypeException
751
+	 * @throws InvalidInterfaceException
752
+	 */
753
+	public static function getStoredNotices()
754
+	{
755
+		if ($user_id = get_current_user_id()) {
756
+			// get notices for logged in user
757
+			$notices = get_user_option(EE_Error::OPTIONS_KEY_NOTICES, $user_id);
758
+			return is_array($notices) ? $notices : array();
759
+		}
760
+		if (EE_Session::isLoadedAndActive()) {
761
+			// get notices for user currently engaged in a session
762
+			$session_data = EE_Session::instance()->get_session_data(EE_Error::OPTIONS_KEY_NOTICES);
763
+			return is_array($session_data) ? $session_data : array();
764
+		}
765
+		// get global notices and hope they apply to the current site visitor
766
+		$notices = get_option(EE_Error::OPTIONS_KEY_NOTICES, array());
767
+		return is_array($notices) ? $notices : array();
768
+	}
769
+
770
+
771
+	/**
772
+	 * @param array $notices
773
+	 * @return bool
774
+	 * @throws InvalidArgumentException
775
+	 * @throws InvalidDataTypeException
776
+	 * @throws InvalidInterfaceException
777
+	 */
778
+	public static function storeNotices(array $notices)
779
+	{
780
+		if ($user_id = get_current_user_id()) {
781
+			// store notices for logged in user
782
+			return (bool) update_user_option(
783
+				$user_id,
784
+				EE_Error::OPTIONS_KEY_NOTICES,
785
+				$notices
786
+			);
787
+		}
788
+		if (EE_Session::isLoadedAndActive()) {
789
+			// store notices for user currently engaged in a session
790
+			return EE_Session::instance()->set_session_data(
791
+				array(EE_Error::OPTIONS_KEY_NOTICES => $notices)
792
+			);
793
+		}
794
+		// store global notices and hope they apply to the same site visitor on the next request
795
+		return update_option(EE_Error::OPTIONS_KEY_NOTICES, $notices);
796
+	}
797
+
798
+
799
+	/**
800
+	 * @return bool|TRUE
801
+	 * @throws InvalidArgumentException
802
+	 * @throws InvalidDataTypeException
803
+	 * @throws InvalidInterfaceException
804
+	 */
805
+	public static function clearNotices()
806
+	{
807
+		if ($user_id = get_current_user_id()) {
808
+			// clear notices for logged in user
809
+			return (bool) update_user_option(
810
+				$user_id,
811
+				EE_Error::OPTIONS_KEY_NOTICES,
812
+				array()
813
+			);
814
+		}
815
+		if (EE_Session::isLoadedAndActive()) {
816
+			// clear notices for user currently engaged in a session
817
+			return EE_Session::instance()->reset_data(EE_Error::OPTIONS_KEY_NOTICES);
818
+		}
819
+		// clear global notices and hope none belonged to some for some other site visitor
820
+		return update_option(EE_Error::OPTIONS_KEY_NOTICES, array());
821
+	}
822
+
823
+
824
+	/**
825
+	 * saves notices to the db for retrieval on next request
826
+	 *
827
+	 * @return void
828
+	 * @throws InvalidArgumentException
829
+	 * @throws InvalidDataTypeException
830
+	 * @throws InvalidInterfaceException
831
+	 */
832
+	public static function stashNoticesBeforeRedirect()
833
+	{
834
+		EE_Error::get_notices(false, true);
835
+	}
836
+
837
+
838
+	/**
839
+	 * compile all error or success messages into one string
840
+	 *
841
+	 * @see EE_Error::get_raw_notices if you want the raw notices without any preparations made to them
842
+	 * @param boolean $format_output            whether or not to format the messages for display in the WP admin
843
+	 * @param boolean $save_to_transient        whether or not to save notices to the db for retrieval on next request
844
+	 *                                          - ONLY do this just before redirecting
845
+	 * @param boolean $remove_empty             whether or not to unset empty messages
846
+	 * @return array
847
+	 * @throws InvalidArgumentException
848
+	 * @throws InvalidDataTypeException
849
+	 * @throws InvalidInterfaceException
850
+	 */
851
+	public static function get_notices($format_output = true, $save_to_transient = false, $remove_empty = true)
852
+	{
853
+		$success_messages = '';
854
+		$attention_messages = '';
855
+		$error_messages = '';
856
+		// either save notices to the db
857
+		if ($save_to_transient || isset($_REQUEST['activate-selected'])) {
858
+			self::$_espresso_notices = array_merge(
859
+				EE_Error::getStoredNotices(),
860
+				self::$_espresso_notices
861
+			);
862
+			EE_Error::storeNotices(self::$_espresso_notices);
863
+			return array();
864
+		}
865
+		$print_scripts = EE_Error::combineExistingAndNewNotices();
866
+		// check for success messages
867
+		if (self::$_espresso_notices['success'] && ! empty(self::$_espresso_notices['success'])) {
868
+			// combine messages
869
+			$success_messages .= implode('<br />', self::$_espresso_notices['success']);
870
+			$print_scripts = true;
871
+		}
872
+		// check for attention messages
873
+		if (self::$_espresso_notices['attention'] && ! empty(self::$_espresso_notices['attention'])) {
874
+			// combine messages
875
+			$attention_messages .= implode('<br />', self::$_espresso_notices['attention']);
876
+			$print_scripts = true;
877
+		}
878
+		// check for error messages
879
+		if (self::$_espresso_notices['errors'] && ! empty(self::$_espresso_notices['errors'])) {
880
+			$error_messages .= count(self::$_espresso_notices['errors']) > 1
881
+				? __('The following errors have occurred:<br />', 'event_espresso')
882
+				: __('An error has occurred:<br />', 'event_espresso');
883
+			// combine messages
884
+			$error_messages .= implode('<br />', self::$_espresso_notices['errors']);
885
+			$print_scripts = true;
886
+		}
887
+		if ($format_output) {
888
+			$notices = EE_Error::formatNoticesOutput(
889
+				$success_messages,
890
+				$attention_messages,
891
+				$error_messages
892
+			);
893
+		} else {
894
+			$notices = array(
895
+				'success'   => $success_messages,
896
+				'attention' => $attention_messages,
897
+				'errors'    => $error_messages,
898
+			);
899
+			if ($remove_empty) {
900
+				// remove empty notices
901
+				foreach ($notices as $type => $notice) {
902
+					if (empty($notice)) {
903
+						unset($notices[ $type ]);
904
+					}
905
+				}
906
+			}
907
+		}
908
+		if ($print_scripts) {
909
+			self::_print_scripts();
910
+		}
911
+		return $notices;
912
+	}
913
+
914
+
915
+	/**
916
+	 * @return bool
917
+	 * @throws InvalidArgumentException
918
+	 * @throws InvalidDataTypeException
919
+	 * @throws InvalidInterfaceException
920
+	 */
921
+	private static function combineExistingAndNewNotices()
922
+	{
923
+		$print_scripts = false;
924
+		// grab any notices that have been previously saved
925
+		$notices = EE_Error::getStoredNotices();
926
+		if (! empty($notices)) {
927
+			foreach ($notices as $type => $notice) {
928
+				if (is_array($notice) && ! empty($notice)) {
929
+					// make sure that existing notice type is an array
930
+					self::$_espresso_notices[ $type ] = is_array(self::$_espresso_notices[ $type ])
931
+														&& ! empty(self::$_espresso_notices[ $type ])
932
+						? self::$_espresso_notices[ $type ]
933
+						: array();
934
+					// add newly created notices to existing ones
935
+					self::$_espresso_notices[ $type ] += $notice;
936
+					$print_scripts = true;
937
+				}
938
+			}
939
+			// now clear any stored notices
940
+			EE_Error::clearNotices();
941
+		}
942
+		return $print_scripts;
943
+	}
944
+
945
+
946
+	/**
947
+	 * @param string $success_messages
948
+	 * @param string $attention_messages
949
+	 * @param string $error_messages
950
+	 * @return string
951
+	 */
952
+	private static function formatNoticesOutput($success_messages, $attention_messages, $error_messages)
953
+	{
954
+		$notices = '<div id="espresso-notices">';
955
+		$close = is_admin()
956
+			? ''
957
+			: '<a class="close-espresso-notice hide-if-no-js"><span class="dashicons dashicons-no"/></a>';
958
+		if ($success_messages !== '') {
959
+			$css_id = is_admin() ? 'ee-success-message' : 'espresso-notices-success';
960
+			$css_class = is_admin() ? 'updated fade' : 'success fade-away';
961
+			// showMessage( $success_messages );
962
+			$notices .= '<div id="' . $css_id . '" '
963
+						. 'class="espresso-notices ' . $css_class . '" '
964
+						. 'style="display:none;">'
965
+						. '<p>' . $success_messages . '</p>'
966
+						. $close
967
+						. '</div>';
968
+		}
969
+		if ($attention_messages !== '') {
970
+			$css_id = is_admin() ? 'ee-attention-message' : 'espresso-notices-attention';
971
+			$css_class = is_admin() ? 'updated ee-notices-attention' : 'attention fade-away';
972
+			// showMessage( $error_messages, TRUE );
973
+			$notices .= '<div id="' . $css_id . '" '
974
+						. 'class="espresso-notices ' . $css_class . '" '
975
+						. 'style="display:none;">'
976
+						. '<p>' . $attention_messages . '</p>'
977
+						. $close
978
+						. '</div>';
979
+		}
980
+		if ($error_messages !== '') {
981
+			$css_id = is_admin() ? 'ee-error-message' : 'espresso-notices-error';
982
+			$css_class = is_admin() ? 'error' : 'error fade-away';
983
+			// showMessage( $error_messages, TRUE );
984
+			$notices .= '<div id="' . $css_id . '" '
985
+						. 'class="espresso-notices ' . $css_class . '" '
986
+						. 'style="display:none;">'
987
+						. '<p>' . $error_messages . '</p>'
988
+						. $close
989
+						. '</div>';
990
+		}
991
+		$notices .= '</div>';
992
+		return $notices;
993
+	}
994
+
995
+
996
+	/**
997
+	 * _print_scripts
998
+	 *
999
+	 * @param    bool $force_print
1000
+	 * @return    string
1001
+	 */
1002
+	private static function _print_scripts($force_print = false)
1003
+	{
1004
+		if (! $force_print && (did_action('admin_enqueue_scripts') || did_action('wp_enqueue_scripts'))) {
1005
+			if (wp_script_is('ee_error_js', 'registered')) {
1006
+				wp_enqueue_style('espresso_default');
1007
+				wp_enqueue_style('espresso_custom_css');
1008
+				wp_enqueue_script('ee_error_js');
1009
+			}
1010
+			if (wp_script_is('ee_error_js', 'enqueued')) {
1011
+				wp_localize_script('ee_error_js', 'ee_settings', array('wp_debug' => WP_DEBUG));
1012
+				return '';
1013
+			}
1014
+		} else {
1015
+			return '
1016 1016
 <script>
1017 1017
 /* <![CDATA[ */
1018 1018
 var ee_settings = {"wp_debug":"' . WP_DEBUG . '"};
@@ -1022,221 +1022,221 @@  discard block
 block discarded – undo
1022 1022
 <script src="' . EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js' . '?ver=' . espresso_version() . '" type="text/javascript"></script>
1023 1023
 <script src="' . EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js' . '?ver=' . espresso_version() . '" type="text/javascript"></script>
1024 1024
 ';
1025
-        }
1026
-        return '';
1027
-    }
1028
-
1029
-
1030
-    /**
1031
-     * @return void
1032
-     */
1033
-    public static function enqueue_error_scripts()
1034
-    {
1035
-        self::_print_scripts();
1036
-    }
1037
-
1038
-
1039
-    /**
1040
-     * create error code from filepath, function name,
1041
-     * and line number where exception or error was thrown
1042
-     *
1043
-     * @param string $file
1044
-     * @param string $func
1045
-     * @param string $line
1046
-     * @return string
1047
-     */
1048
-    public static function generate_error_code($file = '', $func = '', $line = '')
1049
-    {
1050
-        $file = explode('.', basename($file));
1051
-        $error_code = ! empty($file[0]) ? $file[0] : '';
1052
-        $error_code .= ! empty($func) ? ' - ' . $func : '';
1053
-        $error_code .= ! empty($line) ? ' - ' . $line : '';
1054
-        return $error_code;
1055
-    }
1056
-
1057
-
1058
-    /**
1059
-     * write exception details to log file
1060
-     * Since 4.9.53.rc.006 this writes to the standard PHP log file, not EE's custom log file
1061
-     *
1062
-     * @param int   $time
1063
-     * @param array $ex
1064
-     * @param bool  $clear
1065
-     * @return void
1066
-     */
1067
-    public function write_to_error_log($time = 0, $ex = array(), $clear = false)
1068
-    {
1069
-        if (empty($ex)) {
1070
-            return;
1071
-        }
1072
-        if (! $time) {
1073
-            $time = time();
1074
-        }
1075
-        $exception_log = '----------------------------------------------------------------------------------------'
1076
-                         . PHP_EOL;
1077
-        $exception_log .= '[' . date('Y-m-d H:i:s', $time) . ']  Exception Details' . PHP_EOL;
1078
-        $exception_log .= 'Message: ' . $ex['msg'] . PHP_EOL;
1079
-        $exception_log .= 'Code: ' . $ex['code'] . PHP_EOL;
1080
-        $exception_log .= 'File: ' . $ex['file'] . PHP_EOL;
1081
-        $exception_log .= 'Line No: ' . $ex['line'] . PHP_EOL;
1082
-        $exception_log .= 'Stack trace: ' . PHP_EOL;
1083
-        $exception_log .= $ex['string'] . PHP_EOL;
1084
-        $exception_log .= '----------------------------------------------------------------------------------------'
1085
-                          . PHP_EOL;
1086
-        try {
1087
-            error_log($exception_log);
1088
-        } catch (EE_Error $e) {
1089
-            EE_Error::add_error(
1090
-                sprintf(
1091
-                    __(
1092
-                        'Event Espresso error logging could not be setup because: %s',
1093
-                        'event_espresso'
1094
-                    ),
1095
-                    $e->getMessage()
1096
-                )
1097
-            );
1098
-        }
1099
-    }
1100
-
1101
-
1102
-    /**
1103
-     * This is just a wrapper for the EEH_Debug_Tools::instance()->doing_it_wrong() method.
1104
-     * doing_it_wrong() is used in those cases where a normal PHP error won't get thrown,
1105
-     * but the code execution is done in a manner that could lead to unexpected results
1106
-     * (i.e. running to early, or too late in WP or EE loading process).
1107
-     * A good test for knowing whether to use this method is:
1108
-     * 1. Is there going to be a PHP error if something isn't setup/used correctly?
1109
-     * Yes -> use EE_Error::add_error() or throw new EE_Error()
1110
-     * 2. If this is loaded before something else, it won't break anything,
1111
-     * but just wont' do what its supposed to do? Yes -> use EE_Error::doing_it_wrong()
1112
-     *
1113
-     * @uses   constant WP_DEBUG test if wp_debug is on or not
1114
-     * @param string $function      The function that was called
1115
-     * @param string $message       A message explaining what has been done incorrectly
1116
-     * @param string $version       The version of Event Espresso where the error was added
1117
-     * @param string $applies_when  a version string for when you want the doing_it_wrong notice to begin appearing
1118
-     *                              for a deprecated function. This allows deprecation to occur during one version,
1119
-     *                              but not have any notices appear until a later version. This allows developers
1120
-     *                              extra time to update their code before notices appear.
1121
-     * @param int    $error_type
1122
-     */
1123
-    public static function doing_it_wrong(
1124
-        $function,
1125
-        $message,
1126
-        $version,
1127
-        $applies_when = '',
1128
-        $error_type = null
1129
-    ) {
1130
-        if (defined('WP_DEBUG') && WP_DEBUG) {
1131
-            EEH_Debug_Tools::instance()->doing_it_wrong($function, $message, $version, $applies_when, $error_type);
1132
-        }
1133
-    }
1134
-
1135
-
1136
-    /**
1137
-     * Like get_notices, but returns an array of all the notices of the given type.
1138
-     *
1139
-     * @return array {
1140
-     * @type array $success   all the success messages
1141
-     * @type array $errors    all the error messages
1142
-     * @type array $attention all the attention messages
1143
-     * }
1144
-     */
1145
-    public static function get_raw_notices()
1146
-    {
1147
-        return self::$_espresso_notices;
1148
-    }
1149
-
1150
-
1151
-    /**
1152
-     * @deprecated 4.9.27
1153
-     * @param string $pan_name     the name, or key of the Persistent Admin Notice to be stored
1154
-     * @param string $pan_message  the message to be stored persistently until dismissed
1155
-     * @param bool   $force_update allows one to enforce the reappearance of a persistent message.
1156
-     * @return void
1157
-     * @throws InvalidDataTypeException
1158
-     */
1159
-    public static function add_persistent_admin_notice($pan_name = '', $pan_message, $force_update = false)
1160
-    {
1161
-        new PersistentAdminNotice(
1162
-            $pan_name,
1163
-            $pan_message,
1164
-            $force_update
1165
-        );
1166
-        EE_Error::doing_it_wrong(
1167
-            __METHOD__,
1168
-            sprintf(
1169
-                __('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1170
-                '\EventEspresso\core\domain\entities\notifications\PersistentAdminNotice'
1171
-            ),
1172
-            '4.9.27'
1173
-        );
1174
-    }
1175
-
1176
-
1177
-    /**
1178
-     * @deprecated 4.9.27
1179
-     * @param string $pan_name the name, or key of the Persistent Admin Notice to be dismissed
1180
-     * @param bool   $purge
1181
-     * @param bool   $return
1182
-     * @throws DomainException
1183
-     * @throws InvalidInterfaceException
1184
-     * @throws InvalidDataTypeException
1185
-     * @throws ServiceNotFoundException
1186
-     * @throws InvalidArgumentException
1187
-     */
1188
-    public static function dismiss_persistent_admin_notice($pan_name = '', $purge = false, $return = false)
1189
-    {
1190
-        /** @var PersistentAdminNoticeManager $persistent_admin_notice_manager */
1191
-        $persistent_admin_notice_manager = LoaderFactory::getLoader()->getShared(
1192
-            'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1193
-        );
1194
-        $persistent_admin_notice_manager->dismissNotice($pan_name, $purge, $return);
1195
-        EE_Error::doing_it_wrong(
1196
-            __METHOD__,
1197
-            sprintf(
1198
-                __('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1199
-                '\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1200
-            ),
1201
-            '4.9.27'
1202
-        );
1203
-    }
1204
-
1205
-
1206
-    /**
1207
-     * @deprecated 4.9.27
1208
-     * @param  string $pan_name    the name, or key of the Persistent Admin Notice to be stored
1209
-     * @param  string $pan_message the message to be stored persistently until dismissed
1210
-     * @param  string $return_url  URL to go back to after nag notice is dismissed
1211
-     */
1212
-    public static function display_persistent_admin_notices($pan_name = '', $pan_message = '', $return_url = '')
1213
-    {
1214
-        EE_Error::doing_it_wrong(
1215
-            __METHOD__,
1216
-            sprintf(
1217
-                __('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1218
-                '\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1219
-            ),
1220
-            '4.9.27'
1221
-        );
1222
-    }
1223
-
1224
-
1225
-    /**
1226
-     * @deprecated 4.9.27
1227
-     * @param string $return_url
1228
-     */
1229
-    public static function get_persistent_admin_notices($return_url = '')
1230
-    {
1231
-        EE_Error::doing_it_wrong(
1232
-            __METHOD__,
1233
-            sprintf(
1234
-                __('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1235
-                '\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1236
-            ),
1237
-            '4.9.27'
1238
-        );
1239
-    }
1025
+		}
1026
+		return '';
1027
+	}
1028
+
1029
+
1030
+	/**
1031
+	 * @return void
1032
+	 */
1033
+	public static function enqueue_error_scripts()
1034
+	{
1035
+		self::_print_scripts();
1036
+	}
1037
+
1038
+
1039
+	/**
1040
+	 * create error code from filepath, function name,
1041
+	 * and line number where exception or error was thrown
1042
+	 *
1043
+	 * @param string $file
1044
+	 * @param string $func
1045
+	 * @param string $line
1046
+	 * @return string
1047
+	 */
1048
+	public static function generate_error_code($file = '', $func = '', $line = '')
1049
+	{
1050
+		$file = explode('.', basename($file));
1051
+		$error_code = ! empty($file[0]) ? $file[0] : '';
1052
+		$error_code .= ! empty($func) ? ' - ' . $func : '';
1053
+		$error_code .= ! empty($line) ? ' - ' . $line : '';
1054
+		return $error_code;
1055
+	}
1056
+
1057
+
1058
+	/**
1059
+	 * write exception details to log file
1060
+	 * Since 4.9.53.rc.006 this writes to the standard PHP log file, not EE's custom log file
1061
+	 *
1062
+	 * @param int   $time
1063
+	 * @param array $ex
1064
+	 * @param bool  $clear
1065
+	 * @return void
1066
+	 */
1067
+	public function write_to_error_log($time = 0, $ex = array(), $clear = false)
1068
+	{
1069
+		if (empty($ex)) {
1070
+			return;
1071
+		}
1072
+		if (! $time) {
1073
+			$time = time();
1074
+		}
1075
+		$exception_log = '----------------------------------------------------------------------------------------'
1076
+						 . PHP_EOL;
1077
+		$exception_log .= '[' . date('Y-m-d H:i:s', $time) . ']  Exception Details' . PHP_EOL;
1078
+		$exception_log .= 'Message: ' . $ex['msg'] . PHP_EOL;
1079
+		$exception_log .= 'Code: ' . $ex['code'] . PHP_EOL;
1080
+		$exception_log .= 'File: ' . $ex['file'] . PHP_EOL;
1081
+		$exception_log .= 'Line No: ' . $ex['line'] . PHP_EOL;
1082
+		$exception_log .= 'Stack trace: ' . PHP_EOL;
1083
+		$exception_log .= $ex['string'] . PHP_EOL;
1084
+		$exception_log .= '----------------------------------------------------------------------------------------'
1085
+						  . PHP_EOL;
1086
+		try {
1087
+			error_log($exception_log);
1088
+		} catch (EE_Error $e) {
1089
+			EE_Error::add_error(
1090
+				sprintf(
1091
+					__(
1092
+						'Event Espresso error logging could not be setup because: %s',
1093
+						'event_espresso'
1094
+					),
1095
+					$e->getMessage()
1096
+				)
1097
+			);
1098
+		}
1099
+	}
1100
+
1101
+
1102
+	/**
1103
+	 * This is just a wrapper for the EEH_Debug_Tools::instance()->doing_it_wrong() method.
1104
+	 * doing_it_wrong() is used in those cases where a normal PHP error won't get thrown,
1105
+	 * but the code execution is done in a manner that could lead to unexpected results
1106
+	 * (i.e. running to early, or too late in WP or EE loading process).
1107
+	 * A good test for knowing whether to use this method is:
1108
+	 * 1. Is there going to be a PHP error if something isn't setup/used correctly?
1109
+	 * Yes -> use EE_Error::add_error() or throw new EE_Error()
1110
+	 * 2. If this is loaded before something else, it won't break anything,
1111
+	 * but just wont' do what its supposed to do? Yes -> use EE_Error::doing_it_wrong()
1112
+	 *
1113
+	 * @uses   constant WP_DEBUG test if wp_debug is on or not
1114
+	 * @param string $function      The function that was called
1115
+	 * @param string $message       A message explaining what has been done incorrectly
1116
+	 * @param string $version       The version of Event Espresso where the error was added
1117
+	 * @param string $applies_when  a version string for when you want the doing_it_wrong notice to begin appearing
1118
+	 *                              for a deprecated function. This allows deprecation to occur during one version,
1119
+	 *                              but not have any notices appear until a later version. This allows developers
1120
+	 *                              extra time to update their code before notices appear.
1121
+	 * @param int    $error_type
1122
+	 */
1123
+	public static function doing_it_wrong(
1124
+		$function,
1125
+		$message,
1126
+		$version,
1127
+		$applies_when = '',
1128
+		$error_type = null
1129
+	) {
1130
+		if (defined('WP_DEBUG') && WP_DEBUG) {
1131
+			EEH_Debug_Tools::instance()->doing_it_wrong($function, $message, $version, $applies_when, $error_type);
1132
+		}
1133
+	}
1134
+
1135
+
1136
+	/**
1137
+	 * Like get_notices, but returns an array of all the notices of the given type.
1138
+	 *
1139
+	 * @return array {
1140
+	 * @type array $success   all the success messages
1141
+	 * @type array $errors    all the error messages
1142
+	 * @type array $attention all the attention messages
1143
+	 * }
1144
+	 */
1145
+	public static function get_raw_notices()
1146
+	{
1147
+		return self::$_espresso_notices;
1148
+	}
1149
+
1150
+
1151
+	/**
1152
+	 * @deprecated 4.9.27
1153
+	 * @param string $pan_name     the name, or key of the Persistent Admin Notice to be stored
1154
+	 * @param string $pan_message  the message to be stored persistently until dismissed
1155
+	 * @param bool   $force_update allows one to enforce the reappearance of a persistent message.
1156
+	 * @return void
1157
+	 * @throws InvalidDataTypeException
1158
+	 */
1159
+	public static function add_persistent_admin_notice($pan_name = '', $pan_message, $force_update = false)
1160
+	{
1161
+		new PersistentAdminNotice(
1162
+			$pan_name,
1163
+			$pan_message,
1164
+			$force_update
1165
+		);
1166
+		EE_Error::doing_it_wrong(
1167
+			__METHOD__,
1168
+			sprintf(
1169
+				__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1170
+				'\EventEspresso\core\domain\entities\notifications\PersistentAdminNotice'
1171
+			),
1172
+			'4.9.27'
1173
+		);
1174
+	}
1175
+
1176
+
1177
+	/**
1178
+	 * @deprecated 4.9.27
1179
+	 * @param string $pan_name the name, or key of the Persistent Admin Notice to be dismissed
1180
+	 * @param bool   $purge
1181
+	 * @param bool   $return
1182
+	 * @throws DomainException
1183
+	 * @throws InvalidInterfaceException
1184
+	 * @throws InvalidDataTypeException
1185
+	 * @throws ServiceNotFoundException
1186
+	 * @throws InvalidArgumentException
1187
+	 */
1188
+	public static function dismiss_persistent_admin_notice($pan_name = '', $purge = false, $return = false)
1189
+	{
1190
+		/** @var PersistentAdminNoticeManager $persistent_admin_notice_manager */
1191
+		$persistent_admin_notice_manager = LoaderFactory::getLoader()->getShared(
1192
+			'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1193
+		);
1194
+		$persistent_admin_notice_manager->dismissNotice($pan_name, $purge, $return);
1195
+		EE_Error::doing_it_wrong(
1196
+			__METHOD__,
1197
+			sprintf(
1198
+				__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1199
+				'\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1200
+			),
1201
+			'4.9.27'
1202
+		);
1203
+	}
1204
+
1205
+
1206
+	/**
1207
+	 * @deprecated 4.9.27
1208
+	 * @param  string $pan_name    the name, or key of the Persistent Admin Notice to be stored
1209
+	 * @param  string $pan_message the message to be stored persistently until dismissed
1210
+	 * @param  string $return_url  URL to go back to after nag notice is dismissed
1211
+	 */
1212
+	public static function display_persistent_admin_notices($pan_name = '', $pan_message = '', $return_url = '')
1213
+	{
1214
+		EE_Error::doing_it_wrong(
1215
+			__METHOD__,
1216
+			sprintf(
1217
+				__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1218
+				'\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1219
+			),
1220
+			'4.9.27'
1221
+		);
1222
+	}
1223
+
1224
+
1225
+	/**
1226
+	 * @deprecated 4.9.27
1227
+	 * @param string $return_url
1228
+	 */
1229
+	public static function get_persistent_admin_notices($return_url = '')
1230
+	{
1231
+		EE_Error::doing_it_wrong(
1232
+			__METHOD__,
1233
+			sprintf(
1234
+				__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1235
+				'\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1236
+			),
1237
+			'4.9.27'
1238
+		);
1239
+	}
1240 1240
 }
1241 1241
 
1242 1242
 // end of Class EE_Exceptions
@@ -1249,27 +1249,27 @@  discard block
 block discarded – undo
1249 1249
  */
1250 1250
 function espresso_error_enqueue_scripts()
1251 1251
 {
1252
-    // js for error handling
1253
-    wp_register_script(
1254
-        'espresso_core',
1255
-        EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
1256
-        array('jquery'),
1257
-        EVENT_ESPRESSO_VERSION,
1258
-        false
1259
-    );
1260
-    wp_register_script(
1261
-        'ee_error_js',
1262
-        EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js',
1263
-        array('espresso_core'),
1264
-        EVENT_ESPRESSO_VERSION,
1265
-        false
1266
-    );
1252
+	// js for error handling
1253
+	wp_register_script(
1254
+		'espresso_core',
1255
+		EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
1256
+		array('jquery'),
1257
+		EVENT_ESPRESSO_VERSION,
1258
+		false
1259
+	);
1260
+	wp_register_script(
1261
+		'ee_error_js',
1262
+		EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js',
1263
+		array('espresso_core'),
1264
+		EVENT_ESPRESSO_VERSION,
1265
+		false
1266
+	);
1267 1267
 }
1268 1268
 
1269 1269
 if (is_admin()) {
1270
-    add_action('admin_enqueue_scripts', 'espresso_error_enqueue_scripts', 5);
1270
+	add_action('admin_enqueue_scripts', 'espresso_error_enqueue_scripts', 5);
1271 1271
 } else {
1272
-    add_action('wp_enqueue_scripts', 'espresso_error_enqueue_scripts', 5);
1272
+	add_action('wp_enqueue_scripts', 'espresso_error_enqueue_scripts', 5);
1273 1273
 }
1274 1274
 
1275 1275
 
Please login to merge, or discard this patch.
admin_pages/registrations/Registrations_Admin_Page.core.php 2 patches
Indentation   +3705 added lines, -3705 removed lines patch added patch discarded remove patch
@@ -18,2227 +18,2227 @@  discard block
 block discarded – undo
18 18
 class Registrations_Admin_Page extends EE_Admin_Page_CPT
19 19
 {
20 20
 
21
-    /**
22
-     * @var EE_Registration
23
-     */
24
-    private $_registration;
25
-
26
-    /**
27
-     * @var EE_Event
28
-     */
29
-    private $_reg_event;
30
-
31
-    /**
32
-     * @var EE_Session
33
-     */
34
-    private $_session;
35
-
36
-    private static $_reg_status;
37
-
38
-    /**
39
-     * Form for displaying the custom questions for this registration.
40
-     * This gets used a few times throughout the request so its best to cache it
41
-     *
42
-     * @var EE_Registration_Custom_Questions_Form
43
-     */
44
-    protected $_reg_custom_questions_form = null;
45
-
46
-    /**
47
-     * @var EEM_Registration $registration_model
48
-     */
49
-    private $registration_model;
50
-
51
-    /**
52
-     * @var EEM_Attendee $attendee_model
53
-     */
54
-    private $attendee_model;
55
-
56
-    /**
57
-     * @var EEM_Event $event_model
58
-     */
59
-    private $event_model;
60
-
61
-    /**
62
-     * @var EEM_Status $status_model
63
-     */
64
-    private $status_model;
65
-
66
-
67
-    /**
68
-     * @param bool $routing
69
-     * @throws EE_Error
70
-     * @throws InvalidArgumentException
71
-     * @throws InvalidDataTypeException
72
-     * @throws InvalidInterfaceException
73
-     * @throws ReflectionException
74
-     */
75
-    public function __construct($routing = true)
76
-    {
77
-        parent::__construct($routing);
78
-        add_action('wp_loaded', array($this, 'wp_loaded'));
79
-    }
80
-
81
-    /**
82
-     * @return EEM_Registration
83
-     * @throws InvalidArgumentException
84
-     * @throws InvalidDataTypeException
85
-     * @throws InvalidInterfaceException
86
-     * @since 4.10.2.p
87
-     */
88
-    protected function getRegistrationModel()
89
-    {
90
-        if (! $this->registration_model instanceof EEM_Registration) {
91
-            $this->registration_model = $this->getLoader()->getShared('EEM_Registration');
92
-        }
93
-        return $this->registration_model;
94
-    }
95
-
96
-    /**
97
-     * @return EEM_Attendee
98
-     * @throws InvalidArgumentException
99
-     * @throws InvalidDataTypeException
100
-     * @throws InvalidInterfaceException
101
-     * @since 4.10.2.p
102
-     */
103
-    protected function getAttendeeModel()
104
-    {
105
-        if (! $this->attendee_model instanceof EEM_Attendee) {
106
-            $this->attendee_model = $this->getLoader()->getShared('EEM_Attendee');
107
-        }
108
-        return $this->attendee_model;
109
-    }
110
-
111
-
112
-    /**
113
-     * @return EEM_Event
114
-     * @throws InvalidArgumentException
115
-     * @throws InvalidDataTypeException
116
-     * @throws InvalidInterfaceException
117
-     * @since 4.10.2.p
118
-     */
119
-    protected function getEventModel()
120
-    {
121
-        if (! $this->event_model instanceof EEM_Event) {
122
-            $this->event_model = $this->getLoader()->getShared('EEM_Event');
123
-        }
124
-        return $this->event_model;
125
-    }
126
-
127
-    /**
128
-     * @return EEM_Status
129
-     * @throws InvalidArgumentException
130
-     * @throws InvalidDataTypeException
131
-     * @throws InvalidInterfaceException
132
-     * @since 4.10.2.p
133
-     */
134
-    protected function getStatusModel()
135
-    {
136
-        if (! $this->status_model instanceof EEM_Status) {
137
-            $this->status_model = $this->getLoader()->getShared('EEM_Status');
138
-        }
139
-        return $this->status_model;
140
-    }
141
-
142
-
143
-    public function wp_loaded()
144
-    {
145
-        // when adding a new registration...
146
-        if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'new_registration') {
147
-            EE_System::do_not_cache();
148
-            if (! isset($this->_req_data['processing_registration'])
149
-                || absint($this->_req_data['processing_registration']) !== 1
150
-            ) {
151
-                // and it's NOT the attendee information reg step
152
-                // force cookie expiration by setting time to last week
153
-                setcookie('ee_registration_added', 0, time() - WEEK_IN_SECONDS, '/');
154
-                // and update the global
155
-                $_COOKIE['ee_registration_added'] = 0;
156
-            }
157
-        }
158
-    }
159
-
160
-
161
-    protected function _init_page_props()
162
-    {
163
-        $this->page_slug = REG_PG_SLUG;
164
-        $this->_admin_base_url = REG_ADMIN_URL;
165
-        $this->_admin_base_path = REG_ADMIN;
166
-        $this->page_label = esc_html__('Registrations', 'event_espresso');
167
-        $this->_cpt_routes = array(
168
-            'add_new_attendee' => 'espresso_attendees',
169
-            'edit_attendee'    => 'espresso_attendees',
170
-            'insert_attendee'  => 'espresso_attendees',
171
-            'update_attendee'  => 'espresso_attendees',
172
-        );
173
-        $this->_cpt_model_names = array(
174
-            'add_new_attendee' => 'EEM_Attendee',
175
-            'edit_attendee'    => 'EEM_Attendee',
176
-        );
177
-        $this->_cpt_edit_routes = array(
178
-            'espresso_attendees' => 'edit_attendee',
179
-        );
180
-        $this->_pagenow_map = array(
181
-            'add_new_attendee' => 'post-new.php',
182
-            'edit_attendee'    => 'post.php',
183
-            'trash'            => 'post.php',
184
-        );
185
-        add_action('edit_form_after_title', array($this, 'after_title_form_fields'), 10);
186
-        // add filters so that the comment urls don't take users to a confusing 404 page
187
-        add_filter('get_comment_link', array($this, 'clear_comment_link'), 10, 3);
188
-    }
189
-
190
-
191
-    public function clear_comment_link($link, $comment, $args)
192
-    {
193
-        // gotta make sure this only happens on this route
194
-        $post_type = get_post_type($comment->comment_post_ID);
195
-        if ($post_type === 'espresso_attendees') {
196
-            return '#commentsdiv';
197
-        }
198
-        return $link;
199
-    }
200
-
201
-
202
-    protected function _ajax_hooks()
203
-    {
204
-        // todo: all hooks for registrations ajax goes in here
205
-        add_action('wp_ajax_toggle_checkin_status', array($this, 'toggle_checkin_status'));
206
-    }
207
-
208
-
209
-    protected function _define_page_props()
210
-    {
211
-        $this->_admin_page_title = $this->page_label;
212
-        $this->_labels = array(
213
-            'buttons'                      => array(
214
-                'add-registrant'      => esc_html__('Add New Registration', 'event_espresso'),
215
-                'add-attendee'        => esc_html__('Add Contact', 'event_espresso'),
216
-                'edit'                => esc_html__('Edit Contact', 'event_espresso'),
217
-                'report'              => esc_html__('Event Registrations CSV Report', 'event_espresso'),
218
-                'report_all'          => esc_html__('All Registrations CSV Report', 'event_espresso'),
219
-                'report_filtered'     => esc_html__('Filtered CSV Report', 'event_espresso'),
220
-                'contact_list_report' => esc_html__('Contact List Report', 'event_espresso'),
221
-                'contact_list_export' => esc_html__('Export Data', 'event_espresso'),
222
-            ),
223
-            'publishbox'                   => array(
224
-                'add_new_attendee' => esc_html__('Add Contact Record', 'event_espresso'),
225
-                'edit_attendee'    => esc_html__('Update Contact Record', 'event_espresso'),
226
-            ),
227
-            'hide_add_button_on_cpt_route' => array(
228
-                'edit_attendee' => true,
229
-            ),
230
-        );
231
-    }
232
-
233
-
234
-    /**
235
-     *        grab url requests and route them
236
-     *
237
-     * @access private
238
-     * @return void
239
-     * @throws EE_Error
240
-     */
241
-    public function _set_page_routes()
242
-    {
243
-        $this->_get_registration_status_array();
244
-        $reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
245
-            ? $this->_req_data['_REG_ID'] : 0;
246
-        $reg_id = empty($reg_id) && ! empty($this->_req_data['reg_status_change_form']['REG_ID'])
247
-            ? $this->_req_data['reg_status_change_form']['REG_ID']
248
-            : $reg_id;
249
-        $att_id = ! empty($this->_req_data['ATT_ID']) && ! is_array($this->_req_data['ATT_ID'])
250
-            ? $this->_req_data['ATT_ID'] : 0;
251
-        $att_id = ! empty($this->_req_data['post']) && ! is_array($this->_req_data['post'])
252
-            ? $this->_req_data['post']
253
-            : $att_id;
254
-        $this->_page_routes = array(
255
-            'default'                             => array(
256
-                'func'       => '_registrations_overview_list_table',
257
-                'capability' => 'ee_read_registrations',
258
-            ),
259
-            'view_registration'                   => array(
260
-                'func'       => '_registration_details',
261
-                'capability' => 'ee_read_registration',
262
-                'obj_id'     => $reg_id,
263
-            ),
264
-            'edit_registration'                   => array(
265
-                'func'               => '_update_attendee_registration_form',
266
-                'noheader'           => true,
267
-                'headers_sent_route' => 'view_registration',
268
-                'capability'         => 'ee_edit_registration',
269
-                'obj_id'             => $reg_id,
270
-                '_REG_ID'            => $reg_id,
271
-            ),
272
-            'trash_registrations'                 => array(
273
-                'func'       => '_trash_or_restore_registrations',
274
-                'args'       => array('trash' => true),
275
-                'noheader'   => true,
276
-                'capability' => 'ee_delete_registrations',
277
-            ),
278
-            'restore_registrations'               => array(
279
-                'func'       => '_trash_or_restore_registrations',
280
-                'args'       => array('trash' => false),
281
-                'noheader'   => true,
282
-                'capability' => 'ee_delete_registrations',
283
-            ),
284
-            'delete_registrations'                => array(
285
-                'func'       => '_delete_registrations',
286
-                'noheader'   => true,
287
-                'capability' => 'ee_delete_registrations',
288
-            ),
289
-            'new_registration'                    => array(
290
-                'func'       => 'new_registration',
291
-                'capability' => 'ee_edit_registrations',
292
-            ),
293
-            'process_reg_step'                    => array(
294
-                'func'       => 'process_reg_step',
295
-                'noheader'   => true,
296
-                'capability' => 'ee_edit_registrations',
297
-            ),
298
-            'redirect_to_txn'                     => array(
299
-                'func'       => 'redirect_to_txn',
300
-                'noheader'   => true,
301
-                'capability' => 'ee_edit_registrations',
302
-            ),
303
-            'change_reg_status'                   => array(
304
-                'func'       => '_change_reg_status',
305
-                'noheader'   => true,
306
-                'capability' => 'ee_edit_registration',
307
-                'obj_id'     => $reg_id,
308
-            ),
309
-            'approve_registration'                => array(
310
-                'func'       => 'approve_registration',
311
-                'noheader'   => true,
312
-                'capability' => 'ee_edit_registration',
313
-                'obj_id'     => $reg_id,
314
-            ),
315
-            'approve_and_notify_registration'     => array(
316
-                'func'       => 'approve_registration',
317
-                'noheader'   => true,
318
-                'args'       => array(true),
319
-                'capability' => 'ee_edit_registration',
320
-                'obj_id'     => $reg_id,
321
-            ),
322
-            'approve_registrations'               => array(
323
-                'func'       => 'bulk_action_on_registrations',
324
-                'noheader'   => true,
325
-                'capability' => 'ee_edit_registrations',
326
-                'args'       => array('approve'),
327
-            ),
328
-            'approve_and_notify_registrations'    => array(
329
-                'func'       => 'bulk_action_on_registrations',
330
-                'noheader'   => true,
331
-                'capability' => 'ee_edit_registrations',
332
-                'args'       => array('approve', true),
333
-            ),
334
-            'decline_registration'                => array(
335
-                'func'       => 'decline_registration',
336
-                'noheader'   => true,
337
-                'capability' => 'ee_edit_registration',
338
-                'obj_id'     => $reg_id,
339
-            ),
340
-            'decline_and_notify_registration'     => array(
341
-                'func'       => 'decline_registration',
342
-                'noheader'   => true,
343
-                'args'       => array(true),
344
-                'capability' => 'ee_edit_registration',
345
-                'obj_id'     => $reg_id,
346
-            ),
347
-            'decline_registrations'               => array(
348
-                'func'       => 'bulk_action_on_registrations',
349
-                'noheader'   => true,
350
-                'capability' => 'ee_edit_registrations',
351
-                'args'       => array('decline'),
352
-            ),
353
-            'decline_and_notify_registrations'    => array(
354
-                'func'       => 'bulk_action_on_registrations',
355
-                'noheader'   => true,
356
-                'capability' => 'ee_edit_registrations',
357
-                'args'       => array('decline', true),
358
-            ),
359
-            'pending_registration'                => array(
360
-                'func'       => 'pending_registration',
361
-                'noheader'   => true,
362
-                'capability' => 'ee_edit_registration',
363
-                'obj_id'     => $reg_id,
364
-            ),
365
-            'pending_and_notify_registration'     => array(
366
-                'func'       => 'pending_registration',
367
-                'noheader'   => true,
368
-                'args'       => array(true),
369
-                'capability' => 'ee_edit_registration',
370
-                'obj_id'     => $reg_id,
371
-            ),
372
-            'pending_registrations'               => array(
373
-                'func'       => 'bulk_action_on_registrations',
374
-                'noheader'   => true,
375
-                'capability' => 'ee_edit_registrations',
376
-                'args'       => array('pending'),
377
-            ),
378
-            'pending_and_notify_registrations'    => array(
379
-                'func'       => 'bulk_action_on_registrations',
380
-                'noheader'   => true,
381
-                'capability' => 'ee_edit_registrations',
382
-                'args'       => array('pending', true),
383
-            ),
384
-            'no_approve_registration'             => array(
385
-                'func'       => 'not_approve_registration',
386
-                'noheader'   => true,
387
-                'capability' => 'ee_edit_registration',
388
-                'obj_id'     => $reg_id,
389
-            ),
390
-            'no_approve_and_notify_registration'  => array(
391
-                'func'       => 'not_approve_registration',
392
-                'noheader'   => true,
393
-                'args'       => array(true),
394
-                'capability' => 'ee_edit_registration',
395
-                'obj_id'     => $reg_id,
396
-            ),
397
-            'no_approve_registrations'            => array(
398
-                'func'       => 'bulk_action_on_registrations',
399
-                'noheader'   => true,
400
-                'capability' => 'ee_edit_registrations',
401
-                'args'       => array('not_approve'),
402
-            ),
403
-            'no_approve_and_notify_registrations' => array(
404
-                'func'       => 'bulk_action_on_registrations',
405
-                'noheader'   => true,
406
-                'capability' => 'ee_edit_registrations',
407
-                'args'       => array('not_approve', true),
408
-            ),
409
-            'cancel_registration'                 => array(
410
-                'func'       => 'cancel_registration',
411
-                'noheader'   => true,
412
-                'capability' => 'ee_edit_registration',
413
-                'obj_id'     => $reg_id,
414
-            ),
415
-            'cancel_and_notify_registration'      => array(
416
-                'func'       => 'cancel_registration',
417
-                'noheader'   => true,
418
-                'args'       => array(true),
419
-                'capability' => 'ee_edit_registration',
420
-                'obj_id'     => $reg_id,
421
-            ),
422
-            'cancel_registrations'                => array(
423
-                'func'       => 'bulk_action_on_registrations',
424
-                'noheader'   => true,
425
-                'capability' => 'ee_edit_registrations',
426
-                'args'       => array('cancel'),
427
-            ),
428
-            'cancel_and_notify_registrations'     => array(
429
-                'func'       => 'bulk_action_on_registrations',
430
-                'noheader'   => true,
431
-                'capability' => 'ee_edit_registrations',
432
-                'args'       => array('cancel', true),
433
-            ),
434
-            'wait_list_registration'              => array(
435
-                'func'       => 'wait_list_registration',
436
-                'noheader'   => true,
437
-                'capability' => 'ee_edit_registration',
438
-                'obj_id'     => $reg_id,
439
-            ),
440
-            'wait_list_and_notify_registration'   => array(
441
-                'func'       => 'wait_list_registration',
442
-                'noheader'   => true,
443
-                'args'       => array(true),
444
-                'capability' => 'ee_edit_registration',
445
-                'obj_id'     => $reg_id,
446
-            ),
447
-            'contact_list'                        => array(
448
-                'func'       => '_attendee_contact_list_table',
449
-                'capability' => 'ee_read_contacts',
450
-            ),
451
-            'add_new_attendee'                    => array(
452
-                'func' => '_create_new_cpt_item',
453
-                'args' => array(
454
-                    'new_attendee' => true,
455
-                    'capability'   => 'ee_edit_contacts',
456
-                ),
457
-            ),
458
-            'edit_attendee'                       => array(
459
-                'func'       => '_edit_cpt_item',
460
-                'capability' => 'ee_edit_contacts',
461
-                'obj_id'     => $att_id,
462
-            ),
463
-            'duplicate_attendee'                  => array(
464
-                'func'       => '_duplicate_attendee',
465
-                'noheader'   => true,
466
-                'capability' => 'ee_edit_contacts',
467
-                'obj_id'     => $att_id,
468
-            ),
469
-            'insert_attendee'                     => array(
470
-                'func'       => '_insert_or_update_attendee',
471
-                'args'       => array(
472
-                    'new_attendee' => true,
473
-                ),
474
-                'noheader'   => true,
475
-                'capability' => 'ee_edit_contacts',
476
-            ),
477
-            'update_attendee'                     => array(
478
-                'func'       => '_insert_or_update_attendee',
479
-                'args'       => array(
480
-                    'new_attendee' => false,
481
-                ),
482
-                'noheader'   => true,
483
-                'capability' => 'ee_edit_contacts',
484
-                'obj_id'     => $att_id,
485
-            ),
486
-            'trash_attendees'                     => array(
487
-                'func'       => '_trash_or_restore_attendees',
488
-                'args'       => array(
489
-                    'trash' => 'true',
490
-                ),
491
-                'noheader'   => true,
492
-                'capability' => 'ee_delete_contacts',
493
-            ),
494
-            'trash_attendee'                      => array(
495
-                'func'       => '_trash_or_restore_attendees',
496
-                'args'       => array(
497
-                    'trash' => true,
498
-                ),
499
-                'noheader'   => true,
500
-                'capability' => 'ee_delete_contacts',
501
-                'obj_id'     => $att_id,
502
-            ),
503
-            'restore_attendees'                   => array(
504
-                'func'       => '_trash_or_restore_attendees',
505
-                'args'       => array(
506
-                    'trash' => false,
507
-                ),
508
-                'noheader'   => true,
509
-                'capability' => 'ee_delete_contacts',
510
-                'obj_id'     => $att_id,
511
-            ),
512
-            'resend_registration'                 => array(
513
-                'func'       => '_resend_registration',
514
-                'noheader'   => true,
515
-                'capability' => 'ee_send_message',
516
-            ),
517
-            'registrations_report'                => array(
518
-                'func'       => '_registrations_report',
519
-                'noheader'   => true,
520
-                'capability' => 'ee_read_registrations',
521
-            ),
522
-            'contact_list_export'                 => array(
523
-                'func'       => '_contact_list_export',
524
-                'noheader'   => true,
525
-                'capability' => 'export',
526
-            ),
527
-            'contact_list_report'                 => array(
528
-                'func'       => '_contact_list_report',
529
-                'noheader'   => true,
530
-                'capability' => 'ee_read_contacts',
531
-            ),
532
-        );
533
-    }
534
-
535
-
536
-    protected function _set_page_config()
537
-    {
538
-        $this->_page_config = array(
539
-            'default'           => array(
540
-                'nav'           => array(
541
-                    'label' => esc_html__('Overview', 'event_espresso'),
542
-                    'order' => 5,
543
-                ),
544
-                'help_tabs'     => array(
545
-                    'registrations_overview_help_tab'                       => array(
546
-                        'title'    => esc_html__('Registrations Overview', 'event_espresso'),
547
-                        'filename' => 'registrations_overview',
548
-                    ),
549
-                    'registrations_overview_table_column_headings_help_tab' => array(
550
-                        'title'    => esc_html__('Registrations Table Column Headings', 'event_espresso'),
551
-                        'filename' => 'registrations_overview_table_column_headings',
552
-                    ),
553
-                    'registrations_overview_filters_help_tab'               => array(
554
-                        'title'    => esc_html__('Registration Filters', 'event_espresso'),
555
-                        'filename' => 'registrations_overview_filters',
556
-                    ),
557
-                    'registrations_overview_views_help_tab'                 => array(
558
-                        'title'    => esc_html__('Registration Views', 'event_espresso'),
559
-                        'filename' => 'registrations_overview_views',
560
-                    ),
561
-                    'registrations_regoverview_other_help_tab'              => array(
562
-                        'title'    => esc_html__('Registrations Other', 'event_espresso'),
563
-                        'filename' => 'registrations_overview_other',
564
-                    ),
565
-                ),
566
-                'help_tour'     => array('Registration_Overview_Help_Tour'),
567
-                'qtips'         => array('Registration_List_Table_Tips'),
568
-                'list_table'    => 'EE_Registrations_List_Table',
569
-                'require_nonce' => false,
570
-            ),
571
-            'view_registration' => array(
572
-                'nav'           => array(
573
-                    'label'      => esc_html__('REG Details', 'event_espresso'),
574
-                    'order'      => 15,
575
-                    'url'        => isset($this->_req_data['_REG_ID'])
576
-                        ? add_query_arg(array('_REG_ID' => $this->_req_data['_REG_ID']), $this->_current_page_view_url)
577
-                        : $this->_admin_base_url,
578
-                    'persistent' => false,
579
-                ),
580
-                'help_tabs'     => array(
581
-                    'registrations_details_help_tab'                    => array(
582
-                        'title'    => esc_html__('Registration Details', 'event_espresso'),
583
-                        'filename' => 'registrations_details',
584
-                    ),
585
-                    'registrations_details_table_help_tab'              => array(
586
-                        'title'    => esc_html__('Registration Details Table', 'event_espresso'),
587
-                        'filename' => 'registrations_details_table',
588
-                    ),
589
-                    'registrations_details_form_answers_help_tab'       => array(
590
-                        'title'    => esc_html__('Registration Form Answers', 'event_espresso'),
591
-                        'filename' => 'registrations_details_form_answers',
592
-                    ),
593
-                    'registrations_details_registrant_details_help_tab' => array(
594
-                        'title'    => esc_html__('Contact Details', 'event_espresso'),
595
-                        'filename' => 'registrations_details_registrant_details',
596
-                    ),
597
-                ),
598
-                'help_tour'     => array('Registration_Details_Help_Tour'),
599
-                'metaboxes'     => array_merge(
600
-                    $this->_default_espresso_metaboxes,
601
-                    array('_registration_details_metaboxes')
602
-                ),
603
-                'require_nonce' => false,
604
-            ),
605
-            'new_registration'  => array(
606
-                'nav'           => array(
607
-                    'label'      => esc_html__('Add New Registration', 'event_espresso'),
608
-                    'url'        => '#',
609
-                    'order'      => 15,
610
-                    'persistent' => false,
611
-                ),
612
-                'metaboxes'     => $this->_default_espresso_metaboxes,
613
-                'labels'        => array(
614
-                    'publishbox' => esc_html__('Save Registration', 'event_espresso'),
615
-                ),
616
-                'require_nonce' => false,
617
-            ),
618
-            'add_new_attendee'  => array(
619
-                'nav'           => array(
620
-                    'label'      => esc_html__('Add Contact', 'event_espresso'),
621
-                    'order'      => 15,
622
-                    'persistent' => false,
623
-                ),
624
-                'metaboxes'     => array_merge(
625
-                    $this->_default_espresso_metaboxes,
626
-                    array('_publish_post_box', 'attendee_editor_metaboxes')
627
-                ),
628
-                'require_nonce' => false,
629
-            ),
630
-            'edit_attendee'     => array(
631
-                'nav'           => array(
632
-                    'label'      => esc_html__('Edit Contact', 'event_espresso'),
633
-                    'order'      => 15,
634
-                    'persistent' => false,
635
-                    'url'        => isset($this->_req_data['ATT_ID'])
636
-                        ? add_query_arg(array('ATT_ID' => $this->_req_data['ATT_ID']), $this->_current_page_view_url)
637
-                        : $this->_admin_base_url,
638
-                ),
639
-                'metaboxes'     => array('attendee_editor_metaboxes'),
640
-                'require_nonce' => false,
641
-            ),
642
-            'contact_list'      => array(
643
-                'nav'           => array(
644
-                    'label' => esc_html__('Contact List', 'event_espresso'),
645
-                    'order' => 20,
646
-                ),
647
-                'list_table'    => 'EE_Attendee_Contact_List_Table',
648
-                'help_tabs'     => array(
649
-                    'registrations_contact_list_help_tab'                       => array(
650
-                        'title'    => esc_html__('Registrations Contact List', 'event_espresso'),
651
-                        'filename' => 'registrations_contact_list',
652
-                    ),
653
-                    'registrations_contact-list_table_column_headings_help_tab' => array(
654
-                        'title'    => esc_html__('Contact List Table Column Headings', 'event_espresso'),
655
-                        'filename' => 'registrations_contact_list_table_column_headings',
656
-                    ),
657
-                    'registrations_contact_list_views_help_tab'                 => array(
658
-                        'title'    => esc_html__('Contact List Views', 'event_espresso'),
659
-                        'filename' => 'registrations_contact_list_views',
660
-                    ),
661
-                    'registrations_contact_list_other_help_tab'                 => array(
662
-                        'title'    => esc_html__('Contact List Other', 'event_espresso'),
663
-                        'filename' => 'registrations_contact_list_other',
664
-                    ),
665
-                ),
666
-                'help_tour'     => array('Contact_List_Help_Tour'),
667
-                'metaboxes'     => array(),
668
-                'require_nonce' => false,
669
-            ),
670
-            // override default cpt routes
671
-            'create_new'        => '',
672
-            'edit'              => '',
673
-        );
674
-    }
675
-
676
-
677
-    /**
678
-     * The below methods aren't used by this class currently
679
-     */
680
-    protected function _add_screen_options()
681
-    {
682
-    }
683
-
684
-
685
-    protected function _add_feature_pointers()
686
-    {
687
-    }
688
-
689
-
690
-    public function admin_init()
691
-    {
692
-        EE_Registry::$i18n_js_strings['update_att_qstns'] = esc_html__(
693
-            'click "Update Registration Questions" to save your changes',
694
-            'event_espresso'
695
-        );
696
-    }
697
-
698
-
699
-    public function admin_notices()
700
-    {
701
-    }
702
-
703
-
704
-    public function admin_footer_scripts()
705
-    {
706
-    }
707
-
708
-
709
-    /**
710
-     *        get list of registration statuses
711
-     *
712
-     * @access private
713
-     * @return void
714
-     * @throws EE_Error
715
-     */
716
-    private function _get_registration_status_array()
717
-    {
718
-        self::$_reg_status = EEM_Registration::reg_status_array(array(), true);
719
-    }
720
-
721
-
722
-    /**
723
-     * @throws InvalidArgumentException
724
-     * @throws InvalidDataTypeException
725
-     * @throws InvalidInterfaceException
726
-     * @since 4.10.2.p
727
-     */
728
-    protected function _add_screen_options_default()
729
-    {
730
-        $this->_per_page_screen_option();
731
-    }
732
-
733
-
734
-    /**
735
-     * @throws InvalidArgumentException
736
-     * @throws InvalidDataTypeException
737
-     * @throws InvalidInterfaceException
738
-     * @since 4.10.2.p
739
-     */
740
-    protected function _add_screen_options_contact_list()
741
-    {
742
-        $page_title = $this->_admin_page_title;
743
-        $this->_admin_page_title = esc_html__('Contacts', 'event_espresso');
744
-        $this->_per_page_screen_option();
745
-        $this->_admin_page_title = $page_title;
746
-    }
747
-
748
-
749
-    public function load_scripts_styles()
750
-    {
751
-        // style
752
-        wp_register_style(
753
-            'espresso_reg',
754
-            REG_ASSETS_URL . 'espresso_registrations_admin.css',
755
-            array('ee-admin-css'),
756
-            EVENT_ESPRESSO_VERSION
757
-        );
758
-        wp_enqueue_style('espresso_reg');
759
-        // script
760
-        wp_register_script(
761
-            'espresso_reg',
762
-            REG_ASSETS_URL . 'espresso_registrations_admin.js',
763
-            array('jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'),
764
-            EVENT_ESPRESSO_VERSION,
765
-            true
766
-        );
767
-        wp_enqueue_script('espresso_reg');
768
-    }
769
-
770
-
771
-    /**
772
-     * @throws EE_Error
773
-     * @throws InvalidArgumentException
774
-     * @throws InvalidDataTypeException
775
-     * @throws InvalidInterfaceException
776
-     * @throws ReflectionException
777
-     * @since 4.10.2.p
778
-     */
779
-    public function load_scripts_styles_edit_attendee()
780
-    {
781
-        // stuff to only show up on our attendee edit details page.
782
-        $attendee_details_translations = array(
783
-            'att_publish_text' => sprintf(
784
-                /* translators: The date and time */
785
-                wp_strip_all_tags(__('Created on: %s', 'event_espresso')),
786
-                '<b>' . $this->_cpt_model_obj->get_datetime('ATT_created') . '</b>'
787
-            ),
788
-        );
789
-        wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
790
-        wp_enqueue_script('jquery-validate');
791
-    }
792
-
793
-
794
-    /**
795
-     * @throws EE_Error
796
-     * @throws InvalidArgumentException
797
-     * @throws InvalidDataTypeException
798
-     * @throws InvalidInterfaceException
799
-     * @throws ReflectionException
800
-     * @since 4.10.2.p
801
-     */
802
-    public function load_scripts_styles_view_registration()
803
-    {
804
-        // styles
805
-        wp_enqueue_style('espresso-ui-theme');
806
-        // scripts
807
-        $this->_get_reg_custom_questions_form($this->_registration->ID());
808
-        $this->_reg_custom_questions_form->wp_enqueue_scripts(true);
809
-    }
810
-
811
-
812
-    public function load_scripts_styles_contact_list()
813
-    {
814
-        wp_dequeue_style('espresso_reg');
815
-        wp_register_style(
816
-            'espresso_att',
817
-            REG_ASSETS_URL . 'espresso_attendees_admin.css',
818
-            array('ee-admin-css'),
819
-            EVENT_ESPRESSO_VERSION
820
-        );
821
-        wp_enqueue_style('espresso_att');
822
-    }
823
-
824
-
825
-    public function load_scripts_styles_new_registration()
826
-    {
827
-        wp_register_script(
828
-            'ee-spco-for-admin',
829
-            REG_ASSETS_URL . 'spco_for_admin.js',
830
-            array('underscore', 'jquery'),
831
-            EVENT_ESPRESSO_VERSION,
832
-            true
833
-        );
834
-        wp_enqueue_script('ee-spco-for-admin');
835
-        add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
836
-        EE_Form_Section_Proper::wp_enqueue_scripts();
837
-        EED_Ticket_Selector::load_tckt_slctr_assets();
838
-        EE_Datepicker_Input::enqueue_styles_and_scripts();
839
-    }
840
-
841
-
842
-    public function AHEE__EE_Admin_Page__route_admin_request_resend_registration()
843
-    {
844
-        add_filter('FHEE_load_EE_messages', '__return_true');
845
-    }
846
-
847
-
848
-    public function AHEE__EE_Admin_Page__route_admin_request_approve_registration()
849
-    {
850
-        add_filter('FHEE_load_EE_messages', '__return_true');
851
-    }
852
-
853
-
854
-    /**
855
-     * @throws EE_Error
856
-     * @throws InvalidArgumentException
857
-     * @throws InvalidDataTypeException
858
-     * @throws InvalidInterfaceException
859
-     * @throws ReflectionException
860
-     * @since 4.10.2.p
861
-     */
862
-    protected function _set_list_table_views_default()
863
-    {
864
-        // for notification related bulk actions we need to make sure only active messengers have an option.
865
-        EED_Messages::set_autoloaders();
866
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
867
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
868
-        $active_mts = $message_resource_manager->list_of_active_message_types();
869
-        // key= bulk_action_slug, value= message type.
870
-        $match_array = array(
871
-            'approve_registrations'    => 'registration',
872
-            'decline_registrations'    => 'declined_registration',
873
-            'pending_registrations'    => 'pending_approval',
874
-            'no_approve_registrations' => 'not_approved_registration',
875
-            'cancel_registrations'     => 'cancelled_registration',
876
-        );
877
-        $can_send = EE_Registry::instance()->CAP->current_user_can(
878
-            'ee_send_message',
879
-            'batch_send_messages'
880
-        );
881
-        /** setup reg status bulk actions **/
882
-        $def_reg_status_actions['approve_registrations'] = esc_html__('Approve Registrations', 'event_espresso');
883
-        if ($can_send && in_array($match_array['approve_registrations'], $active_mts, true)) {
884
-            $def_reg_status_actions['approve_and_notify_registrations'] = esc_html__(
885
-                'Approve and Notify Registrations',
886
-                'event_espresso'
887
-            );
888
-        }
889
-        $def_reg_status_actions['decline_registrations'] = esc_html__('Decline Registrations', 'event_espresso');
890
-        if ($can_send && in_array($match_array['decline_registrations'], $active_mts, true)) {
891
-            $def_reg_status_actions['decline_and_notify_registrations'] = esc_html__(
892
-                'Decline and Notify Registrations',
893
-                'event_espresso'
894
-            );
895
-        }
896
-        $def_reg_status_actions['pending_registrations'] = esc_html__(
897
-            'Set Registrations to Pending Payment',
898
-            'event_espresso'
899
-        );
900
-        if ($can_send && in_array($match_array['pending_registrations'], $active_mts, true)) {
901
-            $def_reg_status_actions['pending_and_notify_registrations'] = esc_html__(
902
-                'Set Registrations to Pending Payment and Notify',
903
-                'event_espresso'
904
-            );
905
-        }
906
-        $def_reg_status_actions['no_approve_registrations'] = esc_html__(
907
-            'Set Registrations to Not Approved',
908
-            'event_espresso'
909
-        );
910
-        if ($can_send && in_array($match_array['no_approve_registrations'], $active_mts, true)) {
911
-            $def_reg_status_actions['no_approve_and_notify_registrations'] = esc_html__(
912
-                'Set Registrations to Not Approved and Notify',
913
-                'event_espresso'
914
-            );
915
-        }
916
-        $def_reg_status_actions['cancel_registrations'] = esc_html__('Cancel Registrations', 'event_espresso');
917
-        if ($can_send && in_array($match_array['cancel_registrations'], $active_mts, true)) {
918
-            $def_reg_status_actions['cancel_and_notify_registrations'] = esc_html__(
919
-                'Cancel Registrations and Notify',
920
-                'event_espresso'
921
-            );
922
-        }
923
-        $def_reg_status_actions = apply_filters(
924
-            'FHEE__Registrations_Admin_Page___set_list_table_views_default__def_reg_status_actions_array',
925
-            $def_reg_status_actions,
926
-            $active_mts,
927
-            $can_send
928
-        );
929
-
930
-        $this->_views = array(
931
-            'all'   => array(
932
-                'slug'        => 'all',
933
-                'label'       => esc_html__('View All Registrations', 'event_espresso'),
934
-                'count'       => 0,
935
-                'bulk_action' => array_merge(
936
-                    $def_reg_status_actions,
937
-                    array(
938
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
939
-                    )
940
-                ),
941
-            ),
942
-            'month' => array(
943
-                'slug'        => 'month',
944
-                'label'       => esc_html__('This Month', 'event_espresso'),
945
-                'count'       => 0,
946
-                'bulk_action' => array_merge(
947
-                    $def_reg_status_actions,
948
-                    array(
949
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
950
-                    )
951
-                ),
952
-            ),
953
-            'today' => array(
954
-                'slug'        => 'today',
955
-                'label'       => sprintf(
956
-                    esc_html__('Today - %s', 'event_espresso'),
957
-                    date('M d, Y', current_time('timestamp'))
958
-                ),
959
-                'count'       => 0,
960
-                'bulk_action' => array_merge(
961
-                    $def_reg_status_actions,
962
-                    array(
963
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
964
-                    )
965
-                ),
966
-            ),
967
-        );
968
-        if (EE_Registry::instance()->CAP->current_user_can(
969
-            'ee_delete_registrations',
970
-            'espresso_registrations_delete_registration'
971
-        )) {
972
-            $this->_views['incomplete'] = array(
973
-                'slug'        => 'incomplete',
974
-                'label'       => esc_html__('Incomplete', 'event_espresso'),
975
-                'count'       => 0,
976
-                'bulk_action' => array(
977
-                    'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
978
-                ),
979
-            );
980
-            $this->_views['trash'] = array(
981
-                'slug'        => 'trash',
982
-                'label'       => esc_html__('Trash', 'event_espresso'),
983
-                'count'       => 0,
984
-                'bulk_action' => array(
985
-                    'restore_registrations' => esc_html__('Restore Registrations', 'event_espresso'),
986
-                    'delete_registrations'  => esc_html__('Delete Registrations Permanently', 'event_espresso'),
987
-                ),
988
-            );
989
-        }
990
-    }
991
-
992
-
993
-    protected function _set_list_table_views_contact_list()
994
-    {
995
-        $this->_views = array(
996
-            'in_use' => array(
997
-                'slug'        => 'in_use',
998
-                'label'       => esc_html__('In Use', 'event_espresso'),
999
-                'count'       => 0,
1000
-                'bulk_action' => array(
1001
-                    'trash_attendees' => esc_html__('Move to Trash', 'event_espresso'),
1002
-                ),
1003
-            ),
1004
-        );
1005
-        if (EE_Registry::instance()->CAP->current_user_can(
1006
-            'ee_delete_contacts',
1007
-            'espresso_registrations_trash_attendees'
1008
-        )
1009
-        ) {
1010
-            $this->_views['trash'] = array(
1011
-                'slug'        => 'trash',
1012
-                'label'       => esc_html__('Trash', 'event_espresso'),
1013
-                'count'       => 0,
1014
-                'bulk_action' => array(
1015
-                    'restore_attendees' => esc_html__('Restore from Trash', 'event_espresso'),
1016
-                ),
1017
-            );
1018
-        }
1019
-    }
1020
-
1021
-
1022
-    protected function _registration_legend_items()
1023
-    {
1024
-        $fc_items = array(
1025
-            'star-icon'        => array(
1026
-                'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
1027
-                'desc'  => esc_html__('This is the Primary Registrant', 'event_espresso'),
1028
-            ),
1029
-            'view_details'     => array(
1030
-                'class' => 'dashicons dashicons-clipboard',
1031
-                'desc'  => esc_html__('View Registration Details', 'event_espresso'),
1032
-            ),
1033
-            'edit_attendee'    => array(
1034
-                'class' => 'ee-icon ee-icon-user-edit ee-icon-size-16',
1035
-                'desc'  => esc_html__('Edit Contact Details', 'event_espresso'),
1036
-            ),
1037
-            'view_transaction' => array(
1038
-                'class' => 'dashicons dashicons-cart',
1039
-                'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
1040
-            ),
1041
-            'view_invoice'     => array(
1042
-                'class' => 'dashicons dashicons-media-spreadsheet',
1043
-                'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
1044
-            ),
1045
-        );
1046
-        if (EE_Registry::instance()->CAP->current_user_can(
1047
-            'ee_send_message',
1048
-            'espresso_registrations_resend_registration'
1049
-        )) {
1050
-            $fc_items['resend_registration'] = array(
1051
-                'class' => 'dashicons dashicons-email-alt',
1052
-                'desc'  => esc_html__('Resend Registration Details', 'event_espresso'),
1053
-            );
1054
-        } else {
1055
-            $fc_items['blank'] = array('class' => 'blank', 'desc' => '');
1056
-        }
1057
-        if (EE_Registry::instance()->CAP->current_user_can(
1058
-            'ee_read_global_messages',
1059
-            'view_filtered_messages'
1060
-        )) {
1061
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
1062
-            if (is_array($related_for_icon) && isset($related_for_icon['css_class'], $related_for_icon['label'])) {
1063
-                $fc_items['view_related_messages'] = array(
1064
-                    'class' => $related_for_icon['css_class'],
1065
-                    'desc'  => $related_for_icon['label'],
1066
-                );
1067
-            }
1068
-        }
1069
-        $sc_items = array(
1070
-            'approved_status'   => array(
1071
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
1072
-                'desc'  => EEH_Template::pretty_status(
1073
-                    EEM_Registration::status_id_approved,
1074
-                    false,
1075
-                    'sentence'
1076
-                ),
1077
-            ),
1078
-            'pending_status'    => array(
1079
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
1080
-                'desc'  => EEH_Template::pretty_status(
1081
-                    EEM_Registration::status_id_pending_payment,
1082
-                    false,
1083
-                    'sentence'
1084
-                ),
1085
-            ),
1086
-            'wait_list'         => array(
1087
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
1088
-                'desc'  => EEH_Template::pretty_status(
1089
-                    EEM_Registration::status_id_wait_list,
1090
-                    false,
1091
-                    'sentence'
1092
-                ),
1093
-            ),
1094
-            'incomplete_status' => array(
1095
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
1096
-                'desc'  => EEH_Template::pretty_status(
1097
-                    EEM_Registration::status_id_incomplete,
1098
-                    false,
1099
-                    'sentence'
1100
-                ),
1101
-            ),
1102
-            'not_approved'      => array(
1103
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
1104
-                'desc'  => EEH_Template::pretty_status(
1105
-                    EEM_Registration::status_id_not_approved,
1106
-                    false,
1107
-                    'sentence'
1108
-                ),
1109
-            ),
1110
-            'declined_status'   => array(
1111
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
1112
-                'desc'  => EEH_Template::pretty_status(
1113
-                    EEM_Registration::status_id_declined,
1114
-                    false,
1115
-                    'sentence'
1116
-                ),
1117
-            ),
1118
-            'cancelled_status'  => array(
1119
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1120
-                'desc'  => EEH_Template::pretty_status(
1121
-                    EEM_Registration::status_id_cancelled,
1122
-                    false,
1123
-                    'sentence'
1124
-                ),
1125
-            ),
1126
-        );
1127
-        return array_merge($fc_items, $sc_items);
1128
-    }
1129
-
1130
-
1131
-
1132
-    /***************************************        REGISTRATION OVERVIEW        **************************************/
1133
-
1134
-
1135
-
1136
-    /**
1137
-     * @throws DomainException
1138
-     * @throws EE_Error
1139
-     * @throws InvalidArgumentException
1140
-     * @throws InvalidDataTypeException
1141
-     * @throws InvalidInterfaceException
1142
-     * @throws ReflectionException
1143
-     */
1144
-    protected function _registrations_overview_list_table()
1145
-    {
1146
-        $this->appendAddNewRegistrationButtonToPageTitle();
1147
-        $header_text = '';
1148
-        $admin_page_header_decorators = [
1149
-            'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\AttendeeFilterHeader',
1150
-            'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\EventFilterHeader',
1151
-            'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\DateFilterHeader',
1152
-            'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\TicketFilterHeader',
1153
-        ];
1154
-        foreach ($admin_page_header_decorators as $admin_page_header_decorator) {
1155
-            $filter_header_decorator = $this->getLoader()->getNew($admin_page_header_decorator);
1156
-            $header_text = $filter_header_decorator->getHeaderText($header_text);
1157
-        }
1158
-        $this->_template_args['admin_page_header'] = $header_text;
1159
-        $this->_template_args['after_list_table'] = $this->_display_legend($this->_registration_legend_items());
1160
-        $this->display_admin_list_table_page_with_no_sidebar();
1161
-    }
1162
-
1163
-
1164
-    /**
1165
-     * @throws EE_Error
1166
-     * @throws InvalidArgumentException
1167
-     * @throws InvalidDataTypeException
1168
-     * @throws InvalidInterfaceException
1169
-     */
1170
-    private function appendAddNewRegistrationButtonToPageTitle()
1171
-    {
1172
-        $EVT_ID = ! empty($this->_req_data['event_id'])
1173
-            ? absint($this->_req_data['event_id'])
1174
-            : 0;
1175
-        if ($EVT_ID
1176
-            && EE_Registry::instance()->CAP->current_user_can(
1177
-                'ee_edit_registrations',
1178
-                'espresso_registrations_new_registration',
1179
-                $EVT_ID
1180
-            )
1181
-        ) {
1182
-            $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1183
-                'new_registration',
1184
-                'add-registrant',
1185
-                array('event_id' => $EVT_ID),
1186
-                'add-new-h2'
1187
-            );
1188
-        }
1189
-    }
1190
-
1191
-
1192
-    /**
1193
-     * This sets the _registration property for the registration details screen
1194
-     *
1195
-     * @access private
1196
-     * @return bool
1197
-     * @throws EE_Error
1198
-     * @throws InvalidArgumentException
1199
-     * @throws InvalidDataTypeException
1200
-     * @throws InvalidInterfaceException
1201
-     */
1202
-    private function _set_registration_object()
1203
-    {
1204
-        // get out if we've already set the object
1205
-        if ($this->_registration instanceof EE_Registration) {
1206
-            return true;
1207
-        }
1208
-        $REG_ID = (! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1209
-        if ($this->_registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID)) {
1210
-            return true;
1211
-        }
1212
-        $error_msg = sprintf(
1213
-            esc_html__(
1214
-                'An error occurred and the details for Registration ID #%s could not be retrieved.',
1215
-                'event_espresso'
1216
-            ),
1217
-            $REG_ID
1218
-        );
1219
-        EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
1220
-        $this->_registration = null;
1221
-        return false;
1222
-    }
1223
-
1224
-
1225
-    /**
1226
-     * Used to retrieve registrations for the list table.
1227
-     *
1228
-     * @param int  $per_page
1229
-     * @param bool $count
1230
-     * @param bool $this_month
1231
-     * @param bool $today
1232
-     * @return EE_Registration[]|int
1233
-     * @throws EE_Error
1234
-     * @throws InvalidArgumentException
1235
-     * @throws InvalidDataTypeException
1236
-     * @throws InvalidInterfaceException
1237
-     */
1238
-    public function get_registrations(
1239
-        $per_page = 10,
1240
-        $count = false,
1241
-        $this_month = false,
1242
-        $today = false
1243
-    ) {
1244
-        if ($this_month) {
1245
-            $this->_req_data['status'] = 'month';
1246
-        }
1247
-        if ($today) {
1248
-            $this->_req_data['status'] = 'today';
1249
-        }
1250
-        $query_params = $this->_get_registration_query_parameters($this->_req_data, $per_page, $count);
1251
-        /**
1252
-         * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1253
-         *
1254
-         * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1255
-         * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1256
-         *                             or if you have the development copy of EE you can view this at the path:
1257
-         *                             /docs/G--Model-System/model-query-params.md
1258
-         */
1259
-        $query_params['group_by'] = '';
1260
-
1261
-        return $count
1262
-            ? $this->getRegistrationModel()->count($query_params)
1263
-            /** @type EE_Registration[] */
1264
-            : $this->getRegistrationModel()->get_all($query_params);
1265
-    }
1266
-
1267
-
1268
-    /**
1269
-     * Retrieves the query parameters to be used by the Registration model for getting registrations.
1270
-     * Note: this listens to values on the request for some of the query parameters.
1271
-     *
1272
-     * @param array $request
1273
-     * @param int   $per_page
1274
-     * @param bool  $count
1275
-     * @return array
1276
-     * @throws EE_Error
1277
-     * @throws InvalidArgumentException
1278
-     * @throws InvalidDataTypeException
1279
-     * @throws InvalidInterfaceException
1280
-     */
1281
-    protected function _get_registration_query_parameters(
1282
-        $request = array(),
1283
-        $per_page = 10,
1284
-        $count = false
1285
-    ) {
1286
-        /** @var EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder $list_table_query_builder */
1287
-        $list_table_query_builder = $this->getLoader()->getNew(
1288
-            'EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder',
1289
-            [ $request ]
1290
-        );
1291
-        return $list_table_query_builder->getQueryParams($per_page, $count);
1292
-    }
1293
-
1294
-
1295
-    public function get_registration_status_array()
1296
-    {
1297
-        return self::$_reg_status;
1298
-    }
1299
-
1300
-
1301
-
1302
-
1303
-    /***************************************        REGISTRATION DETAILS        ***************************************/
1304
-    /**
1305
-     *        generates HTML for the View Registration Details Admin page
1306
-     *
1307
-     * @access protected
1308
-     * @return void
1309
-     * @throws DomainException
1310
-     * @throws EE_Error
1311
-     * @throws InvalidArgumentException
1312
-     * @throws InvalidDataTypeException
1313
-     * @throws InvalidInterfaceException
1314
-     * @throws EntityNotFoundException
1315
-     * @throws ReflectionException
1316
-     */
1317
-    protected function _registration_details()
1318
-    {
1319
-        $this->_template_args = array();
1320
-        $this->_set_registration_object();
1321
-        if (is_object($this->_registration)) {
1322
-            $transaction = $this->_registration->transaction()
1323
-                ? $this->_registration->transaction()
1324
-                : EE_Transaction::new_instance();
1325
-            $this->_session = $transaction->session_data();
1326
-            $event_id = $this->_registration->event_ID();
1327
-            $this->_template_args['reg_nmbr']['value'] = $this->_registration->ID();
1328
-            $this->_template_args['reg_nmbr']['label'] = esc_html__('Registration Number', 'event_espresso');
1329
-            $this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1330
-            $this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1331
-            $this->_template_args['grand_total'] = $transaction->total();
1332
-            $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
1333
-            // link back to overview
1334
-            $this->_template_args['reg_overview_url'] = REG_ADMIN_URL;
1335
-            $this->_template_args['registration'] = $this->_registration;
1336
-            $this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1337
-                array(
1338
-                    'action'   => 'default',
1339
-                    'event_id' => $event_id,
1340
-                ),
1341
-                REG_ADMIN_URL
1342
-            );
1343
-            $this->_template_args['filtered_transactions_link'] = EE_Admin_Page::add_query_args_and_nonce(
1344
-                array(
1345
-                    'action' => 'default',
1346
-                    'EVT_ID' => $event_id,
1347
-                    'page'   => 'espresso_transactions',
1348
-                ),
1349
-                admin_url('admin.php')
1350
-            );
1351
-            $this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
1352
-                array(
1353
-                    'page'   => 'espresso_events',
1354
-                    'action' => 'edit',
1355
-                    'post'   => $event_id,
1356
-                ),
1357
-                admin_url('admin.php')
1358
-            );
1359
-            // next and previous links
1360
-            $next_reg = $this->_registration->next(
1361
-                null,
1362
-                array(),
1363
-                'REG_ID'
1364
-            );
1365
-            $this->_template_args['next_registration'] = $next_reg
1366
-                ? $this->_next_link(
1367
-                    EE_Admin_Page::add_query_args_and_nonce(
1368
-                        array(
1369
-                            'action'  => 'view_registration',
1370
-                            '_REG_ID' => $next_reg['REG_ID'],
1371
-                        ),
1372
-                        REG_ADMIN_URL
1373
-                    ),
1374
-                    'dashicons dashicons-arrow-right ee-icon-size-22'
1375
-                )
1376
-                : '';
1377
-            $previous_reg = $this->_registration->previous(
1378
-                null,
1379
-                array(),
1380
-                'REG_ID'
1381
-            );
1382
-            $this->_template_args['previous_registration'] = $previous_reg
1383
-                ? $this->_previous_link(
1384
-                    EE_Admin_Page::add_query_args_and_nonce(
1385
-                        array(
1386
-                            'action'  => 'view_registration',
1387
-                            '_REG_ID' => $previous_reg['REG_ID'],
1388
-                        ),
1389
-                        REG_ADMIN_URL
1390
-                    ),
1391
-                    'dashicons dashicons-arrow-left ee-icon-size-22'
1392
-                )
1393
-                : '';
1394
-            // grab header
1395
-            $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1396
-            $this->_template_args['REG_ID'] = $this->_registration->ID();
1397
-            $this->_template_args['admin_page_header'] = EEH_Template::display_template(
1398
-                $template_path,
1399
-                $this->_template_args,
1400
-                true
1401
-            );
1402
-        } else {
1403
-            $this->_template_args['admin_page_header'] = $this->display_espresso_notices();
1404
-        }
1405
-        // the details template wrapper
1406
-        $this->display_admin_page_with_sidebar();
1407
-    }
1408
-
1409
-
1410
-    /**
1411
-     * @throws EE_Error
1412
-     * @throws InvalidArgumentException
1413
-     * @throws InvalidDataTypeException
1414
-     * @throws InvalidInterfaceException
1415
-     * @throws ReflectionException
1416
-     * @since 4.10.2.p
1417
-     */
1418
-    protected function _registration_details_metaboxes()
1419
-    {
1420
-        do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1421
-        $this->_set_registration_object();
1422
-        $attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1423
-        add_meta_box(
1424
-            'edit-reg-status-mbox',
1425
-            esc_html__('Registration Status', 'event_espresso'),
1426
-            array($this, 'set_reg_status_buttons_metabox'),
1427
-            $this->wp_page_slug,
1428
-            'normal',
1429
-            'high'
1430
-        );
1431
-        add_meta_box(
1432
-            'edit-reg-details-mbox',
1433
-            esc_html__('Registration Details', 'event_espresso'),
1434
-            array($this, '_reg_details_meta_box'),
1435
-            $this->wp_page_slug,
1436
-            'normal',
1437
-            'high'
1438
-        );
1439
-        if ($attendee instanceof EE_Attendee
1440
-            && EE_Registry::instance()->CAP->current_user_can(
1441
-                'ee_read_registration',
1442
-                'edit-reg-questions-mbox',
1443
-                $this->_registration->ID()
1444
-            )
1445
-        ) {
1446
-            add_meta_box(
1447
-                'edit-reg-questions-mbox',
1448
-                esc_html__('Registration Form Answers', 'event_espresso'),
1449
-                array($this, '_reg_questions_meta_box'),
1450
-                $this->wp_page_slug,
1451
-                'normal',
1452
-                'high'
1453
-            );
1454
-        }
1455
-        add_meta_box(
1456
-            'edit-reg-registrant-mbox',
1457
-            esc_html__('Contact Details', 'event_espresso'),
1458
-            array($this, '_reg_registrant_side_meta_box'),
1459
-            $this->wp_page_slug,
1460
-            'side',
1461
-            'high'
1462
-        );
1463
-        if ($this->_registration->group_size() > 1) {
1464
-            add_meta_box(
1465
-                'edit-reg-attendees-mbox',
1466
-                esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1467
-                array($this, '_reg_attendees_meta_box'),
1468
-                $this->wp_page_slug,
1469
-                'normal',
1470
-                'high'
1471
-            );
1472
-        }
1473
-    }
1474
-
1475
-
1476
-    /**
1477
-     * set_reg_status_buttons_metabox
1478
-     *
1479
-     * @access protected
1480
-     * @return string
1481
-     * @throws EE_Error
1482
-     * @throws EntityNotFoundException
1483
-     * @throws InvalidArgumentException
1484
-     * @throws InvalidDataTypeException
1485
-     * @throws InvalidInterfaceException
1486
-     * @throws ReflectionException
1487
-     */
1488
-    public function set_reg_status_buttons_metabox()
1489
-    {
1490
-        $this->_set_registration_object();
1491
-        $change_reg_status_form = $this->_generate_reg_status_change_form();
1492
-        echo $change_reg_status_form->form_open(
1493
-            self::add_query_args_and_nonce(
1494
-                array(
1495
-                    'action' => 'change_reg_status',
1496
-                ),
1497
-                REG_ADMIN_URL
1498
-            )
1499
-        );
1500
-        echo $change_reg_status_form->get_html();
1501
-        echo $change_reg_status_form->form_close();
1502
-    }
1503
-
1504
-
1505
-    /**
1506
-     * @return EE_Form_Section_Proper
1507
-     * @throws EE_Error
1508
-     * @throws InvalidArgumentException
1509
-     * @throws InvalidDataTypeException
1510
-     * @throws InvalidInterfaceException
1511
-     * @throws EntityNotFoundException
1512
-     * @throws ReflectionException
1513
-     */
1514
-    protected function _generate_reg_status_change_form()
1515
-    {
1516
-        $reg_status_change_form_array = array(
1517
-            'name'            => 'reg_status_change_form',
1518
-            'html_id'         => 'reg-status-change-form',
1519
-            'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1520
-            'subsections'     => array(
1521
-                'return'             => new EE_Hidden_Input(
1522
-                    array(
1523
-                        'name'    => 'return',
1524
-                        'default' => 'view_registration',
1525
-                    )
1526
-                ),
1527
-                'REG_ID'             => new EE_Hidden_Input(
1528
-                    array(
1529
-                        'name'    => 'REG_ID',
1530
-                        'default' => $this->_registration->ID(),
1531
-                    )
1532
-                ),
1533
-                'current_status'     => new EE_Form_Section_HTML(
1534
-                    EEH_HTML::table(
1535
-                        EEH_HTML::tr(
1536
-                            EEH_HTML::th(
1537
-                                EEH_HTML::label(
1538
-                                    EEH_HTML::strong(
1539
-                                        esc_html__('Current Registration Status', 'event_espresso')
1540
-                                    )
1541
-                                )
1542
-                            )
1543
-                            . EEH_HTML::td(
1544
-                                EEH_HTML::strong(
1545
-                                    $this->_registration->pretty_status(),
1546
-                                    '',
1547
-                                    'status-' . $this->_registration->status_ID(),
1548
-                                    'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1549
-                                )
1550
-                            )
1551
-                        )
1552
-                    )
1553
-                )
1554
-            )
1555
-        );
1556
-        if (EE_Registry::instance()->CAP->current_user_can(
1557
-            'ee_edit_registration',
1558
-            'toggle_registration_status',
1559
-            $this->_registration->ID()
1560
-        )) {
1561
-            $reg_status_change_form_array['subsections']['reg_status'] = new EE_Select_Input(
1562
-                $this->_get_reg_statuses(),
1563
-                array(
1564
-                    'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1565
-                    'default'         => $this->_registration->status_ID(),
1566
-                )
1567
-            );
1568
-            $reg_status_change_form_array['subsections']['send_notifications'] = new EE_Yes_No_Input(
1569
-                array(
1570
-                    'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1571
-                    'default'         => false,
1572
-                    'html_help_text'  => esc_html__(
1573
-                        'If set to "Yes", then the related messages will be sent to the registrant.',
1574
-                        'event_espresso'
1575
-                    )
1576
-                )
1577
-            );
1578
-            $reg_status_change_form_array['subsections']['submit'] = new EE_Submit_Input(
1579
-                array(
1580
-                    'html_class'      => 'button-primary',
1581
-                    'html_label_text' => '&nbsp;',
1582
-                    'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1583
-                )
1584
-            );
1585
-        }
1586
-        return new EE_Form_Section_Proper($reg_status_change_form_array);
1587
-    }
1588
-
1589
-
1590
-    /**
1591
-     * Returns an array of all the buttons for the various statuses and switch status actions
1592
-     *
1593
-     * @return array
1594
-     * @throws EE_Error
1595
-     * @throws InvalidArgumentException
1596
-     * @throws InvalidDataTypeException
1597
-     * @throws InvalidInterfaceException
1598
-     * @throws EntityNotFoundException
1599
-     */
1600
-    protected function _get_reg_statuses()
1601
-    {
1602
-        $reg_status_array = $this->getRegistrationModel()->reg_status_array();
1603
-        unset($reg_status_array[ EEM_Registration::status_id_incomplete ]);
1604
-        // get current reg status
1605
-        $current_status = $this->_registration->status_ID();
1606
-        // is registration for free event? This will determine whether to display the pending payment option
1607
-        if ($current_status !== EEM_Registration::status_id_pending_payment
1608
-            && EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1609
-        ) {
1610
-            unset($reg_status_array[ EEM_Registration::status_id_pending_payment ]);
1611
-        }
1612
-        return $this->getStatusModel()->localized_status($reg_status_array, false, 'sentence');
1613
-    }
1614
-
1615
-
1616
-    /**
1617
-     * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1618
-     *
1619
-     * @param bool $status REG status given for changing registrations to.
1620
-     * @param bool $notify Whether to send messages notifications or not.
1621
-     * @return array (array with reg_id(s) updated and whether update was successful.
1622
-     * @throws DomainException
1623
-     * @throws EE_Error
1624
-     * @throws EntityNotFoundException
1625
-     * @throws InvalidArgumentException
1626
-     * @throws InvalidDataTypeException
1627
-     * @throws InvalidInterfaceException
1628
-     * @throws ReflectionException
1629
-     * @throws RuntimeException
1630
-     */
1631
-    protected function _set_registration_status_from_request($status = false, $notify = false)
1632
-    {
1633
-        if (isset($this->_req_data['reg_status_change_form'])) {
1634
-            $REG_IDs = isset($this->_req_data['reg_status_change_form']['REG_ID'])
1635
-                ? (array) $this->_req_data['reg_status_change_form']['REG_ID']
1636
-                : array();
1637
-        } else {
1638
-            $REG_IDs = isset($this->_req_data['_REG_ID'])
1639
-                ? (array) $this->_req_data['_REG_ID']
1640
-                : array();
1641
-        }
1642
-        // sanitize $REG_IDs
1643
-        $REG_IDs = array_map('absint', $REG_IDs);
1644
-        // and remove empty entries
1645
-        $REG_IDs = array_filter($REG_IDs);
1646
-
1647
-        $result = $this->_set_registration_status($REG_IDs, $status, $notify);
1648
-
1649
-        /**
1650
-         * Set and filter $_req_data['_REG_ID'] for any potential future messages notifications.
1651
-         * Currently this value is used downstream by the _process_resend_registration method.
1652
-         *
1653
-         * @param int|array                $registration_ids The registration ids that have had their status changed successfully.
1654
-         * @param bool                     $status           The status registrations were changed to.
1655
-         * @param bool                     $success          If the status was changed successfully for all registrations.
1656
-         * @param Registrations_Admin_Page $admin_page_object
1657
-         */
1658
-        $this->_req_data['_REG_ID'] = apply_filters(
1659
-            'FHEE__Registrations_Admin_Page___set_registration_status_from_request__REG_IDs',
1660
-            $result['REG_ID'],
1661
-            $status,
1662
-            $result['success'],
1663
-            $this
1664
-        );
1665
-
1666
-        // notify?
1667
-        if ($notify
1668
-            && $result['success']
1669
-            && ! empty($this->_req_data['_REG_ID'])
1670
-            && EE_Registry::instance()->CAP->current_user_can(
1671
-                'ee_send_message',
1672
-                'espresso_registrations_resend_registration'
1673
-            )
1674
-        ) {
1675
-            $this->_process_resend_registration();
1676
-        }
1677
-        return $result;
1678
-    }
1679
-
1680
-
1681
-    /**
1682
-     * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1683
-     * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1684
-     *
1685
-     * @param array  $REG_IDs
1686
-     * @param string $status
1687
-     * @param bool   $notify  Used to indicate whether notification was requested or not.  This determines the context
1688
-     *                        slug sent with setting the registration status.
1689
-     * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1690
-     * @throws EE_Error
1691
-     * @throws InvalidArgumentException
1692
-     * @throws InvalidDataTypeException
1693
-     * @throws InvalidInterfaceException
1694
-     * @throws ReflectionException
1695
-     * @throws RuntimeException
1696
-     * @throws EntityNotFoundException
1697
-     * @throws DomainException
1698
-     */
1699
-    protected function _set_registration_status($REG_IDs = array(), $status = '', $notify = false)
1700
-    {
1701
-        $success = false;
1702
-        // typecast $REG_IDs
1703
-        $REG_IDs = (array) $REG_IDs;
1704
-        if (! empty($REG_IDs)) {
1705
-            $success = true;
1706
-            // set default status if none is passed
1707
-            $status = $status ? $status : EEM_Registration::status_id_pending_payment;
1708
-            $status_context = $notify
1709
-                ? Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
1710
-                : Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN;
1711
-            // loop through REG_ID's and change status
1712
-            foreach ($REG_IDs as $REG_ID) {
1713
-                $registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
1714
-                if ($registration instanceof EE_Registration) {
1715
-                    $registration->set_status(
1716
-                        $status,
1717
-                        false,
1718
-                        new Context(
1719
-                            $status_context,
1720
-                            esc_html__(
1721
-                                'Manually triggered status change on a Registration Admin Page route.',
1722
-                                'event_espresso'
1723
-                            )
1724
-                        )
1725
-                    );
1726
-                    $result = $registration->save();
1727
-                    // verifying explicit fails because update *may* just return 0 for 0 rows affected
1728
-                    $success = $result !== false ? $success : false;
1729
-                }
1730
-            }
1731
-        }
1732
-
1733
-        // return $success and processed registrations
1734
-        return array('REG_ID' => $REG_IDs, 'success' => $success);
1735
-    }
1736
-
1737
-
1738
-    /**
1739
-     * Common logic for setting up success message and redirecting to appropriate route
1740
-     *
1741
-     * @param string $STS_ID status id for the registration changed to
1742
-     * @param bool   $notify indicates whether the _set_registration_status_from_request does notifications or not.
1743
-     * @return void
1744
-     * @throws DomainException
1745
-     * @throws EE_Error
1746
-     * @throws EntityNotFoundException
1747
-     * @throws InvalidArgumentException
1748
-     * @throws InvalidDataTypeException
1749
-     * @throws InvalidInterfaceException
1750
-     * @throws ReflectionException
1751
-     * @throws RuntimeException
1752
-     */
1753
-    protected function _reg_status_change_return($STS_ID, $notify = false)
1754
-    {
1755
-        $result = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1756
-            : array('success' => false);
1757
-        $success = isset($result['success']) && $result['success'];
1758
-        // setup success message
1759
-        if ($success) {
1760
-            if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1761
-                $msg = sprintf(
1762
-                    esc_html__('Registration status has been set to %s', 'event_espresso'),
1763
-                    EEH_Template::pretty_status($STS_ID, false, 'lower')
1764
-                );
1765
-            } else {
1766
-                $msg = sprintf(
1767
-                    esc_html__('Registrations have been set to %s.', 'event_espresso'),
1768
-                    EEH_Template::pretty_status($STS_ID, false, 'lower')
1769
-                );
1770
-            }
1771
-            EE_Error::add_success($msg);
1772
-        } else {
1773
-            EE_Error::add_error(
1774
-                esc_html__(
1775
-                    'Something went wrong, and the status was not changed',
1776
-                    'event_espresso'
1777
-                ),
1778
-                __FILE__,
1779
-                __LINE__,
1780
-                __FUNCTION__
1781
-            );
1782
-        }
1783
-        if (isset($this->_req_data['return']) && $this->_req_data['return'] === 'view_registration') {
1784
-            $route = array('action' => 'view_registration', '_REG_ID' => reset($result['REG_ID']));
1785
-        } else {
1786
-            $route = array('action' => 'default');
1787
-        }
1788
-        $route = $this->mergeExistingRequestParamsWithRedirectArgs($route);
1789
-        $this->_redirect_after_action($success, '', '', $route, true);
1790
-    }
1791
-
1792
-
1793
-    /**
1794
-     * incoming reg status change from reg details page.
1795
-     *
1796
-     * @return void
1797
-     * @throws EE_Error
1798
-     * @throws EntityNotFoundException
1799
-     * @throws InvalidArgumentException
1800
-     * @throws InvalidDataTypeException
1801
-     * @throws InvalidInterfaceException
1802
-     * @throws ReflectionException
1803
-     * @throws RuntimeException
1804
-     * @throws DomainException
1805
-     */
1806
-    protected function _change_reg_status()
1807
-    {
1808
-        $this->_req_data['return'] = 'view_registration';
1809
-        // set notify based on whether the send notifications toggle is set or not
1810
-        $notify = ! empty($this->_req_data['reg_status_change_form']['send_notifications']);
1811
-        // $notify = ! empty( $this->_req_data['txn_reg_status_change']['send_notifications'] );
1812
-        $this->_req_data['reg_status_change_form']['reg_status'] = isset($this->_req_data['reg_status_change_form']['reg_status'])
1813
-            ? $this->_req_data['reg_status_change_form']['reg_status'] : '';
1814
-        switch ($this->_req_data['reg_status_change_form']['reg_status']) {
1815
-            case EEM_Registration::status_id_approved:
1816
-            case EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'):
1817
-                $this->approve_registration($notify);
1818
-                break;
1819
-            case EEM_Registration::status_id_pending_payment:
1820
-            case EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'):
1821
-                $this->pending_registration($notify);
1822
-                break;
1823
-            case EEM_Registration::status_id_not_approved:
1824
-            case EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'):
1825
-                $this->not_approve_registration($notify);
1826
-                break;
1827
-            case EEM_Registration::status_id_declined:
1828
-            case EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'):
1829
-                $this->decline_registration($notify);
1830
-                break;
1831
-            case EEM_Registration::status_id_cancelled:
1832
-            case EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'):
1833
-                $this->cancel_registration($notify);
1834
-                break;
1835
-            case EEM_Registration::status_id_wait_list:
1836
-            case EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'):
1837
-                $this->wait_list_registration($notify);
1838
-                break;
1839
-            case EEM_Registration::status_id_incomplete:
1840
-            default:
1841
-                $result['success'] = false;
1842
-                unset($this->_req_data['return']);
1843
-                $this->_reg_status_change_return('', false);
1844
-                break;
1845
-        }
1846
-    }
1847
-
1848
-
1849
-    /**
1850
-     * Callback for bulk action routes.
1851
-     * Note: although we could just register the singular route callbacks for each bulk action route as well, this
1852
-     * method was chosen so there is one central place all the registration status bulk actions are going through.
1853
-     * Potentially, this provides an easier place to locate logic that is specific to these bulk actions (as opposed to
1854
-     * when an action is happening on just a single registration).
1855
-     *
1856
-     * @param      $action
1857
-     * @param bool $notify
1858
-     */
1859
-    protected function bulk_action_on_registrations($action, $notify = false)
1860
-    {
1861
-        do_action(
1862
-            'AHEE__Registrations_Admin_Page__bulk_action_on_registrations__before_execution',
1863
-            $this,
1864
-            $action,
1865
-            $notify
1866
-        );
1867
-        $method = $action . '_registration';
1868
-        if (method_exists($this, $method)) {
1869
-            $this->$method($notify);
1870
-        }
1871
-    }
1872
-
1873
-
1874
-    /**
1875
-     * approve_registration
1876
-     *
1877
-     * @access protected
1878
-     * @param bool $notify whether or not to notify the registrant about their approval.
1879
-     * @return void
1880
-     * @throws EE_Error
1881
-     * @throws EntityNotFoundException
1882
-     * @throws InvalidArgumentException
1883
-     * @throws InvalidDataTypeException
1884
-     * @throws InvalidInterfaceException
1885
-     * @throws ReflectionException
1886
-     * @throws RuntimeException
1887
-     * @throws DomainException
1888
-     */
1889
-    protected function approve_registration($notify = false)
1890
-    {
1891
-        $this->_reg_status_change_return(EEM_Registration::status_id_approved, $notify);
1892
-    }
1893
-
1894
-
1895
-    /**
1896
-     *        decline_registration
1897
-     *
1898
-     * @access protected
1899
-     * @param bool $notify whether or not to notify the registrant about their status change.
1900
-     * @return void
1901
-     * @throws EE_Error
1902
-     * @throws EntityNotFoundException
1903
-     * @throws InvalidArgumentException
1904
-     * @throws InvalidDataTypeException
1905
-     * @throws InvalidInterfaceException
1906
-     * @throws ReflectionException
1907
-     * @throws RuntimeException
1908
-     * @throws DomainException
1909
-     */
1910
-    protected function decline_registration($notify = false)
1911
-    {
1912
-        $this->_reg_status_change_return(EEM_Registration::status_id_declined, $notify);
1913
-    }
1914
-
1915
-
1916
-    /**
1917
-     *        cancel_registration
1918
-     *
1919
-     * @access protected
1920
-     * @param bool $notify whether or not to notify the registrant about their status change.
1921
-     * @return void
1922
-     * @throws EE_Error
1923
-     * @throws EntityNotFoundException
1924
-     * @throws InvalidArgumentException
1925
-     * @throws InvalidDataTypeException
1926
-     * @throws InvalidInterfaceException
1927
-     * @throws ReflectionException
1928
-     * @throws RuntimeException
1929
-     * @throws DomainException
1930
-     */
1931
-    protected function cancel_registration($notify = false)
1932
-    {
1933
-        $this->_reg_status_change_return(EEM_Registration::status_id_cancelled, $notify);
1934
-    }
1935
-
1936
-
1937
-    /**
1938
-     *        not_approve_registration
1939
-     *
1940
-     * @access protected
1941
-     * @param bool $notify whether or not to notify the registrant about their status change.
1942
-     * @return void
1943
-     * @throws EE_Error
1944
-     * @throws EntityNotFoundException
1945
-     * @throws InvalidArgumentException
1946
-     * @throws InvalidDataTypeException
1947
-     * @throws InvalidInterfaceException
1948
-     * @throws ReflectionException
1949
-     * @throws RuntimeException
1950
-     * @throws DomainException
1951
-     */
1952
-    protected function not_approve_registration($notify = false)
1953
-    {
1954
-        $this->_reg_status_change_return(EEM_Registration::status_id_not_approved, $notify);
1955
-    }
1956
-
1957
-
1958
-    /**
1959
-     *        decline_registration
1960
-     *
1961
-     * @access protected
1962
-     * @param bool $notify whether or not to notify the registrant about their status change.
1963
-     * @return void
1964
-     * @throws EE_Error
1965
-     * @throws EntityNotFoundException
1966
-     * @throws InvalidArgumentException
1967
-     * @throws InvalidDataTypeException
1968
-     * @throws InvalidInterfaceException
1969
-     * @throws ReflectionException
1970
-     * @throws RuntimeException
1971
-     * @throws DomainException
1972
-     */
1973
-    protected function pending_registration($notify = false)
1974
-    {
1975
-        $this->_reg_status_change_return(EEM_Registration::status_id_pending_payment, $notify);
1976
-    }
1977
-
1978
-
1979
-    /**
1980
-     * waitlist_registration
1981
-     *
1982
-     * @access protected
1983
-     * @param bool $notify whether or not to notify the registrant about their status change.
1984
-     * @return void
1985
-     * @throws EE_Error
1986
-     * @throws EntityNotFoundException
1987
-     * @throws InvalidArgumentException
1988
-     * @throws InvalidDataTypeException
1989
-     * @throws InvalidInterfaceException
1990
-     * @throws ReflectionException
1991
-     * @throws RuntimeException
1992
-     * @throws DomainException
1993
-     */
1994
-    protected function wait_list_registration($notify = false)
1995
-    {
1996
-        $this->_reg_status_change_return(EEM_Registration::status_id_wait_list, $notify);
1997
-    }
1998
-
1999
-
2000
-    /**
2001
-     *        generates HTML for the Registration main meta box
2002
-     *
2003
-     * @access public
2004
-     * @return void
2005
-     * @throws DomainException
2006
-     * @throws EE_Error
2007
-     * @throws InvalidArgumentException
2008
-     * @throws InvalidDataTypeException
2009
-     * @throws InvalidInterfaceException
2010
-     * @throws ReflectionException
2011
-     * @throws EntityNotFoundException
2012
-     */
2013
-    public function _reg_details_meta_box()
2014
-    {
2015
-        EEH_Autoloader::register_line_item_display_autoloaders();
2016
-        EEH_Autoloader::register_line_item_filter_autoloaders();
2017
-        EE_Registry::instance()->load_helper('Line_Item');
2018
-        $transaction = $this->_registration->transaction() ? $this->_registration->transaction()
2019
-            : EE_Transaction::new_instance();
2020
-        $this->_session = $transaction->session_data();
2021
-        $filters = new EE_Line_Item_Filter_Collection();
2022
-        $filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
2023
-        $filters->add(new EE_Non_Zero_Line_Item_Filter());
2024
-        $line_item_filter_processor = new EE_Line_Item_Filter_Processor(
2025
-            $filters,
2026
-            $transaction->total_line_item()
2027
-        );
2028
-        $filtered_line_item_tree = $line_item_filter_processor->process();
2029
-        $line_item_display = new EE_Line_Item_Display(
2030
-            'reg_admin_table',
2031
-            'EE_Admin_Table_Registration_Line_Item_Display_Strategy'
2032
-        );
2033
-        $this->_template_args['line_item_table'] = $line_item_display->display_line_item(
2034
-            $filtered_line_item_tree,
2035
-            array('EE_Registration' => $this->_registration)
2036
-        );
2037
-        $attendee = $this->_registration->attendee();
2038
-        if (EE_Registry::instance()->CAP->current_user_can(
2039
-            'ee_read_transaction',
2040
-            'espresso_transactions_view_transaction'
2041
-        )) {
2042
-            $this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
2043
-                EE_Admin_Page::add_query_args_and_nonce(
2044
-                    array(
2045
-                        'action' => 'view_transaction',
2046
-                        'TXN_ID' => $transaction->ID(),
2047
-                    ),
2048
-                    TXN_ADMIN_URL
2049
-                ),
2050
-                esc_html__(' View Transaction', 'event_espresso'),
2051
-                'button secondary-button right',
2052
-                'dashicons dashicons-cart'
2053
-            );
2054
-        } else {
2055
-            $this->_template_args['view_transaction_button'] = '';
2056
-        }
2057
-        if ($attendee instanceof EE_Attendee
2058
-            && EE_Registry::instance()->CAP->current_user_can(
2059
-                'ee_send_message',
2060
-                'espresso_registrations_resend_registration'
2061
-            )
2062
-        ) {
2063
-            $this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
2064
-                EE_Admin_Page::add_query_args_and_nonce(
2065
-                    array(
2066
-                        'action'      => 'resend_registration',
2067
-                        '_REG_ID'     => $this->_registration->ID(),
2068
-                        'redirect_to' => 'view_registration',
2069
-                    ),
2070
-                    REG_ADMIN_URL
2071
-                ),
2072
-                esc_html__(' Resend Registration', 'event_espresso'),
2073
-                'button secondary-button right',
2074
-                'dashicons dashicons-email-alt'
2075
-            );
2076
-        } else {
2077
-            $this->_template_args['resend_registration_button'] = '';
2078
-        }
2079
-        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2080
-        $payment = $transaction->get_first_related('Payment');
2081
-        $payment = ! $payment instanceof EE_Payment
2082
-            ? EE_Payment::new_instance()
2083
-            : $payment;
2084
-        $payment_method = $payment->get_first_related('Payment_Method');
2085
-        $payment_method = ! $payment_method instanceof EE_Payment_Method
2086
-            ? EE_Payment_Method::new_instance()
2087
-            : $payment_method;
2088
-        $reg_details = array(
2089
-            'payment_method'       => $payment_method->name(),
2090
-            'response_msg'         => $payment->gateway_response(),
2091
-            'registration_id'      => $this->_registration->get('REG_code'),
2092
-            'registration_session' => $this->_registration->session_ID(),
2093
-            'ip_address'           => isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '',
2094
-            'user_agent'           => isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '',
2095
-        );
2096
-        if (isset($reg_details['registration_id'])) {
2097
-            $this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2098
-            $this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2099
-                'Registration ID',
2100
-                'event_espresso'
2101
-            );
2102
-            $this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2103
-        }
2104
-        if (isset($reg_details['payment_method'])) {
2105
-            $this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2106
-            $this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2107
-                'Most Recent Payment Method',
2108
-                'event_espresso'
2109
-            );
2110
-            $this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2111
-            $this->_template_args['reg_details']['response_msg']['value'] = $reg_details['response_msg'];
2112
-            $this->_template_args['reg_details']['response_msg']['label'] = esc_html__(
2113
-                'Payment method response',
2114
-                'event_espresso'
2115
-            );
2116
-            $this->_template_args['reg_details']['response_msg']['class'] = 'regular-text';
2117
-        }
2118
-        $this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2119
-        $this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2120
-            'Registration Session',
2121
-            'event_espresso'
2122
-        );
2123
-        $this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2124
-        $this->_template_args['reg_details']['ip_address']['value'] = $reg_details['ip_address'];
2125
-        $this->_template_args['reg_details']['ip_address']['label'] = esc_html__(
2126
-            'Registration placed from IP',
2127
-            'event_espresso'
2128
-        );
2129
-        $this->_template_args['reg_details']['ip_address']['class'] = 'regular-text';
2130
-        $this->_template_args['reg_details']['user_agent']['value'] = $reg_details['user_agent'];
2131
-        $this->_template_args['reg_details']['user_agent']['label'] = esc_html__(
2132
-            'Registrant User Agent',
2133
-            'event_espresso'
2134
-        );
2135
-        $this->_template_args['reg_details']['user_agent']['class'] = 'large-text';
2136
-        $this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
2137
-            array(
2138
-                'action'   => 'default',
2139
-                'event_id' => $this->_registration->event_ID(),
2140
-            ),
2141
-            REG_ADMIN_URL
2142
-        );
2143
-        $this->_template_args['REG_ID'] = $this->_registration->ID();
2144
-        $this->_template_args['event_id'] = $this->_registration->event_ID();
2145
-        $template_path =
2146
-            REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2147
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2148
-    }
2149
-
2150
-
2151
-    /**
2152
-     * generates HTML for the Registration Questions meta box.
2153
-     * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2154
-     * otherwise uses new forms system
2155
-     *
2156
-     * @access public
2157
-     * @return void
2158
-     * @throws DomainException
2159
-     * @throws EE_Error
2160
-     * @throws InvalidArgumentException
2161
-     * @throws InvalidDataTypeException
2162
-     * @throws InvalidInterfaceException
2163
-     * @throws ReflectionException
2164
-     */
2165
-    public function _reg_questions_meta_box()
2166
-    {
2167
-        // allow someone to override this method entirely
2168
-        if (apply_filters(
2169
-            'FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default',
2170
-            true,
2171
-            $this,
2172
-            $this->_registration
2173
-        )) {
2174
-            $form = $this->_get_reg_custom_questions_form(
2175
-                $this->_registration->ID()
2176
-            );
2177
-            $this->_template_args['att_questions'] = count($form->subforms()) > 0
2178
-                ? $form->get_html_and_js()
2179
-                : '';
2180
-            $this->_template_args['reg_questions_form_action'] = 'edit_registration';
2181
-            $this->_template_args['REG_ID'] = $this->_registration->ID();
2182
-            $template_path =
2183
-                REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2184
-            echo EEH_Template::display_template($template_path, $this->_template_args, true);
2185
-        }
2186
-    }
2187
-
2188
-
2189
-    /**
2190
-     * form_before_question_group
2191
-     *
2192
-     * @deprecated    as of 4.8.32.rc.000
2193
-     * @access        public
2194
-     * @param        string $output
2195
-     * @return        string
2196
-     */
2197
-    public function form_before_question_group($output)
2198
-    {
2199
-        EE_Error::doing_it_wrong(
2200
-            __CLASS__ . '::' . __FUNCTION__,
2201
-            esc_html__(
2202
-                '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.',
2203
-                'event_espresso'
2204
-            ),
2205
-            '4.8.32.rc.000'
2206
-        );
2207
-        return '
21
+	/**
22
+	 * @var EE_Registration
23
+	 */
24
+	private $_registration;
25
+
26
+	/**
27
+	 * @var EE_Event
28
+	 */
29
+	private $_reg_event;
30
+
31
+	/**
32
+	 * @var EE_Session
33
+	 */
34
+	private $_session;
35
+
36
+	private static $_reg_status;
37
+
38
+	/**
39
+	 * Form for displaying the custom questions for this registration.
40
+	 * This gets used a few times throughout the request so its best to cache it
41
+	 *
42
+	 * @var EE_Registration_Custom_Questions_Form
43
+	 */
44
+	protected $_reg_custom_questions_form = null;
45
+
46
+	/**
47
+	 * @var EEM_Registration $registration_model
48
+	 */
49
+	private $registration_model;
50
+
51
+	/**
52
+	 * @var EEM_Attendee $attendee_model
53
+	 */
54
+	private $attendee_model;
55
+
56
+	/**
57
+	 * @var EEM_Event $event_model
58
+	 */
59
+	private $event_model;
60
+
61
+	/**
62
+	 * @var EEM_Status $status_model
63
+	 */
64
+	private $status_model;
65
+
66
+
67
+	/**
68
+	 * @param bool $routing
69
+	 * @throws EE_Error
70
+	 * @throws InvalidArgumentException
71
+	 * @throws InvalidDataTypeException
72
+	 * @throws InvalidInterfaceException
73
+	 * @throws ReflectionException
74
+	 */
75
+	public function __construct($routing = true)
76
+	{
77
+		parent::__construct($routing);
78
+		add_action('wp_loaded', array($this, 'wp_loaded'));
79
+	}
80
+
81
+	/**
82
+	 * @return EEM_Registration
83
+	 * @throws InvalidArgumentException
84
+	 * @throws InvalidDataTypeException
85
+	 * @throws InvalidInterfaceException
86
+	 * @since 4.10.2.p
87
+	 */
88
+	protected function getRegistrationModel()
89
+	{
90
+		if (! $this->registration_model instanceof EEM_Registration) {
91
+			$this->registration_model = $this->getLoader()->getShared('EEM_Registration');
92
+		}
93
+		return $this->registration_model;
94
+	}
95
+
96
+	/**
97
+	 * @return EEM_Attendee
98
+	 * @throws InvalidArgumentException
99
+	 * @throws InvalidDataTypeException
100
+	 * @throws InvalidInterfaceException
101
+	 * @since 4.10.2.p
102
+	 */
103
+	protected function getAttendeeModel()
104
+	{
105
+		if (! $this->attendee_model instanceof EEM_Attendee) {
106
+			$this->attendee_model = $this->getLoader()->getShared('EEM_Attendee');
107
+		}
108
+		return $this->attendee_model;
109
+	}
110
+
111
+
112
+	/**
113
+	 * @return EEM_Event
114
+	 * @throws InvalidArgumentException
115
+	 * @throws InvalidDataTypeException
116
+	 * @throws InvalidInterfaceException
117
+	 * @since 4.10.2.p
118
+	 */
119
+	protected function getEventModel()
120
+	{
121
+		if (! $this->event_model instanceof EEM_Event) {
122
+			$this->event_model = $this->getLoader()->getShared('EEM_Event');
123
+		}
124
+		return $this->event_model;
125
+	}
126
+
127
+	/**
128
+	 * @return EEM_Status
129
+	 * @throws InvalidArgumentException
130
+	 * @throws InvalidDataTypeException
131
+	 * @throws InvalidInterfaceException
132
+	 * @since 4.10.2.p
133
+	 */
134
+	protected function getStatusModel()
135
+	{
136
+		if (! $this->status_model instanceof EEM_Status) {
137
+			$this->status_model = $this->getLoader()->getShared('EEM_Status');
138
+		}
139
+		return $this->status_model;
140
+	}
141
+
142
+
143
+	public function wp_loaded()
144
+	{
145
+		// when adding a new registration...
146
+		if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'new_registration') {
147
+			EE_System::do_not_cache();
148
+			if (! isset($this->_req_data['processing_registration'])
149
+				|| absint($this->_req_data['processing_registration']) !== 1
150
+			) {
151
+				// and it's NOT the attendee information reg step
152
+				// force cookie expiration by setting time to last week
153
+				setcookie('ee_registration_added', 0, time() - WEEK_IN_SECONDS, '/');
154
+				// and update the global
155
+				$_COOKIE['ee_registration_added'] = 0;
156
+			}
157
+		}
158
+	}
159
+
160
+
161
+	protected function _init_page_props()
162
+	{
163
+		$this->page_slug = REG_PG_SLUG;
164
+		$this->_admin_base_url = REG_ADMIN_URL;
165
+		$this->_admin_base_path = REG_ADMIN;
166
+		$this->page_label = esc_html__('Registrations', 'event_espresso');
167
+		$this->_cpt_routes = array(
168
+			'add_new_attendee' => 'espresso_attendees',
169
+			'edit_attendee'    => 'espresso_attendees',
170
+			'insert_attendee'  => 'espresso_attendees',
171
+			'update_attendee'  => 'espresso_attendees',
172
+		);
173
+		$this->_cpt_model_names = array(
174
+			'add_new_attendee' => 'EEM_Attendee',
175
+			'edit_attendee'    => 'EEM_Attendee',
176
+		);
177
+		$this->_cpt_edit_routes = array(
178
+			'espresso_attendees' => 'edit_attendee',
179
+		);
180
+		$this->_pagenow_map = array(
181
+			'add_new_attendee' => 'post-new.php',
182
+			'edit_attendee'    => 'post.php',
183
+			'trash'            => 'post.php',
184
+		);
185
+		add_action('edit_form_after_title', array($this, 'after_title_form_fields'), 10);
186
+		// add filters so that the comment urls don't take users to a confusing 404 page
187
+		add_filter('get_comment_link', array($this, 'clear_comment_link'), 10, 3);
188
+	}
189
+
190
+
191
+	public function clear_comment_link($link, $comment, $args)
192
+	{
193
+		// gotta make sure this only happens on this route
194
+		$post_type = get_post_type($comment->comment_post_ID);
195
+		if ($post_type === 'espresso_attendees') {
196
+			return '#commentsdiv';
197
+		}
198
+		return $link;
199
+	}
200
+
201
+
202
+	protected function _ajax_hooks()
203
+	{
204
+		// todo: all hooks for registrations ajax goes in here
205
+		add_action('wp_ajax_toggle_checkin_status', array($this, 'toggle_checkin_status'));
206
+	}
207
+
208
+
209
+	protected function _define_page_props()
210
+	{
211
+		$this->_admin_page_title = $this->page_label;
212
+		$this->_labels = array(
213
+			'buttons'                      => array(
214
+				'add-registrant'      => esc_html__('Add New Registration', 'event_espresso'),
215
+				'add-attendee'        => esc_html__('Add Contact', 'event_espresso'),
216
+				'edit'                => esc_html__('Edit Contact', 'event_espresso'),
217
+				'report'              => esc_html__('Event Registrations CSV Report', 'event_espresso'),
218
+				'report_all'          => esc_html__('All Registrations CSV Report', 'event_espresso'),
219
+				'report_filtered'     => esc_html__('Filtered CSV Report', 'event_espresso'),
220
+				'contact_list_report' => esc_html__('Contact List Report', 'event_espresso'),
221
+				'contact_list_export' => esc_html__('Export Data', 'event_espresso'),
222
+			),
223
+			'publishbox'                   => array(
224
+				'add_new_attendee' => esc_html__('Add Contact Record', 'event_espresso'),
225
+				'edit_attendee'    => esc_html__('Update Contact Record', 'event_espresso'),
226
+			),
227
+			'hide_add_button_on_cpt_route' => array(
228
+				'edit_attendee' => true,
229
+			),
230
+		);
231
+	}
232
+
233
+
234
+	/**
235
+	 *        grab url requests and route them
236
+	 *
237
+	 * @access private
238
+	 * @return void
239
+	 * @throws EE_Error
240
+	 */
241
+	public function _set_page_routes()
242
+	{
243
+		$this->_get_registration_status_array();
244
+		$reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
245
+			? $this->_req_data['_REG_ID'] : 0;
246
+		$reg_id = empty($reg_id) && ! empty($this->_req_data['reg_status_change_form']['REG_ID'])
247
+			? $this->_req_data['reg_status_change_form']['REG_ID']
248
+			: $reg_id;
249
+		$att_id = ! empty($this->_req_data['ATT_ID']) && ! is_array($this->_req_data['ATT_ID'])
250
+			? $this->_req_data['ATT_ID'] : 0;
251
+		$att_id = ! empty($this->_req_data['post']) && ! is_array($this->_req_data['post'])
252
+			? $this->_req_data['post']
253
+			: $att_id;
254
+		$this->_page_routes = array(
255
+			'default'                             => array(
256
+				'func'       => '_registrations_overview_list_table',
257
+				'capability' => 'ee_read_registrations',
258
+			),
259
+			'view_registration'                   => array(
260
+				'func'       => '_registration_details',
261
+				'capability' => 'ee_read_registration',
262
+				'obj_id'     => $reg_id,
263
+			),
264
+			'edit_registration'                   => array(
265
+				'func'               => '_update_attendee_registration_form',
266
+				'noheader'           => true,
267
+				'headers_sent_route' => 'view_registration',
268
+				'capability'         => 'ee_edit_registration',
269
+				'obj_id'             => $reg_id,
270
+				'_REG_ID'            => $reg_id,
271
+			),
272
+			'trash_registrations'                 => array(
273
+				'func'       => '_trash_or_restore_registrations',
274
+				'args'       => array('trash' => true),
275
+				'noheader'   => true,
276
+				'capability' => 'ee_delete_registrations',
277
+			),
278
+			'restore_registrations'               => array(
279
+				'func'       => '_trash_or_restore_registrations',
280
+				'args'       => array('trash' => false),
281
+				'noheader'   => true,
282
+				'capability' => 'ee_delete_registrations',
283
+			),
284
+			'delete_registrations'                => array(
285
+				'func'       => '_delete_registrations',
286
+				'noheader'   => true,
287
+				'capability' => 'ee_delete_registrations',
288
+			),
289
+			'new_registration'                    => array(
290
+				'func'       => 'new_registration',
291
+				'capability' => 'ee_edit_registrations',
292
+			),
293
+			'process_reg_step'                    => array(
294
+				'func'       => 'process_reg_step',
295
+				'noheader'   => true,
296
+				'capability' => 'ee_edit_registrations',
297
+			),
298
+			'redirect_to_txn'                     => array(
299
+				'func'       => 'redirect_to_txn',
300
+				'noheader'   => true,
301
+				'capability' => 'ee_edit_registrations',
302
+			),
303
+			'change_reg_status'                   => array(
304
+				'func'       => '_change_reg_status',
305
+				'noheader'   => true,
306
+				'capability' => 'ee_edit_registration',
307
+				'obj_id'     => $reg_id,
308
+			),
309
+			'approve_registration'                => array(
310
+				'func'       => 'approve_registration',
311
+				'noheader'   => true,
312
+				'capability' => 'ee_edit_registration',
313
+				'obj_id'     => $reg_id,
314
+			),
315
+			'approve_and_notify_registration'     => array(
316
+				'func'       => 'approve_registration',
317
+				'noheader'   => true,
318
+				'args'       => array(true),
319
+				'capability' => 'ee_edit_registration',
320
+				'obj_id'     => $reg_id,
321
+			),
322
+			'approve_registrations'               => array(
323
+				'func'       => 'bulk_action_on_registrations',
324
+				'noheader'   => true,
325
+				'capability' => 'ee_edit_registrations',
326
+				'args'       => array('approve'),
327
+			),
328
+			'approve_and_notify_registrations'    => array(
329
+				'func'       => 'bulk_action_on_registrations',
330
+				'noheader'   => true,
331
+				'capability' => 'ee_edit_registrations',
332
+				'args'       => array('approve', true),
333
+			),
334
+			'decline_registration'                => array(
335
+				'func'       => 'decline_registration',
336
+				'noheader'   => true,
337
+				'capability' => 'ee_edit_registration',
338
+				'obj_id'     => $reg_id,
339
+			),
340
+			'decline_and_notify_registration'     => array(
341
+				'func'       => 'decline_registration',
342
+				'noheader'   => true,
343
+				'args'       => array(true),
344
+				'capability' => 'ee_edit_registration',
345
+				'obj_id'     => $reg_id,
346
+			),
347
+			'decline_registrations'               => array(
348
+				'func'       => 'bulk_action_on_registrations',
349
+				'noheader'   => true,
350
+				'capability' => 'ee_edit_registrations',
351
+				'args'       => array('decline'),
352
+			),
353
+			'decline_and_notify_registrations'    => array(
354
+				'func'       => 'bulk_action_on_registrations',
355
+				'noheader'   => true,
356
+				'capability' => 'ee_edit_registrations',
357
+				'args'       => array('decline', true),
358
+			),
359
+			'pending_registration'                => array(
360
+				'func'       => 'pending_registration',
361
+				'noheader'   => true,
362
+				'capability' => 'ee_edit_registration',
363
+				'obj_id'     => $reg_id,
364
+			),
365
+			'pending_and_notify_registration'     => array(
366
+				'func'       => 'pending_registration',
367
+				'noheader'   => true,
368
+				'args'       => array(true),
369
+				'capability' => 'ee_edit_registration',
370
+				'obj_id'     => $reg_id,
371
+			),
372
+			'pending_registrations'               => array(
373
+				'func'       => 'bulk_action_on_registrations',
374
+				'noheader'   => true,
375
+				'capability' => 'ee_edit_registrations',
376
+				'args'       => array('pending'),
377
+			),
378
+			'pending_and_notify_registrations'    => array(
379
+				'func'       => 'bulk_action_on_registrations',
380
+				'noheader'   => true,
381
+				'capability' => 'ee_edit_registrations',
382
+				'args'       => array('pending', true),
383
+			),
384
+			'no_approve_registration'             => array(
385
+				'func'       => 'not_approve_registration',
386
+				'noheader'   => true,
387
+				'capability' => 'ee_edit_registration',
388
+				'obj_id'     => $reg_id,
389
+			),
390
+			'no_approve_and_notify_registration'  => array(
391
+				'func'       => 'not_approve_registration',
392
+				'noheader'   => true,
393
+				'args'       => array(true),
394
+				'capability' => 'ee_edit_registration',
395
+				'obj_id'     => $reg_id,
396
+			),
397
+			'no_approve_registrations'            => array(
398
+				'func'       => 'bulk_action_on_registrations',
399
+				'noheader'   => true,
400
+				'capability' => 'ee_edit_registrations',
401
+				'args'       => array('not_approve'),
402
+			),
403
+			'no_approve_and_notify_registrations' => array(
404
+				'func'       => 'bulk_action_on_registrations',
405
+				'noheader'   => true,
406
+				'capability' => 'ee_edit_registrations',
407
+				'args'       => array('not_approve', true),
408
+			),
409
+			'cancel_registration'                 => array(
410
+				'func'       => 'cancel_registration',
411
+				'noheader'   => true,
412
+				'capability' => 'ee_edit_registration',
413
+				'obj_id'     => $reg_id,
414
+			),
415
+			'cancel_and_notify_registration'      => array(
416
+				'func'       => 'cancel_registration',
417
+				'noheader'   => true,
418
+				'args'       => array(true),
419
+				'capability' => 'ee_edit_registration',
420
+				'obj_id'     => $reg_id,
421
+			),
422
+			'cancel_registrations'                => array(
423
+				'func'       => 'bulk_action_on_registrations',
424
+				'noheader'   => true,
425
+				'capability' => 'ee_edit_registrations',
426
+				'args'       => array('cancel'),
427
+			),
428
+			'cancel_and_notify_registrations'     => array(
429
+				'func'       => 'bulk_action_on_registrations',
430
+				'noheader'   => true,
431
+				'capability' => 'ee_edit_registrations',
432
+				'args'       => array('cancel', true),
433
+			),
434
+			'wait_list_registration'              => array(
435
+				'func'       => 'wait_list_registration',
436
+				'noheader'   => true,
437
+				'capability' => 'ee_edit_registration',
438
+				'obj_id'     => $reg_id,
439
+			),
440
+			'wait_list_and_notify_registration'   => array(
441
+				'func'       => 'wait_list_registration',
442
+				'noheader'   => true,
443
+				'args'       => array(true),
444
+				'capability' => 'ee_edit_registration',
445
+				'obj_id'     => $reg_id,
446
+			),
447
+			'contact_list'                        => array(
448
+				'func'       => '_attendee_contact_list_table',
449
+				'capability' => 'ee_read_contacts',
450
+			),
451
+			'add_new_attendee'                    => array(
452
+				'func' => '_create_new_cpt_item',
453
+				'args' => array(
454
+					'new_attendee' => true,
455
+					'capability'   => 'ee_edit_contacts',
456
+				),
457
+			),
458
+			'edit_attendee'                       => array(
459
+				'func'       => '_edit_cpt_item',
460
+				'capability' => 'ee_edit_contacts',
461
+				'obj_id'     => $att_id,
462
+			),
463
+			'duplicate_attendee'                  => array(
464
+				'func'       => '_duplicate_attendee',
465
+				'noheader'   => true,
466
+				'capability' => 'ee_edit_contacts',
467
+				'obj_id'     => $att_id,
468
+			),
469
+			'insert_attendee'                     => array(
470
+				'func'       => '_insert_or_update_attendee',
471
+				'args'       => array(
472
+					'new_attendee' => true,
473
+				),
474
+				'noheader'   => true,
475
+				'capability' => 'ee_edit_contacts',
476
+			),
477
+			'update_attendee'                     => array(
478
+				'func'       => '_insert_or_update_attendee',
479
+				'args'       => array(
480
+					'new_attendee' => false,
481
+				),
482
+				'noheader'   => true,
483
+				'capability' => 'ee_edit_contacts',
484
+				'obj_id'     => $att_id,
485
+			),
486
+			'trash_attendees'                     => array(
487
+				'func'       => '_trash_or_restore_attendees',
488
+				'args'       => array(
489
+					'trash' => 'true',
490
+				),
491
+				'noheader'   => true,
492
+				'capability' => 'ee_delete_contacts',
493
+			),
494
+			'trash_attendee'                      => array(
495
+				'func'       => '_trash_or_restore_attendees',
496
+				'args'       => array(
497
+					'trash' => true,
498
+				),
499
+				'noheader'   => true,
500
+				'capability' => 'ee_delete_contacts',
501
+				'obj_id'     => $att_id,
502
+			),
503
+			'restore_attendees'                   => array(
504
+				'func'       => '_trash_or_restore_attendees',
505
+				'args'       => array(
506
+					'trash' => false,
507
+				),
508
+				'noheader'   => true,
509
+				'capability' => 'ee_delete_contacts',
510
+				'obj_id'     => $att_id,
511
+			),
512
+			'resend_registration'                 => array(
513
+				'func'       => '_resend_registration',
514
+				'noheader'   => true,
515
+				'capability' => 'ee_send_message',
516
+			),
517
+			'registrations_report'                => array(
518
+				'func'       => '_registrations_report',
519
+				'noheader'   => true,
520
+				'capability' => 'ee_read_registrations',
521
+			),
522
+			'contact_list_export'                 => array(
523
+				'func'       => '_contact_list_export',
524
+				'noheader'   => true,
525
+				'capability' => 'export',
526
+			),
527
+			'contact_list_report'                 => array(
528
+				'func'       => '_contact_list_report',
529
+				'noheader'   => true,
530
+				'capability' => 'ee_read_contacts',
531
+			),
532
+		);
533
+	}
534
+
535
+
536
+	protected function _set_page_config()
537
+	{
538
+		$this->_page_config = array(
539
+			'default'           => array(
540
+				'nav'           => array(
541
+					'label' => esc_html__('Overview', 'event_espresso'),
542
+					'order' => 5,
543
+				),
544
+				'help_tabs'     => array(
545
+					'registrations_overview_help_tab'                       => array(
546
+						'title'    => esc_html__('Registrations Overview', 'event_espresso'),
547
+						'filename' => 'registrations_overview',
548
+					),
549
+					'registrations_overview_table_column_headings_help_tab' => array(
550
+						'title'    => esc_html__('Registrations Table Column Headings', 'event_espresso'),
551
+						'filename' => 'registrations_overview_table_column_headings',
552
+					),
553
+					'registrations_overview_filters_help_tab'               => array(
554
+						'title'    => esc_html__('Registration Filters', 'event_espresso'),
555
+						'filename' => 'registrations_overview_filters',
556
+					),
557
+					'registrations_overview_views_help_tab'                 => array(
558
+						'title'    => esc_html__('Registration Views', 'event_espresso'),
559
+						'filename' => 'registrations_overview_views',
560
+					),
561
+					'registrations_regoverview_other_help_tab'              => array(
562
+						'title'    => esc_html__('Registrations Other', 'event_espresso'),
563
+						'filename' => 'registrations_overview_other',
564
+					),
565
+				),
566
+				'help_tour'     => array('Registration_Overview_Help_Tour'),
567
+				'qtips'         => array('Registration_List_Table_Tips'),
568
+				'list_table'    => 'EE_Registrations_List_Table',
569
+				'require_nonce' => false,
570
+			),
571
+			'view_registration' => array(
572
+				'nav'           => array(
573
+					'label'      => esc_html__('REG Details', 'event_espresso'),
574
+					'order'      => 15,
575
+					'url'        => isset($this->_req_data['_REG_ID'])
576
+						? add_query_arg(array('_REG_ID' => $this->_req_data['_REG_ID']), $this->_current_page_view_url)
577
+						: $this->_admin_base_url,
578
+					'persistent' => false,
579
+				),
580
+				'help_tabs'     => array(
581
+					'registrations_details_help_tab'                    => array(
582
+						'title'    => esc_html__('Registration Details', 'event_espresso'),
583
+						'filename' => 'registrations_details',
584
+					),
585
+					'registrations_details_table_help_tab'              => array(
586
+						'title'    => esc_html__('Registration Details Table', 'event_espresso'),
587
+						'filename' => 'registrations_details_table',
588
+					),
589
+					'registrations_details_form_answers_help_tab'       => array(
590
+						'title'    => esc_html__('Registration Form Answers', 'event_espresso'),
591
+						'filename' => 'registrations_details_form_answers',
592
+					),
593
+					'registrations_details_registrant_details_help_tab' => array(
594
+						'title'    => esc_html__('Contact Details', 'event_espresso'),
595
+						'filename' => 'registrations_details_registrant_details',
596
+					),
597
+				),
598
+				'help_tour'     => array('Registration_Details_Help_Tour'),
599
+				'metaboxes'     => array_merge(
600
+					$this->_default_espresso_metaboxes,
601
+					array('_registration_details_metaboxes')
602
+				),
603
+				'require_nonce' => false,
604
+			),
605
+			'new_registration'  => array(
606
+				'nav'           => array(
607
+					'label'      => esc_html__('Add New Registration', 'event_espresso'),
608
+					'url'        => '#',
609
+					'order'      => 15,
610
+					'persistent' => false,
611
+				),
612
+				'metaboxes'     => $this->_default_espresso_metaboxes,
613
+				'labels'        => array(
614
+					'publishbox' => esc_html__('Save Registration', 'event_espresso'),
615
+				),
616
+				'require_nonce' => false,
617
+			),
618
+			'add_new_attendee'  => array(
619
+				'nav'           => array(
620
+					'label'      => esc_html__('Add Contact', 'event_espresso'),
621
+					'order'      => 15,
622
+					'persistent' => false,
623
+				),
624
+				'metaboxes'     => array_merge(
625
+					$this->_default_espresso_metaboxes,
626
+					array('_publish_post_box', 'attendee_editor_metaboxes')
627
+				),
628
+				'require_nonce' => false,
629
+			),
630
+			'edit_attendee'     => array(
631
+				'nav'           => array(
632
+					'label'      => esc_html__('Edit Contact', 'event_espresso'),
633
+					'order'      => 15,
634
+					'persistent' => false,
635
+					'url'        => isset($this->_req_data['ATT_ID'])
636
+						? add_query_arg(array('ATT_ID' => $this->_req_data['ATT_ID']), $this->_current_page_view_url)
637
+						: $this->_admin_base_url,
638
+				),
639
+				'metaboxes'     => array('attendee_editor_metaboxes'),
640
+				'require_nonce' => false,
641
+			),
642
+			'contact_list'      => array(
643
+				'nav'           => array(
644
+					'label' => esc_html__('Contact List', 'event_espresso'),
645
+					'order' => 20,
646
+				),
647
+				'list_table'    => 'EE_Attendee_Contact_List_Table',
648
+				'help_tabs'     => array(
649
+					'registrations_contact_list_help_tab'                       => array(
650
+						'title'    => esc_html__('Registrations Contact List', 'event_espresso'),
651
+						'filename' => 'registrations_contact_list',
652
+					),
653
+					'registrations_contact-list_table_column_headings_help_tab' => array(
654
+						'title'    => esc_html__('Contact List Table Column Headings', 'event_espresso'),
655
+						'filename' => 'registrations_contact_list_table_column_headings',
656
+					),
657
+					'registrations_contact_list_views_help_tab'                 => array(
658
+						'title'    => esc_html__('Contact List Views', 'event_espresso'),
659
+						'filename' => 'registrations_contact_list_views',
660
+					),
661
+					'registrations_contact_list_other_help_tab'                 => array(
662
+						'title'    => esc_html__('Contact List Other', 'event_espresso'),
663
+						'filename' => 'registrations_contact_list_other',
664
+					),
665
+				),
666
+				'help_tour'     => array('Contact_List_Help_Tour'),
667
+				'metaboxes'     => array(),
668
+				'require_nonce' => false,
669
+			),
670
+			// override default cpt routes
671
+			'create_new'        => '',
672
+			'edit'              => '',
673
+		);
674
+	}
675
+
676
+
677
+	/**
678
+	 * The below methods aren't used by this class currently
679
+	 */
680
+	protected function _add_screen_options()
681
+	{
682
+	}
683
+
684
+
685
+	protected function _add_feature_pointers()
686
+	{
687
+	}
688
+
689
+
690
+	public function admin_init()
691
+	{
692
+		EE_Registry::$i18n_js_strings['update_att_qstns'] = esc_html__(
693
+			'click "Update Registration Questions" to save your changes',
694
+			'event_espresso'
695
+		);
696
+	}
697
+
698
+
699
+	public function admin_notices()
700
+	{
701
+	}
702
+
703
+
704
+	public function admin_footer_scripts()
705
+	{
706
+	}
707
+
708
+
709
+	/**
710
+	 *        get list of registration statuses
711
+	 *
712
+	 * @access private
713
+	 * @return void
714
+	 * @throws EE_Error
715
+	 */
716
+	private function _get_registration_status_array()
717
+	{
718
+		self::$_reg_status = EEM_Registration::reg_status_array(array(), true);
719
+	}
720
+
721
+
722
+	/**
723
+	 * @throws InvalidArgumentException
724
+	 * @throws InvalidDataTypeException
725
+	 * @throws InvalidInterfaceException
726
+	 * @since 4.10.2.p
727
+	 */
728
+	protected function _add_screen_options_default()
729
+	{
730
+		$this->_per_page_screen_option();
731
+	}
732
+
733
+
734
+	/**
735
+	 * @throws InvalidArgumentException
736
+	 * @throws InvalidDataTypeException
737
+	 * @throws InvalidInterfaceException
738
+	 * @since 4.10.2.p
739
+	 */
740
+	protected function _add_screen_options_contact_list()
741
+	{
742
+		$page_title = $this->_admin_page_title;
743
+		$this->_admin_page_title = esc_html__('Contacts', 'event_espresso');
744
+		$this->_per_page_screen_option();
745
+		$this->_admin_page_title = $page_title;
746
+	}
747
+
748
+
749
+	public function load_scripts_styles()
750
+	{
751
+		// style
752
+		wp_register_style(
753
+			'espresso_reg',
754
+			REG_ASSETS_URL . 'espresso_registrations_admin.css',
755
+			array('ee-admin-css'),
756
+			EVENT_ESPRESSO_VERSION
757
+		);
758
+		wp_enqueue_style('espresso_reg');
759
+		// script
760
+		wp_register_script(
761
+			'espresso_reg',
762
+			REG_ASSETS_URL . 'espresso_registrations_admin.js',
763
+			array('jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'),
764
+			EVENT_ESPRESSO_VERSION,
765
+			true
766
+		);
767
+		wp_enqueue_script('espresso_reg');
768
+	}
769
+
770
+
771
+	/**
772
+	 * @throws EE_Error
773
+	 * @throws InvalidArgumentException
774
+	 * @throws InvalidDataTypeException
775
+	 * @throws InvalidInterfaceException
776
+	 * @throws ReflectionException
777
+	 * @since 4.10.2.p
778
+	 */
779
+	public function load_scripts_styles_edit_attendee()
780
+	{
781
+		// stuff to only show up on our attendee edit details page.
782
+		$attendee_details_translations = array(
783
+			'att_publish_text' => sprintf(
784
+				/* translators: The date and time */
785
+				wp_strip_all_tags(__('Created on: %s', 'event_espresso')),
786
+				'<b>' . $this->_cpt_model_obj->get_datetime('ATT_created') . '</b>'
787
+			),
788
+		);
789
+		wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
790
+		wp_enqueue_script('jquery-validate');
791
+	}
792
+
793
+
794
+	/**
795
+	 * @throws EE_Error
796
+	 * @throws InvalidArgumentException
797
+	 * @throws InvalidDataTypeException
798
+	 * @throws InvalidInterfaceException
799
+	 * @throws ReflectionException
800
+	 * @since 4.10.2.p
801
+	 */
802
+	public function load_scripts_styles_view_registration()
803
+	{
804
+		// styles
805
+		wp_enqueue_style('espresso-ui-theme');
806
+		// scripts
807
+		$this->_get_reg_custom_questions_form($this->_registration->ID());
808
+		$this->_reg_custom_questions_form->wp_enqueue_scripts(true);
809
+	}
810
+
811
+
812
+	public function load_scripts_styles_contact_list()
813
+	{
814
+		wp_dequeue_style('espresso_reg');
815
+		wp_register_style(
816
+			'espresso_att',
817
+			REG_ASSETS_URL . 'espresso_attendees_admin.css',
818
+			array('ee-admin-css'),
819
+			EVENT_ESPRESSO_VERSION
820
+		);
821
+		wp_enqueue_style('espresso_att');
822
+	}
823
+
824
+
825
+	public function load_scripts_styles_new_registration()
826
+	{
827
+		wp_register_script(
828
+			'ee-spco-for-admin',
829
+			REG_ASSETS_URL . 'spco_for_admin.js',
830
+			array('underscore', 'jquery'),
831
+			EVENT_ESPRESSO_VERSION,
832
+			true
833
+		);
834
+		wp_enqueue_script('ee-spco-for-admin');
835
+		add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
836
+		EE_Form_Section_Proper::wp_enqueue_scripts();
837
+		EED_Ticket_Selector::load_tckt_slctr_assets();
838
+		EE_Datepicker_Input::enqueue_styles_and_scripts();
839
+	}
840
+
841
+
842
+	public function AHEE__EE_Admin_Page__route_admin_request_resend_registration()
843
+	{
844
+		add_filter('FHEE_load_EE_messages', '__return_true');
845
+	}
846
+
847
+
848
+	public function AHEE__EE_Admin_Page__route_admin_request_approve_registration()
849
+	{
850
+		add_filter('FHEE_load_EE_messages', '__return_true');
851
+	}
852
+
853
+
854
+	/**
855
+	 * @throws EE_Error
856
+	 * @throws InvalidArgumentException
857
+	 * @throws InvalidDataTypeException
858
+	 * @throws InvalidInterfaceException
859
+	 * @throws ReflectionException
860
+	 * @since 4.10.2.p
861
+	 */
862
+	protected function _set_list_table_views_default()
863
+	{
864
+		// for notification related bulk actions we need to make sure only active messengers have an option.
865
+		EED_Messages::set_autoloaders();
866
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
867
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
868
+		$active_mts = $message_resource_manager->list_of_active_message_types();
869
+		// key= bulk_action_slug, value= message type.
870
+		$match_array = array(
871
+			'approve_registrations'    => 'registration',
872
+			'decline_registrations'    => 'declined_registration',
873
+			'pending_registrations'    => 'pending_approval',
874
+			'no_approve_registrations' => 'not_approved_registration',
875
+			'cancel_registrations'     => 'cancelled_registration',
876
+		);
877
+		$can_send = EE_Registry::instance()->CAP->current_user_can(
878
+			'ee_send_message',
879
+			'batch_send_messages'
880
+		);
881
+		/** setup reg status bulk actions **/
882
+		$def_reg_status_actions['approve_registrations'] = esc_html__('Approve Registrations', 'event_espresso');
883
+		if ($can_send && in_array($match_array['approve_registrations'], $active_mts, true)) {
884
+			$def_reg_status_actions['approve_and_notify_registrations'] = esc_html__(
885
+				'Approve and Notify Registrations',
886
+				'event_espresso'
887
+			);
888
+		}
889
+		$def_reg_status_actions['decline_registrations'] = esc_html__('Decline Registrations', 'event_espresso');
890
+		if ($can_send && in_array($match_array['decline_registrations'], $active_mts, true)) {
891
+			$def_reg_status_actions['decline_and_notify_registrations'] = esc_html__(
892
+				'Decline and Notify Registrations',
893
+				'event_espresso'
894
+			);
895
+		}
896
+		$def_reg_status_actions['pending_registrations'] = esc_html__(
897
+			'Set Registrations to Pending Payment',
898
+			'event_espresso'
899
+		);
900
+		if ($can_send && in_array($match_array['pending_registrations'], $active_mts, true)) {
901
+			$def_reg_status_actions['pending_and_notify_registrations'] = esc_html__(
902
+				'Set Registrations to Pending Payment and Notify',
903
+				'event_espresso'
904
+			);
905
+		}
906
+		$def_reg_status_actions['no_approve_registrations'] = esc_html__(
907
+			'Set Registrations to Not Approved',
908
+			'event_espresso'
909
+		);
910
+		if ($can_send && in_array($match_array['no_approve_registrations'], $active_mts, true)) {
911
+			$def_reg_status_actions['no_approve_and_notify_registrations'] = esc_html__(
912
+				'Set Registrations to Not Approved and Notify',
913
+				'event_espresso'
914
+			);
915
+		}
916
+		$def_reg_status_actions['cancel_registrations'] = esc_html__('Cancel Registrations', 'event_espresso');
917
+		if ($can_send && in_array($match_array['cancel_registrations'], $active_mts, true)) {
918
+			$def_reg_status_actions['cancel_and_notify_registrations'] = esc_html__(
919
+				'Cancel Registrations and Notify',
920
+				'event_espresso'
921
+			);
922
+		}
923
+		$def_reg_status_actions = apply_filters(
924
+			'FHEE__Registrations_Admin_Page___set_list_table_views_default__def_reg_status_actions_array',
925
+			$def_reg_status_actions,
926
+			$active_mts,
927
+			$can_send
928
+		);
929
+
930
+		$this->_views = array(
931
+			'all'   => array(
932
+				'slug'        => 'all',
933
+				'label'       => esc_html__('View All Registrations', 'event_espresso'),
934
+				'count'       => 0,
935
+				'bulk_action' => array_merge(
936
+					$def_reg_status_actions,
937
+					array(
938
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
939
+					)
940
+				),
941
+			),
942
+			'month' => array(
943
+				'slug'        => 'month',
944
+				'label'       => esc_html__('This Month', 'event_espresso'),
945
+				'count'       => 0,
946
+				'bulk_action' => array_merge(
947
+					$def_reg_status_actions,
948
+					array(
949
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
950
+					)
951
+				),
952
+			),
953
+			'today' => array(
954
+				'slug'        => 'today',
955
+				'label'       => sprintf(
956
+					esc_html__('Today - %s', 'event_espresso'),
957
+					date('M d, Y', current_time('timestamp'))
958
+				),
959
+				'count'       => 0,
960
+				'bulk_action' => array_merge(
961
+					$def_reg_status_actions,
962
+					array(
963
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
964
+					)
965
+				),
966
+			),
967
+		);
968
+		if (EE_Registry::instance()->CAP->current_user_can(
969
+			'ee_delete_registrations',
970
+			'espresso_registrations_delete_registration'
971
+		)) {
972
+			$this->_views['incomplete'] = array(
973
+				'slug'        => 'incomplete',
974
+				'label'       => esc_html__('Incomplete', 'event_espresso'),
975
+				'count'       => 0,
976
+				'bulk_action' => array(
977
+					'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
978
+				),
979
+			);
980
+			$this->_views['trash'] = array(
981
+				'slug'        => 'trash',
982
+				'label'       => esc_html__('Trash', 'event_espresso'),
983
+				'count'       => 0,
984
+				'bulk_action' => array(
985
+					'restore_registrations' => esc_html__('Restore Registrations', 'event_espresso'),
986
+					'delete_registrations'  => esc_html__('Delete Registrations Permanently', 'event_espresso'),
987
+				),
988
+			);
989
+		}
990
+	}
991
+
992
+
993
+	protected function _set_list_table_views_contact_list()
994
+	{
995
+		$this->_views = array(
996
+			'in_use' => array(
997
+				'slug'        => 'in_use',
998
+				'label'       => esc_html__('In Use', 'event_espresso'),
999
+				'count'       => 0,
1000
+				'bulk_action' => array(
1001
+					'trash_attendees' => esc_html__('Move to Trash', 'event_espresso'),
1002
+				),
1003
+			),
1004
+		);
1005
+		if (EE_Registry::instance()->CAP->current_user_can(
1006
+			'ee_delete_contacts',
1007
+			'espresso_registrations_trash_attendees'
1008
+		)
1009
+		) {
1010
+			$this->_views['trash'] = array(
1011
+				'slug'        => 'trash',
1012
+				'label'       => esc_html__('Trash', 'event_espresso'),
1013
+				'count'       => 0,
1014
+				'bulk_action' => array(
1015
+					'restore_attendees' => esc_html__('Restore from Trash', 'event_espresso'),
1016
+				),
1017
+			);
1018
+		}
1019
+	}
1020
+
1021
+
1022
+	protected function _registration_legend_items()
1023
+	{
1024
+		$fc_items = array(
1025
+			'star-icon'        => array(
1026
+				'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
1027
+				'desc'  => esc_html__('This is the Primary Registrant', 'event_espresso'),
1028
+			),
1029
+			'view_details'     => array(
1030
+				'class' => 'dashicons dashicons-clipboard',
1031
+				'desc'  => esc_html__('View Registration Details', 'event_espresso'),
1032
+			),
1033
+			'edit_attendee'    => array(
1034
+				'class' => 'ee-icon ee-icon-user-edit ee-icon-size-16',
1035
+				'desc'  => esc_html__('Edit Contact Details', 'event_espresso'),
1036
+			),
1037
+			'view_transaction' => array(
1038
+				'class' => 'dashicons dashicons-cart',
1039
+				'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
1040
+			),
1041
+			'view_invoice'     => array(
1042
+				'class' => 'dashicons dashicons-media-spreadsheet',
1043
+				'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
1044
+			),
1045
+		);
1046
+		if (EE_Registry::instance()->CAP->current_user_can(
1047
+			'ee_send_message',
1048
+			'espresso_registrations_resend_registration'
1049
+		)) {
1050
+			$fc_items['resend_registration'] = array(
1051
+				'class' => 'dashicons dashicons-email-alt',
1052
+				'desc'  => esc_html__('Resend Registration Details', 'event_espresso'),
1053
+			);
1054
+		} else {
1055
+			$fc_items['blank'] = array('class' => 'blank', 'desc' => '');
1056
+		}
1057
+		if (EE_Registry::instance()->CAP->current_user_can(
1058
+			'ee_read_global_messages',
1059
+			'view_filtered_messages'
1060
+		)) {
1061
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
1062
+			if (is_array($related_for_icon) && isset($related_for_icon['css_class'], $related_for_icon['label'])) {
1063
+				$fc_items['view_related_messages'] = array(
1064
+					'class' => $related_for_icon['css_class'],
1065
+					'desc'  => $related_for_icon['label'],
1066
+				);
1067
+			}
1068
+		}
1069
+		$sc_items = array(
1070
+			'approved_status'   => array(
1071
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
1072
+				'desc'  => EEH_Template::pretty_status(
1073
+					EEM_Registration::status_id_approved,
1074
+					false,
1075
+					'sentence'
1076
+				),
1077
+			),
1078
+			'pending_status'    => array(
1079
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
1080
+				'desc'  => EEH_Template::pretty_status(
1081
+					EEM_Registration::status_id_pending_payment,
1082
+					false,
1083
+					'sentence'
1084
+				),
1085
+			),
1086
+			'wait_list'         => array(
1087
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
1088
+				'desc'  => EEH_Template::pretty_status(
1089
+					EEM_Registration::status_id_wait_list,
1090
+					false,
1091
+					'sentence'
1092
+				),
1093
+			),
1094
+			'incomplete_status' => array(
1095
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
1096
+				'desc'  => EEH_Template::pretty_status(
1097
+					EEM_Registration::status_id_incomplete,
1098
+					false,
1099
+					'sentence'
1100
+				),
1101
+			),
1102
+			'not_approved'      => array(
1103
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
1104
+				'desc'  => EEH_Template::pretty_status(
1105
+					EEM_Registration::status_id_not_approved,
1106
+					false,
1107
+					'sentence'
1108
+				),
1109
+			),
1110
+			'declined_status'   => array(
1111
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
1112
+				'desc'  => EEH_Template::pretty_status(
1113
+					EEM_Registration::status_id_declined,
1114
+					false,
1115
+					'sentence'
1116
+				),
1117
+			),
1118
+			'cancelled_status'  => array(
1119
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1120
+				'desc'  => EEH_Template::pretty_status(
1121
+					EEM_Registration::status_id_cancelled,
1122
+					false,
1123
+					'sentence'
1124
+				),
1125
+			),
1126
+		);
1127
+		return array_merge($fc_items, $sc_items);
1128
+	}
1129
+
1130
+
1131
+
1132
+	/***************************************        REGISTRATION OVERVIEW        **************************************/
1133
+
1134
+
1135
+
1136
+	/**
1137
+	 * @throws DomainException
1138
+	 * @throws EE_Error
1139
+	 * @throws InvalidArgumentException
1140
+	 * @throws InvalidDataTypeException
1141
+	 * @throws InvalidInterfaceException
1142
+	 * @throws ReflectionException
1143
+	 */
1144
+	protected function _registrations_overview_list_table()
1145
+	{
1146
+		$this->appendAddNewRegistrationButtonToPageTitle();
1147
+		$header_text = '';
1148
+		$admin_page_header_decorators = [
1149
+			'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\AttendeeFilterHeader',
1150
+			'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\EventFilterHeader',
1151
+			'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\DateFilterHeader',
1152
+			'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\TicketFilterHeader',
1153
+		];
1154
+		foreach ($admin_page_header_decorators as $admin_page_header_decorator) {
1155
+			$filter_header_decorator = $this->getLoader()->getNew($admin_page_header_decorator);
1156
+			$header_text = $filter_header_decorator->getHeaderText($header_text);
1157
+		}
1158
+		$this->_template_args['admin_page_header'] = $header_text;
1159
+		$this->_template_args['after_list_table'] = $this->_display_legend($this->_registration_legend_items());
1160
+		$this->display_admin_list_table_page_with_no_sidebar();
1161
+	}
1162
+
1163
+
1164
+	/**
1165
+	 * @throws EE_Error
1166
+	 * @throws InvalidArgumentException
1167
+	 * @throws InvalidDataTypeException
1168
+	 * @throws InvalidInterfaceException
1169
+	 */
1170
+	private function appendAddNewRegistrationButtonToPageTitle()
1171
+	{
1172
+		$EVT_ID = ! empty($this->_req_data['event_id'])
1173
+			? absint($this->_req_data['event_id'])
1174
+			: 0;
1175
+		if ($EVT_ID
1176
+			&& EE_Registry::instance()->CAP->current_user_can(
1177
+				'ee_edit_registrations',
1178
+				'espresso_registrations_new_registration',
1179
+				$EVT_ID
1180
+			)
1181
+		) {
1182
+			$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1183
+				'new_registration',
1184
+				'add-registrant',
1185
+				array('event_id' => $EVT_ID),
1186
+				'add-new-h2'
1187
+			);
1188
+		}
1189
+	}
1190
+
1191
+
1192
+	/**
1193
+	 * This sets the _registration property for the registration details screen
1194
+	 *
1195
+	 * @access private
1196
+	 * @return bool
1197
+	 * @throws EE_Error
1198
+	 * @throws InvalidArgumentException
1199
+	 * @throws InvalidDataTypeException
1200
+	 * @throws InvalidInterfaceException
1201
+	 */
1202
+	private function _set_registration_object()
1203
+	{
1204
+		// get out if we've already set the object
1205
+		if ($this->_registration instanceof EE_Registration) {
1206
+			return true;
1207
+		}
1208
+		$REG_ID = (! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1209
+		if ($this->_registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID)) {
1210
+			return true;
1211
+		}
1212
+		$error_msg = sprintf(
1213
+			esc_html__(
1214
+				'An error occurred and the details for Registration ID #%s could not be retrieved.',
1215
+				'event_espresso'
1216
+			),
1217
+			$REG_ID
1218
+		);
1219
+		EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
1220
+		$this->_registration = null;
1221
+		return false;
1222
+	}
1223
+
1224
+
1225
+	/**
1226
+	 * Used to retrieve registrations for the list table.
1227
+	 *
1228
+	 * @param int  $per_page
1229
+	 * @param bool $count
1230
+	 * @param bool $this_month
1231
+	 * @param bool $today
1232
+	 * @return EE_Registration[]|int
1233
+	 * @throws EE_Error
1234
+	 * @throws InvalidArgumentException
1235
+	 * @throws InvalidDataTypeException
1236
+	 * @throws InvalidInterfaceException
1237
+	 */
1238
+	public function get_registrations(
1239
+		$per_page = 10,
1240
+		$count = false,
1241
+		$this_month = false,
1242
+		$today = false
1243
+	) {
1244
+		if ($this_month) {
1245
+			$this->_req_data['status'] = 'month';
1246
+		}
1247
+		if ($today) {
1248
+			$this->_req_data['status'] = 'today';
1249
+		}
1250
+		$query_params = $this->_get_registration_query_parameters($this->_req_data, $per_page, $count);
1251
+		/**
1252
+		 * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1253
+		 *
1254
+		 * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1255
+		 * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1256
+		 *                             or if you have the development copy of EE you can view this at the path:
1257
+		 *                             /docs/G--Model-System/model-query-params.md
1258
+		 */
1259
+		$query_params['group_by'] = '';
1260
+
1261
+		return $count
1262
+			? $this->getRegistrationModel()->count($query_params)
1263
+			/** @type EE_Registration[] */
1264
+			: $this->getRegistrationModel()->get_all($query_params);
1265
+	}
1266
+
1267
+
1268
+	/**
1269
+	 * Retrieves the query parameters to be used by the Registration model for getting registrations.
1270
+	 * Note: this listens to values on the request for some of the query parameters.
1271
+	 *
1272
+	 * @param array $request
1273
+	 * @param int   $per_page
1274
+	 * @param bool  $count
1275
+	 * @return array
1276
+	 * @throws EE_Error
1277
+	 * @throws InvalidArgumentException
1278
+	 * @throws InvalidDataTypeException
1279
+	 * @throws InvalidInterfaceException
1280
+	 */
1281
+	protected function _get_registration_query_parameters(
1282
+		$request = array(),
1283
+		$per_page = 10,
1284
+		$count = false
1285
+	) {
1286
+		/** @var EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder $list_table_query_builder */
1287
+		$list_table_query_builder = $this->getLoader()->getNew(
1288
+			'EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder',
1289
+			[ $request ]
1290
+		);
1291
+		return $list_table_query_builder->getQueryParams($per_page, $count);
1292
+	}
1293
+
1294
+
1295
+	public function get_registration_status_array()
1296
+	{
1297
+		return self::$_reg_status;
1298
+	}
1299
+
1300
+
1301
+
1302
+
1303
+	/***************************************        REGISTRATION DETAILS        ***************************************/
1304
+	/**
1305
+	 *        generates HTML for the View Registration Details Admin page
1306
+	 *
1307
+	 * @access protected
1308
+	 * @return void
1309
+	 * @throws DomainException
1310
+	 * @throws EE_Error
1311
+	 * @throws InvalidArgumentException
1312
+	 * @throws InvalidDataTypeException
1313
+	 * @throws InvalidInterfaceException
1314
+	 * @throws EntityNotFoundException
1315
+	 * @throws ReflectionException
1316
+	 */
1317
+	protected function _registration_details()
1318
+	{
1319
+		$this->_template_args = array();
1320
+		$this->_set_registration_object();
1321
+		if (is_object($this->_registration)) {
1322
+			$transaction = $this->_registration->transaction()
1323
+				? $this->_registration->transaction()
1324
+				: EE_Transaction::new_instance();
1325
+			$this->_session = $transaction->session_data();
1326
+			$event_id = $this->_registration->event_ID();
1327
+			$this->_template_args['reg_nmbr']['value'] = $this->_registration->ID();
1328
+			$this->_template_args['reg_nmbr']['label'] = esc_html__('Registration Number', 'event_espresso');
1329
+			$this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1330
+			$this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1331
+			$this->_template_args['grand_total'] = $transaction->total();
1332
+			$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
1333
+			// link back to overview
1334
+			$this->_template_args['reg_overview_url'] = REG_ADMIN_URL;
1335
+			$this->_template_args['registration'] = $this->_registration;
1336
+			$this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1337
+				array(
1338
+					'action'   => 'default',
1339
+					'event_id' => $event_id,
1340
+				),
1341
+				REG_ADMIN_URL
1342
+			);
1343
+			$this->_template_args['filtered_transactions_link'] = EE_Admin_Page::add_query_args_and_nonce(
1344
+				array(
1345
+					'action' => 'default',
1346
+					'EVT_ID' => $event_id,
1347
+					'page'   => 'espresso_transactions',
1348
+				),
1349
+				admin_url('admin.php')
1350
+			);
1351
+			$this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
1352
+				array(
1353
+					'page'   => 'espresso_events',
1354
+					'action' => 'edit',
1355
+					'post'   => $event_id,
1356
+				),
1357
+				admin_url('admin.php')
1358
+			);
1359
+			// next and previous links
1360
+			$next_reg = $this->_registration->next(
1361
+				null,
1362
+				array(),
1363
+				'REG_ID'
1364
+			);
1365
+			$this->_template_args['next_registration'] = $next_reg
1366
+				? $this->_next_link(
1367
+					EE_Admin_Page::add_query_args_and_nonce(
1368
+						array(
1369
+							'action'  => 'view_registration',
1370
+							'_REG_ID' => $next_reg['REG_ID'],
1371
+						),
1372
+						REG_ADMIN_URL
1373
+					),
1374
+					'dashicons dashicons-arrow-right ee-icon-size-22'
1375
+				)
1376
+				: '';
1377
+			$previous_reg = $this->_registration->previous(
1378
+				null,
1379
+				array(),
1380
+				'REG_ID'
1381
+			);
1382
+			$this->_template_args['previous_registration'] = $previous_reg
1383
+				? $this->_previous_link(
1384
+					EE_Admin_Page::add_query_args_and_nonce(
1385
+						array(
1386
+							'action'  => 'view_registration',
1387
+							'_REG_ID' => $previous_reg['REG_ID'],
1388
+						),
1389
+						REG_ADMIN_URL
1390
+					),
1391
+					'dashicons dashicons-arrow-left ee-icon-size-22'
1392
+				)
1393
+				: '';
1394
+			// grab header
1395
+			$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1396
+			$this->_template_args['REG_ID'] = $this->_registration->ID();
1397
+			$this->_template_args['admin_page_header'] = EEH_Template::display_template(
1398
+				$template_path,
1399
+				$this->_template_args,
1400
+				true
1401
+			);
1402
+		} else {
1403
+			$this->_template_args['admin_page_header'] = $this->display_espresso_notices();
1404
+		}
1405
+		// the details template wrapper
1406
+		$this->display_admin_page_with_sidebar();
1407
+	}
1408
+
1409
+
1410
+	/**
1411
+	 * @throws EE_Error
1412
+	 * @throws InvalidArgumentException
1413
+	 * @throws InvalidDataTypeException
1414
+	 * @throws InvalidInterfaceException
1415
+	 * @throws ReflectionException
1416
+	 * @since 4.10.2.p
1417
+	 */
1418
+	protected function _registration_details_metaboxes()
1419
+	{
1420
+		do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1421
+		$this->_set_registration_object();
1422
+		$attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1423
+		add_meta_box(
1424
+			'edit-reg-status-mbox',
1425
+			esc_html__('Registration Status', 'event_espresso'),
1426
+			array($this, 'set_reg_status_buttons_metabox'),
1427
+			$this->wp_page_slug,
1428
+			'normal',
1429
+			'high'
1430
+		);
1431
+		add_meta_box(
1432
+			'edit-reg-details-mbox',
1433
+			esc_html__('Registration Details', 'event_espresso'),
1434
+			array($this, '_reg_details_meta_box'),
1435
+			$this->wp_page_slug,
1436
+			'normal',
1437
+			'high'
1438
+		);
1439
+		if ($attendee instanceof EE_Attendee
1440
+			&& EE_Registry::instance()->CAP->current_user_can(
1441
+				'ee_read_registration',
1442
+				'edit-reg-questions-mbox',
1443
+				$this->_registration->ID()
1444
+			)
1445
+		) {
1446
+			add_meta_box(
1447
+				'edit-reg-questions-mbox',
1448
+				esc_html__('Registration Form Answers', 'event_espresso'),
1449
+				array($this, '_reg_questions_meta_box'),
1450
+				$this->wp_page_slug,
1451
+				'normal',
1452
+				'high'
1453
+			);
1454
+		}
1455
+		add_meta_box(
1456
+			'edit-reg-registrant-mbox',
1457
+			esc_html__('Contact Details', 'event_espresso'),
1458
+			array($this, '_reg_registrant_side_meta_box'),
1459
+			$this->wp_page_slug,
1460
+			'side',
1461
+			'high'
1462
+		);
1463
+		if ($this->_registration->group_size() > 1) {
1464
+			add_meta_box(
1465
+				'edit-reg-attendees-mbox',
1466
+				esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1467
+				array($this, '_reg_attendees_meta_box'),
1468
+				$this->wp_page_slug,
1469
+				'normal',
1470
+				'high'
1471
+			);
1472
+		}
1473
+	}
1474
+
1475
+
1476
+	/**
1477
+	 * set_reg_status_buttons_metabox
1478
+	 *
1479
+	 * @access protected
1480
+	 * @return string
1481
+	 * @throws EE_Error
1482
+	 * @throws EntityNotFoundException
1483
+	 * @throws InvalidArgumentException
1484
+	 * @throws InvalidDataTypeException
1485
+	 * @throws InvalidInterfaceException
1486
+	 * @throws ReflectionException
1487
+	 */
1488
+	public function set_reg_status_buttons_metabox()
1489
+	{
1490
+		$this->_set_registration_object();
1491
+		$change_reg_status_form = $this->_generate_reg_status_change_form();
1492
+		echo $change_reg_status_form->form_open(
1493
+			self::add_query_args_and_nonce(
1494
+				array(
1495
+					'action' => 'change_reg_status',
1496
+				),
1497
+				REG_ADMIN_URL
1498
+			)
1499
+		);
1500
+		echo $change_reg_status_form->get_html();
1501
+		echo $change_reg_status_form->form_close();
1502
+	}
1503
+
1504
+
1505
+	/**
1506
+	 * @return EE_Form_Section_Proper
1507
+	 * @throws EE_Error
1508
+	 * @throws InvalidArgumentException
1509
+	 * @throws InvalidDataTypeException
1510
+	 * @throws InvalidInterfaceException
1511
+	 * @throws EntityNotFoundException
1512
+	 * @throws ReflectionException
1513
+	 */
1514
+	protected function _generate_reg_status_change_form()
1515
+	{
1516
+		$reg_status_change_form_array = array(
1517
+			'name'            => 'reg_status_change_form',
1518
+			'html_id'         => 'reg-status-change-form',
1519
+			'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1520
+			'subsections'     => array(
1521
+				'return'             => new EE_Hidden_Input(
1522
+					array(
1523
+						'name'    => 'return',
1524
+						'default' => 'view_registration',
1525
+					)
1526
+				),
1527
+				'REG_ID'             => new EE_Hidden_Input(
1528
+					array(
1529
+						'name'    => 'REG_ID',
1530
+						'default' => $this->_registration->ID(),
1531
+					)
1532
+				),
1533
+				'current_status'     => new EE_Form_Section_HTML(
1534
+					EEH_HTML::table(
1535
+						EEH_HTML::tr(
1536
+							EEH_HTML::th(
1537
+								EEH_HTML::label(
1538
+									EEH_HTML::strong(
1539
+										esc_html__('Current Registration Status', 'event_espresso')
1540
+									)
1541
+								)
1542
+							)
1543
+							. EEH_HTML::td(
1544
+								EEH_HTML::strong(
1545
+									$this->_registration->pretty_status(),
1546
+									'',
1547
+									'status-' . $this->_registration->status_ID(),
1548
+									'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1549
+								)
1550
+							)
1551
+						)
1552
+					)
1553
+				)
1554
+			)
1555
+		);
1556
+		if (EE_Registry::instance()->CAP->current_user_can(
1557
+			'ee_edit_registration',
1558
+			'toggle_registration_status',
1559
+			$this->_registration->ID()
1560
+		)) {
1561
+			$reg_status_change_form_array['subsections']['reg_status'] = new EE_Select_Input(
1562
+				$this->_get_reg_statuses(),
1563
+				array(
1564
+					'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1565
+					'default'         => $this->_registration->status_ID(),
1566
+				)
1567
+			);
1568
+			$reg_status_change_form_array['subsections']['send_notifications'] = new EE_Yes_No_Input(
1569
+				array(
1570
+					'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1571
+					'default'         => false,
1572
+					'html_help_text'  => esc_html__(
1573
+						'If set to "Yes", then the related messages will be sent to the registrant.',
1574
+						'event_espresso'
1575
+					)
1576
+				)
1577
+			);
1578
+			$reg_status_change_form_array['subsections']['submit'] = new EE_Submit_Input(
1579
+				array(
1580
+					'html_class'      => 'button-primary',
1581
+					'html_label_text' => '&nbsp;',
1582
+					'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1583
+				)
1584
+			);
1585
+		}
1586
+		return new EE_Form_Section_Proper($reg_status_change_form_array);
1587
+	}
1588
+
1589
+
1590
+	/**
1591
+	 * Returns an array of all the buttons for the various statuses and switch status actions
1592
+	 *
1593
+	 * @return array
1594
+	 * @throws EE_Error
1595
+	 * @throws InvalidArgumentException
1596
+	 * @throws InvalidDataTypeException
1597
+	 * @throws InvalidInterfaceException
1598
+	 * @throws EntityNotFoundException
1599
+	 */
1600
+	protected function _get_reg_statuses()
1601
+	{
1602
+		$reg_status_array = $this->getRegistrationModel()->reg_status_array();
1603
+		unset($reg_status_array[ EEM_Registration::status_id_incomplete ]);
1604
+		// get current reg status
1605
+		$current_status = $this->_registration->status_ID();
1606
+		// is registration for free event? This will determine whether to display the pending payment option
1607
+		if ($current_status !== EEM_Registration::status_id_pending_payment
1608
+			&& EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1609
+		) {
1610
+			unset($reg_status_array[ EEM_Registration::status_id_pending_payment ]);
1611
+		}
1612
+		return $this->getStatusModel()->localized_status($reg_status_array, false, 'sentence');
1613
+	}
1614
+
1615
+
1616
+	/**
1617
+	 * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1618
+	 *
1619
+	 * @param bool $status REG status given for changing registrations to.
1620
+	 * @param bool $notify Whether to send messages notifications or not.
1621
+	 * @return array (array with reg_id(s) updated and whether update was successful.
1622
+	 * @throws DomainException
1623
+	 * @throws EE_Error
1624
+	 * @throws EntityNotFoundException
1625
+	 * @throws InvalidArgumentException
1626
+	 * @throws InvalidDataTypeException
1627
+	 * @throws InvalidInterfaceException
1628
+	 * @throws ReflectionException
1629
+	 * @throws RuntimeException
1630
+	 */
1631
+	protected function _set_registration_status_from_request($status = false, $notify = false)
1632
+	{
1633
+		if (isset($this->_req_data['reg_status_change_form'])) {
1634
+			$REG_IDs = isset($this->_req_data['reg_status_change_form']['REG_ID'])
1635
+				? (array) $this->_req_data['reg_status_change_form']['REG_ID']
1636
+				: array();
1637
+		} else {
1638
+			$REG_IDs = isset($this->_req_data['_REG_ID'])
1639
+				? (array) $this->_req_data['_REG_ID']
1640
+				: array();
1641
+		}
1642
+		// sanitize $REG_IDs
1643
+		$REG_IDs = array_map('absint', $REG_IDs);
1644
+		// and remove empty entries
1645
+		$REG_IDs = array_filter($REG_IDs);
1646
+
1647
+		$result = $this->_set_registration_status($REG_IDs, $status, $notify);
1648
+
1649
+		/**
1650
+		 * Set and filter $_req_data['_REG_ID'] for any potential future messages notifications.
1651
+		 * Currently this value is used downstream by the _process_resend_registration method.
1652
+		 *
1653
+		 * @param int|array                $registration_ids The registration ids that have had their status changed successfully.
1654
+		 * @param bool                     $status           The status registrations were changed to.
1655
+		 * @param bool                     $success          If the status was changed successfully for all registrations.
1656
+		 * @param Registrations_Admin_Page $admin_page_object
1657
+		 */
1658
+		$this->_req_data['_REG_ID'] = apply_filters(
1659
+			'FHEE__Registrations_Admin_Page___set_registration_status_from_request__REG_IDs',
1660
+			$result['REG_ID'],
1661
+			$status,
1662
+			$result['success'],
1663
+			$this
1664
+		);
1665
+
1666
+		// notify?
1667
+		if ($notify
1668
+			&& $result['success']
1669
+			&& ! empty($this->_req_data['_REG_ID'])
1670
+			&& EE_Registry::instance()->CAP->current_user_can(
1671
+				'ee_send_message',
1672
+				'espresso_registrations_resend_registration'
1673
+			)
1674
+		) {
1675
+			$this->_process_resend_registration();
1676
+		}
1677
+		return $result;
1678
+	}
1679
+
1680
+
1681
+	/**
1682
+	 * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1683
+	 * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1684
+	 *
1685
+	 * @param array  $REG_IDs
1686
+	 * @param string $status
1687
+	 * @param bool   $notify  Used to indicate whether notification was requested or not.  This determines the context
1688
+	 *                        slug sent with setting the registration status.
1689
+	 * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1690
+	 * @throws EE_Error
1691
+	 * @throws InvalidArgumentException
1692
+	 * @throws InvalidDataTypeException
1693
+	 * @throws InvalidInterfaceException
1694
+	 * @throws ReflectionException
1695
+	 * @throws RuntimeException
1696
+	 * @throws EntityNotFoundException
1697
+	 * @throws DomainException
1698
+	 */
1699
+	protected function _set_registration_status($REG_IDs = array(), $status = '', $notify = false)
1700
+	{
1701
+		$success = false;
1702
+		// typecast $REG_IDs
1703
+		$REG_IDs = (array) $REG_IDs;
1704
+		if (! empty($REG_IDs)) {
1705
+			$success = true;
1706
+			// set default status if none is passed
1707
+			$status = $status ? $status : EEM_Registration::status_id_pending_payment;
1708
+			$status_context = $notify
1709
+				? Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
1710
+				: Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN;
1711
+			// loop through REG_ID's and change status
1712
+			foreach ($REG_IDs as $REG_ID) {
1713
+				$registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
1714
+				if ($registration instanceof EE_Registration) {
1715
+					$registration->set_status(
1716
+						$status,
1717
+						false,
1718
+						new Context(
1719
+							$status_context,
1720
+							esc_html__(
1721
+								'Manually triggered status change on a Registration Admin Page route.',
1722
+								'event_espresso'
1723
+							)
1724
+						)
1725
+					);
1726
+					$result = $registration->save();
1727
+					// verifying explicit fails because update *may* just return 0 for 0 rows affected
1728
+					$success = $result !== false ? $success : false;
1729
+				}
1730
+			}
1731
+		}
1732
+
1733
+		// return $success and processed registrations
1734
+		return array('REG_ID' => $REG_IDs, 'success' => $success);
1735
+	}
1736
+
1737
+
1738
+	/**
1739
+	 * Common logic for setting up success message and redirecting to appropriate route
1740
+	 *
1741
+	 * @param string $STS_ID status id for the registration changed to
1742
+	 * @param bool   $notify indicates whether the _set_registration_status_from_request does notifications or not.
1743
+	 * @return void
1744
+	 * @throws DomainException
1745
+	 * @throws EE_Error
1746
+	 * @throws EntityNotFoundException
1747
+	 * @throws InvalidArgumentException
1748
+	 * @throws InvalidDataTypeException
1749
+	 * @throws InvalidInterfaceException
1750
+	 * @throws ReflectionException
1751
+	 * @throws RuntimeException
1752
+	 */
1753
+	protected function _reg_status_change_return($STS_ID, $notify = false)
1754
+	{
1755
+		$result = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1756
+			: array('success' => false);
1757
+		$success = isset($result['success']) && $result['success'];
1758
+		// setup success message
1759
+		if ($success) {
1760
+			if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1761
+				$msg = sprintf(
1762
+					esc_html__('Registration status has been set to %s', 'event_espresso'),
1763
+					EEH_Template::pretty_status($STS_ID, false, 'lower')
1764
+				);
1765
+			} else {
1766
+				$msg = sprintf(
1767
+					esc_html__('Registrations have been set to %s.', 'event_espresso'),
1768
+					EEH_Template::pretty_status($STS_ID, false, 'lower')
1769
+				);
1770
+			}
1771
+			EE_Error::add_success($msg);
1772
+		} else {
1773
+			EE_Error::add_error(
1774
+				esc_html__(
1775
+					'Something went wrong, and the status was not changed',
1776
+					'event_espresso'
1777
+				),
1778
+				__FILE__,
1779
+				__LINE__,
1780
+				__FUNCTION__
1781
+			);
1782
+		}
1783
+		if (isset($this->_req_data['return']) && $this->_req_data['return'] === 'view_registration') {
1784
+			$route = array('action' => 'view_registration', '_REG_ID' => reset($result['REG_ID']));
1785
+		} else {
1786
+			$route = array('action' => 'default');
1787
+		}
1788
+		$route = $this->mergeExistingRequestParamsWithRedirectArgs($route);
1789
+		$this->_redirect_after_action($success, '', '', $route, true);
1790
+	}
1791
+
1792
+
1793
+	/**
1794
+	 * incoming reg status change from reg details page.
1795
+	 *
1796
+	 * @return void
1797
+	 * @throws EE_Error
1798
+	 * @throws EntityNotFoundException
1799
+	 * @throws InvalidArgumentException
1800
+	 * @throws InvalidDataTypeException
1801
+	 * @throws InvalidInterfaceException
1802
+	 * @throws ReflectionException
1803
+	 * @throws RuntimeException
1804
+	 * @throws DomainException
1805
+	 */
1806
+	protected function _change_reg_status()
1807
+	{
1808
+		$this->_req_data['return'] = 'view_registration';
1809
+		// set notify based on whether the send notifications toggle is set or not
1810
+		$notify = ! empty($this->_req_data['reg_status_change_form']['send_notifications']);
1811
+		// $notify = ! empty( $this->_req_data['txn_reg_status_change']['send_notifications'] );
1812
+		$this->_req_data['reg_status_change_form']['reg_status'] = isset($this->_req_data['reg_status_change_form']['reg_status'])
1813
+			? $this->_req_data['reg_status_change_form']['reg_status'] : '';
1814
+		switch ($this->_req_data['reg_status_change_form']['reg_status']) {
1815
+			case EEM_Registration::status_id_approved:
1816
+			case EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'):
1817
+				$this->approve_registration($notify);
1818
+				break;
1819
+			case EEM_Registration::status_id_pending_payment:
1820
+			case EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'):
1821
+				$this->pending_registration($notify);
1822
+				break;
1823
+			case EEM_Registration::status_id_not_approved:
1824
+			case EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'):
1825
+				$this->not_approve_registration($notify);
1826
+				break;
1827
+			case EEM_Registration::status_id_declined:
1828
+			case EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'):
1829
+				$this->decline_registration($notify);
1830
+				break;
1831
+			case EEM_Registration::status_id_cancelled:
1832
+			case EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'):
1833
+				$this->cancel_registration($notify);
1834
+				break;
1835
+			case EEM_Registration::status_id_wait_list:
1836
+			case EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'):
1837
+				$this->wait_list_registration($notify);
1838
+				break;
1839
+			case EEM_Registration::status_id_incomplete:
1840
+			default:
1841
+				$result['success'] = false;
1842
+				unset($this->_req_data['return']);
1843
+				$this->_reg_status_change_return('', false);
1844
+				break;
1845
+		}
1846
+	}
1847
+
1848
+
1849
+	/**
1850
+	 * Callback for bulk action routes.
1851
+	 * Note: although we could just register the singular route callbacks for each bulk action route as well, this
1852
+	 * method was chosen so there is one central place all the registration status bulk actions are going through.
1853
+	 * Potentially, this provides an easier place to locate logic that is specific to these bulk actions (as opposed to
1854
+	 * when an action is happening on just a single registration).
1855
+	 *
1856
+	 * @param      $action
1857
+	 * @param bool $notify
1858
+	 */
1859
+	protected function bulk_action_on_registrations($action, $notify = false)
1860
+	{
1861
+		do_action(
1862
+			'AHEE__Registrations_Admin_Page__bulk_action_on_registrations__before_execution',
1863
+			$this,
1864
+			$action,
1865
+			$notify
1866
+		);
1867
+		$method = $action . '_registration';
1868
+		if (method_exists($this, $method)) {
1869
+			$this->$method($notify);
1870
+		}
1871
+	}
1872
+
1873
+
1874
+	/**
1875
+	 * approve_registration
1876
+	 *
1877
+	 * @access protected
1878
+	 * @param bool $notify whether or not to notify the registrant about their approval.
1879
+	 * @return void
1880
+	 * @throws EE_Error
1881
+	 * @throws EntityNotFoundException
1882
+	 * @throws InvalidArgumentException
1883
+	 * @throws InvalidDataTypeException
1884
+	 * @throws InvalidInterfaceException
1885
+	 * @throws ReflectionException
1886
+	 * @throws RuntimeException
1887
+	 * @throws DomainException
1888
+	 */
1889
+	protected function approve_registration($notify = false)
1890
+	{
1891
+		$this->_reg_status_change_return(EEM_Registration::status_id_approved, $notify);
1892
+	}
1893
+
1894
+
1895
+	/**
1896
+	 *        decline_registration
1897
+	 *
1898
+	 * @access protected
1899
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1900
+	 * @return void
1901
+	 * @throws EE_Error
1902
+	 * @throws EntityNotFoundException
1903
+	 * @throws InvalidArgumentException
1904
+	 * @throws InvalidDataTypeException
1905
+	 * @throws InvalidInterfaceException
1906
+	 * @throws ReflectionException
1907
+	 * @throws RuntimeException
1908
+	 * @throws DomainException
1909
+	 */
1910
+	protected function decline_registration($notify = false)
1911
+	{
1912
+		$this->_reg_status_change_return(EEM_Registration::status_id_declined, $notify);
1913
+	}
1914
+
1915
+
1916
+	/**
1917
+	 *        cancel_registration
1918
+	 *
1919
+	 * @access protected
1920
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1921
+	 * @return void
1922
+	 * @throws EE_Error
1923
+	 * @throws EntityNotFoundException
1924
+	 * @throws InvalidArgumentException
1925
+	 * @throws InvalidDataTypeException
1926
+	 * @throws InvalidInterfaceException
1927
+	 * @throws ReflectionException
1928
+	 * @throws RuntimeException
1929
+	 * @throws DomainException
1930
+	 */
1931
+	protected function cancel_registration($notify = false)
1932
+	{
1933
+		$this->_reg_status_change_return(EEM_Registration::status_id_cancelled, $notify);
1934
+	}
1935
+
1936
+
1937
+	/**
1938
+	 *        not_approve_registration
1939
+	 *
1940
+	 * @access protected
1941
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1942
+	 * @return void
1943
+	 * @throws EE_Error
1944
+	 * @throws EntityNotFoundException
1945
+	 * @throws InvalidArgumentException
1946
+	 * @throws InvalidDataTypeException
1947
+	 * @throws InvalidInterfaceException
1948
+	 * @throws ReflectionException
1949
+	 * @throws RuntimeException
1950
+	 * @throws DomainException
1951
+	 */
1952
+	protected function not_approve_registration($notify = false)
1953
+	{
1954
+		$this->_reg_status_change_return(EEM_Registration::status_id_not_approved, $notify);
1955
+	}
1956
+
1957
+
1958
+	/**
1959
+	 *        decline_registration
1960
+	 *
1961
+	 * @access protected
1962
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1963
+	 * @return void
1964
+	 * @throws EE_Error
1965
+	 * @throws EntityNotFoundException
1966
+	 * @throws InvalidArgumentException
1967
+	 * @throws InvalidDataTypeException
1968
+	 * @throws InvalidInterfaceException
1969
+	 * @throws ReflectionException
1970
+	 * @throws RuntimeException
1971
+	 * @throws DomainException
1972
+	 */
1973
+	protected function pending_registration($notify = false)
1974
+	{
1975
+		$this->_reg_status_change_return(EEM_Registration::status_id_pending_payment, $notify);
1976
+	}
1977
+
1978
+
1979
+	/**
1980
+	 * waitlist_registration
1981
+	 *
1982
+	 * @access protected
1983
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1984
+	 * @return void
1985
+	 * @throws EE_Error
1986
+	 * @throws EntityNotFoundException
1987
+	 * @throws InvalidArgumentException
1988
+	 * @throws InvalidDataTypeException
1989
+	 * @throws InvalidInterfaceException
1990
+	 * @throws ReflectionException
1991
+	 * @throws RuntimeException
1992
+	 * @throws DomainException
1993
+	 */
1994
+	protected function wait_list_registration($notify = false)
1995
+	{
1996
+		$this->_reg_status_change_return(EEM_Registration::status_id_wait_list, $notify);
1997
+	}
1998
+
1999
+
2000
+	/**
2001
+	 *        generates HTML for the Registration main meta box
2002
+	 *
2003
+	 * @access public
2004
+	 * @return void
2005
+	 * @throws DomainException
2006
+	 * @throws EE_Error
2007
+	 * @throws InvalidArgumentException
2008
+	 * @throws InvalidDataTypeException
2009
+	 * @throws InvalidInterfaceException
2010
+	 * @throws ReflectionException
2011
+	 * @throws EntityNotFoundException
2012
+	 */
2013
+	public function _reg_details_meta_box()
2014
+	{
2015
+		EEH_Autoloader::register_line_item_display_autoloaders();
2016
+		EEH_Autoloader::register_line_item_filter_autoloaders();
2017
+		EE_Registry::instance()->load_helper('Line_Item');
2018
+		$transaction = $this->_registration->transaction() ? $this->_registration->transaction()
2019
+			: EE_Transaction::new_instance();
2020
+		$this->_session = $transaction->session_data();
2021
+		$filters = new EE_Line_Item_Filter_Collection();
2022
+		$filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
2023
+		$filters->add(new EE_Non_Zero_Line_Item_Filter());
2024
+		$line_item_filter_processor = new EE_Line_Item_Filter_Processor(
2025
+			$filters,
2026
+			$transaction->total_line_item()
2027
+		);
2028
+		$filtered_line_item_tree = $line_item_filter_processor->process();
2029
+		$line_item_display = new EE_Line_Item_Display(
2030
+			'reg_admin_table',
2031
+			'EE_Admin_Table_Registration_Line_Item_Display_Strategy'
2032
+		);
2033
+		$this->_template_args['line_item_table'] = $line_item_display->display_line_item(
2034
+			$filtered_line_item_tree,
2035
+			array('EE_Registration' => $this->_registration)
2036
+		);
2037
+		$attendee = $this->_registration->attendee();
2038
+		if (EE_Registry::instance()->CAP->current_user_can(
2039
+			'ee_read_transaction',
2040
+			'espresso_transactions_view_transaction'
2041
+		)) {
2042
+			$this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
2043
+				EE_Admin_Page::add_query_args_and_nonce(
2044
+					array(
2045
+						'action' => 'view_transaction',
2046
+						'TXN_ID' => $transaction->ID(),
2047
+					),
2048
+					TXN_ADMIN_URL
2049
+				),
2050
+				esc_html__(' View Transaction', 'event_espresso'),
2051
+				'button secondary-button right',
2052
+				'dashicons dashicons-cart'
2053
+			);
2054
+		} else {
2055
+			$this->_template_args['view_transaction_button'] = '';
2056
+		}
2057
+		if ($attendee instanceof EE_Attendee
2058
+			&& EE_Registry::instance()->CAP->current_user_can(
2059
+				'ee_send_message',
2060
+				'espresso_registrations_resend_registration'
2061
+			)
2062
+		) {
2063
+			$this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
2064
+				EE_Admin_Page::add_query_args_and_nonce(
2065
+					array(
2066
+						'action'      => 'resend_registration',
2067
+						'_REG_ID'     => $this->_registration->ID(),
2068
+						'redirect_to' => 'view_registration',
2069
+					),
2070
+					REG_ADMIN_URL
2071
+				),
2072
+				esc_html__(' Resend Registration', 'event_espresso'),
2073
+				'button secondary-button right',
2074
+				'dashicons dashicons-email-alt'
2075
+			);
2076
+		} else {
2077
+			$this->_template_args['resend_registration_button'] = '';
2078
+		}
2079
+		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2080
+		$payment = $transaction->get_first_related('Payment');
2081
+		$payment = ! $payment instanceof EE_Payment
2082
+			? EE_Payment::new_instance()
2083
+			: $payment;
2084
+		$payment_method = $payment->get_first_related('Payment_Method');
2085
+		$payment_method = ! $payment_method instanceof EE_Payment_Method
2086
+			? EE_Payment_Method::new_instance()
2087
+			: $payment_method;
2088
+		$reg_details = array(
2089
+			'payment_method'       => $payment_method->name(),
2090
+			'response_msg'         => $payment->gateway_response(),
2091
+			'registration_id'      => $this->_registration->get('REG_code'),
2092
+			'registration_session' => $this->_registration->session_ID(),
2093
+			'ip_address'           => isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '',
2094
+			'user_agent'           => isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '',
2095
+		);
2096
+		if (isset($reg_details['registration_id'])) {
2097
+			$this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2098
+			$this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2099
+				'Registration ID',
2100
+				'event_espresso'
2101
+			);
2102
+			$this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2103
+		}
2104
+		if (isset($reg_details['payment_method'])) {
2105
+			$this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2106
+			$this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2107
+				'Most Recent Payment Method',
2108
+				'event_espresso'
2109
+			);
2110
+			$this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2111
+			$this->_template_args['reg_details']['response_msg']['value'] = $reg_details['response_msg'];
2112
+			$this->_template_args['reg_details']['response_msg']['label'] = esc_html__(
2113
+				'Payment method response',
2114
+				'event_espresso'
2115
+			);
2116
+			$this->_template_args['reg_details']['response_msg']['class'] = 'regular-text';
2117
+		}
2118
+		$this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2119
+		$this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2120
+			'Registration Session',
2121
+			'event_espresso'
2122
+		);
2123
+		$this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2124
+		$this->_template_args['reg_details']['ip_address']['value'] = $reg_details['ip_address'];
2125
+		$this->_template_args['reg_details']['ip_address']['label'] = esc_html__(
2126
+			'Registration placed from IP',
2127
+			'event_espresso'
2128
+		);
2129
+		$this->_template_args['reg_details']['ip_address']['class'] = 'regular-text';
2130
+		$this->_template_args['reg_details']['user_agent']['value'] = $reg_details['user_agent'];
2131
+		$this->_template_args['reg_details']['user_agent']['label'] = esc_html__(
2132
+			'Registrant User Agent',
2133
+			'event_espresso'
2134
+		);
2135
+		$this->_template_args['reg_details']['user_agent']['class'] = 'large-text';
2136
+		$this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
2137
+			array(
2138
+				'action'   => 'default',
2139
+				'event_id' => $this->_registration->event_ID(),
2140
+			),
2141
+			REG_ADMIN_URL
2142
+		);
2143
+		$this->_template_args['REG_ID'] = $this->_registration->ID();
2144
+		$this->_template_args['event_id'] = $this->_registration->event_ID();
2145
+		$template_path =
2146
+			REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2147
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2148
+	}
2149
+
2150
+
2151
+	/**
2152
+	 * generates HTML for the Registration Questions meta box.
2153
+	 * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2154
+	 * otherwise uses new forms system
2155
+	 *
2156
+	 * @access public
2157
+	 * @return void
2158
+	 * @throws DomainException
2159
+	 * @throws EE_Error
2160
+	 * @throws InvalidArgumentException
2161
+	 * @throws InvalidDataTypeException
2162
+	 * @throws InvalidInterfaceException
2163
+	 * @throws ReflectionException
2164
+	 */
2165
+	public function _reg_questions_meta_box()
2166
+	{
2167
+		// allow someone to override this method entirely
2168
+		if (apply_filters(
2169
+			'FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default',
2170
+			true,
2171
+			$this,
2172
+			$this->_registration
2173
+		)) {
2174
+			$form = $this->_get_reg_custom_questions_form(
2175
+				$this->_registration->ID()
2176
+			);
2177
+			$this->_template_args['att_questions'] = count($form->subforms()) > 0
2178
+				? $form->get_html_and_js()
2179
+				: '';
2180
+			$this->_template_args['reg_questions_form_action'] = 'edit_registration';
2181
+			$this->_template_args['REG_ID'] = $this->_registration->ID();
2182
+			$template_path =
2183
+				REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2184
+			echo EEH_Template::display_template($template_path, $this->_template_args, true);
2185
+		}
2186
+	}
2187
+
2188
+
2189
+	/**
2190
+	 * form_before_question_group
2191
+	 *
2192
+	 * @deprecated    as of 4.8.32.rc.000
2193
+	 * @access        public
2194
+	 * @param        string $output
2195
+	 * @return        string
2196
+	 */
2197
+	public function form_before_question_group($output)
2198
+	{
2199
+		EE_Error::doing_it_wrong(
2200
+			__CLASS__ . '::' . __FUNCTION__,
2201
+			esc_html__(
2202
+				'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.',
2203
+				'event_espresso'
2204
+			),
2205
+			'4.8.32.rc.000'
2206
+		);
2207
+		return '
2208 2208
 	<table class="form-table ee-width-100">
2209 2209
 		<tbody>
2210 2210
 			';
2211
-    }
2212
-
2213
-
2214
-    /**
2215
-     * form_after_question_group
2216
-     *
2217
-     * @deprecated    as of 4.8.32.rc.000
2218
-     * @access        public
2219
-     * @param        string $output
2220
-     * @return        string
2221
-     */
2222
-    public function form_after_question_group($output)
2223
-    {
2224
-        EE_Error::doing_it_wrong(
2225
-            __CLASS__ . '::' . __FUNCTION__,
2226
-            esc_html__(
2227
-                '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.',
2228
-                'event_espresso'
2229
-            ),
2230
-            '4.8.32.rc.000'
2231
-        );
2232
-        return '
2211
+	}
2212
+
2213
+
2214
+	/**
2215
+	 * form_after_question_group
2216
+	 *
2217
+	 * @deprecated    as of 4.8.32.rc.000
2218
+	 * @access        public
2219
+	 * @param        string $output
2220
+	 * @return        string
2221
+	 */
2222
+	public function form_after_question_group($output)
2223
+	{
2224
+		EE_Error::doing_it_wrong(
2225
+			__CLASS__ . '::' . __FUNCTION__,
2226
+			esc_html__(
2227
+				'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.',
2228
+				'event_espresso'
2229
+			),
2230
+			'4.8.32.rc.000'
2231
+		);
2232
+		return '
2233 2233
 			<tr class="hide-if-no-js">
2234 2234
 				<th> </th>
2235 2235
 				<td class="reg-admin-edit-attendee-question-td">
2236 2236
 					<a class="reg-admin-edit-attendee-question-lnk" href="#" title="'
2237
-               . esc_attr__('click to edit question', 'event_espresso')
2238
-               . '">
2237
+			   . esc_attr__('click to edit question', 'event_espresso')
2238
+			   . '">
2239 2239
 						<span class="reg-admin-edit-question-group-spn lt-grey-txt">'
2240
-               . esc_html__('edit the above question group', 'event_espresso')
2241
-               . '</span>
2240
+			   . esc_html__('edit the above question group', 'event_espresso')
2241
+			   . '</span>
2242 2242
 						<div class="dashicons dashicons-edit"></div>
2243 2243
 					</a>
2244 2244
 				</td>
@@ -2246,642 +2246,642 @@  discard block
 block discarded – undo
2246 2246
 		</tbody>
2247 2247
 	</table>
2248 2248
 ';
2249
-    }
2250
-
2251
-
2252
-    /**
2253
-     * form_form_field_label_wrap
2254
-     *
2255
-     * @deprecated    as of 4.8.32.rc.000
2256
-     * @access        public
2257
-     * @param        string $label
2258
-     * @return        string
2259
-     */
2260
-    public function form_form_field_label_wrap($label)
2261
-    {
2262
-        EE_Error::doing_it_wrong(
2263
-            __CLASS__ . '::' . __FUNCTION__,
2264
-            esc_html__(
2265
-                '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.',
2266
-                'event_espresso'
2267
-            ),
2268
-            '4.8.32.rc.000'
2269
-        );
2270
-        return '
2249
+	}
2250
+
2251
+
2252
+	/**
2253
+	 * form_form_field_label_wrap
2254
+	 *
2255
+	 * @deprecated    as of 4.8.32.rc.000
2256
+	 * @access        public
2257
+	 * @param        string $label
2258
+	 * @return        string
2259
+	 */
2260
+	public function form_form_field_label_wrap($label)
2261
+	{
2262
+		EE_Error::doing_it_wrong(
2263
+			__CLASS__ . '::' . __FUNCTION__,
2264
+			esc_html__(
2265
+				'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.',
2266
+				'event_espresso'
2267
+			),
2268
+			'4.8.32.rc.000'
2269
+		);
2270
+		return '
2271 2271
 			<tr>
2272 2272
 				<th>
2273 2273
 					' . $label . '
2274 2274
 				</th>';
2275
-    }
2276
-
2277
-
2278
-    /**
2279
-     * form_form_field_input__wrap
2280
-     *
2281
-     * @deprecated    as of 4.8.32.rc.000
2282
-     * @access        public
2283
-     * @param        string $input
2284
-     * @return        string
2285
-     */
2286
-    public function form_form_field_input__wrap($input)
2287
-    {
2288
-        EE_Error::doing_it_wrong(
2289
-            __CLASS__ . '::' . __FUNCTION__,
2290
-            esc_html__(
2291
-                '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.',
2292
-                'event_espresso'
2293
-            ),
2294
-            '4.8.32.rc.000'
2295
-        );
2296
-        return '
2275
+	}
2276
+
2277
+
2278
+	/**
2279
+	 * form_form_field_input__wrap
2280
+	 *
2281
+	 * @deprecated    as of 4.8.32.rc.000
2282
+	 * @access        public
2283
+	 * @param        string $input
2284
+	 * @return        string
2285
+	 */
2286
+	public function form_form_field_input__wrap($input)
2287
+	{
2288
+		EE_Error::doing_it_wrong(
2289
+			__CLASS__ . '::' . __FUNCTION__,
2290
+			esc_html__(
2291
+				'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.',
2292
+				'event_espresso'
2293
+			),
2294
+			'4.8.32.rc.000'
2295
+		);
2296
+		return '
2297 2297
 				<td class="reg-admin-attendee-questions-input-td disabled-input">
2298 2298
 					' . $input . '
2299 2299
 				</td>
2300 2300
 			</tr>';
2301
-    }
2302
-
2303
-
2304
-    /**
2305
-     * Updates the registration's custom questions according to the form info, if the form is submitted.
2306
-     * If it's not a post, the "view_registrations" route will be called next on the SAME request
2307
-     * to display the page
2308
-     *
2309
-     * @access protected
2310
-     * @return void
2311
-     * @throws EE_Error
2312
-     * @throws InvalidArgumentException
2313
-     * @throws InvalidDataTypeException
2314
-     * @throws InvalidInterfaceException
2315
-     * @throws ReflectionException
2316
-     */
2317
-    protected function _update_attendee_registration_form()
2318
-    {
2319
-        do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2320
-        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
2321
-            $REG_ID = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : false;
2322
-            $success = $this->_save_reg_custom_questions_form($REG_ID);
2323
-            if ($success) {
2324
-                $what = esc_html__('Registration Form', 'event_espresso');
2325
-                $route = $REG_ID ? array('action' => 'view_registration', '_REG_ID' => $REG_ID)
2326
-                    : array('action' => 'default');
2327
-                $this->_redirect_after_action($success, $what, esc_html__('updated', 'event_espresso'), $route);
2328
-            }
2329
-        }
2330
-    }
2331
-
2332
-
2333
-    /**
2334
-     * Gets the form for saving registrations custom questions (if done
2335
-     * previously retrieves the cached form object, which may have validation errors in it)
2336
-     *
2337
-     * @param int $REG_ID
2338
-     * @return EE_Registration_Custom_Questions_Form
2339
-     * @throws EE_Error
2340
-     * @throws InvalidArgumentException
2341
-     * @throws InvalidDataTypeException
2342
-     * @throws InvalidInterfaceException
2343
-     */
2344
-    protected function _get_reg_custom_questions_form($REG_ID)
2345
-    {
2346
-        if (! $this->_reg_custom_questions_form) {
2347
-            require_once(REG_ADMIN . 'form_sections/EE_Registration_Custom_Questions_Form.form.php');
2348
-            $this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2349
-                $this->getRegistrationModel()->get_one_by_ID($REG_ID)
2350
-            );
2351
-            $this->_reg_custom_questions_form->_construct_finalize(null, null);
2352
-        }
2353
-        return $this->_reg_custom_questions_form;
2354
-    }
2355
-
2356
-
2357
-    /**
2358
-     * Saves
2359
-     *
2360
-     * @access private
2361
-     * @param bool $REG_ID
2362
-     * @return bool
2363
-     * @throws EE_Error
2364
-     * @throws InvalidArgumentException
2365
-     * @throws InvalidDataTypeException
2366
-     * @throws InvalidInterfaceException
2367
-     * @throws ReflectionException
2368
-     */
2369
-    private function _save_reg_custom_questions_form($REG_ID = false)
2370
-    {
2371
-        if (! $REG_ID) {
2372
-            EE_Error::add_error(
2373
-                esc_html__(
2374
-                    'An error occurred. No registration ID was received.',
2375
-                    'event_espresso'
2376
-                ),
2377
-                __FILE__,
2378
-                __FUNCTION__,
2379
-                __LINE__
2380
-            );
2381
-        }
2382
-        $form = $this->_get_reg_custom_questions_form($REG_ID);
2383
-        $form->receive_form_submission($this->_req_data);
2384
-        $success = false;
2385
-        if ($form->is_valid()) {
2386
-            foreach ($form->subforms() as $question_group_id => $question_group_form) {
2387
-                foreach ($question_group_form->inputs() as $question_id => $input) {
2388
-                    $where_conditions = array(
2389
-                        'QST_ID' => $question_id,
2390
-                        'REG_ID' => $REG_ID,
2391
-                    );
2392
-                    $possibly_new_values = array(
2393
-                        'ANS_value' => $input->normalized_value(),
2394
-                    );
2395
-                    $answer = EEM_Answer::instance()->get_one(array($where_conditions));
2396
-                    if ($answer instanceof EE_Answer) {
2397
-                        $success = $answer->save($possibly_new_values);
2398
-                    } else {
2399
-                        // insert it then
2400
-                        $cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2401
-                        $answer = EE_Answer::new_instance($cols_n_vals);
2402
-                        $success = $answer->save();
2403
-                    }
2404
-                }
2405
-            }
2406
-        } else {
2407
-            EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2408
-        }
2409
-        return $success;
2410
-    }
2411
-
2412
-
2413
-    /**
2414
-     *        generates HTML for the Registration main meta box
2415
-     *
2416
-     * @access public
2417
-     * @return void
2418
-     * @throws DomainException
2419
-     * @throws EE_Error
2420
-     * @throws InvalidArgumentException
2421
-     * @throws InvalidDataTypeException
2422
-     * @throws InvalidInterfaceException
2423
-     * @throws ReflectionException
2424
-     */
2425
-    public function _reg_attendees_meta_box()
2426
-    {
2427
-        $REG = $this->getRegistrationModel();
2428
-        // get all other registrations on this transaction, and cache
2429
-        // the attendees for them so we don't have to run another query using force_join
2430
-        $registrations = $REG->get_all(
2431
-            array(
2432
-                array(
2433
-                    'TXN_ID' => $this->_registration->transaction_ID(),
2434
-                    'REG_ID' => array('!=', $this->_registration->ID()),
2435
-                ),
2436
-                'force_join' => array('Attendee'),
2437
-                'default_where_conditions' => 'other_models_only',
2438
-            )
2439
-        );
2440
-        $this->_template_args['attendees'] = array();
2441
-        $this->_template_args['attendee_notice'] = '';
2442
-        if (empty($registrations)
2443
-            || (is_array($registrations)
2444
-                && ! EEH_Array::get_one_item_from_array($registrations))
2445
-        ) {
2446
-            EE_Error::add_error(
2447
-                esc_html__(
2448
-                    'There are no records attached to this registration. Something may have gone wrong with the registration',
2449
-                    'event_espresso'
2450
-                ),
2451
-                __FILE__,
2452
-                __FUNCTION__,
2453
-                __LINE__
2454
-            );
2455
-            $this->_template_args['attendee_notice'] = EE_Error::get_notices();
2456
-        } else {
2457
-            $att_nmbr = 1;
2458
-            foreach ($registrations as $registration) {
2459
-                /* @var $registration EE_Registration */
2460
-                $attendee = $registration->attendee()
2461
-                    ? $registration->attendee()
2462
-                    : $this->getAttendeeModel()->create_default_object();
2463
-                $this->_template_args['attendees'][ $att_nmbr ]['STS_ID'] = $registration->status_ID();
2464
-                $this->_template_args['attendees'][ $att_nmbr ]['fname'] = $attendee->fname();
2465
-                $this->_template_args['attendees'][ $att_nmbr ]['lname'] = $attendee->lname();
2466
-                $this->_template_args['attendees'][ $att_nmbr ]['email'] = $attendee->email();
2467
-                $this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2468
-                $this->_template_args['attendees'][ $att_nmbr ]['address'] = implode(
2469
-                    ', ',
2470
-                    $attendee->full_address_as_array()
2471
-                );
2472
-                $this->_template_args['attendees'][ $att_nmbr ]['att_link'] = self::add_query_args_and_nonce(
2473
-                    array(
2474
-                        'action' => 'edit_attendee',
2475
-                        'post'   => $attendee->ID(),
2476
-                    ),
2477
-                    REG_ADMIN_URL
2478
-                );
2479
-                $this->_template_args['attendees'][ $att_nmbr ]['event_name'] = $registration->event_obj() instanceof EE_Event
2480
-                    ? $registration->event_obj()->name()
2481
-                    : '';
2482
-                $att_nmbr++;
2483
-            }
2484
-            $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2485
-        }
2486
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2487
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2488
-    }
2489
-
2490
-
2491
-    /**
2492
-     *        generates HTML for the Edit Registration side meta box
2493
-     *
2494
-     * @access public
2495
-     * @return void
2496
-     * @throws DomainException
2497
-     * @throws EE_Error
2498
-     * @throws InvalidArgumentException
2499
-     * @throws InvalidDataTypeException
2500
-     * @throws InvalidInterfaceException
2501
-     * @throws ReflectionException
2502
-     */
2503
-    public function _reg_registrant_side_meta_box()
2504
-    {
2505
-        /*@var $attendee EE_Attendee */
2506
-        $att_check = $this->_registration->attendee();
2507
-        $attendee = $att_check instanceof EE_Attendee
2508
-            ? $att_check
2509
-            : $this->getAttendeeModel()->create_default_object();
2510
-        // now let's determine if this is not the primary registration.  If it isn't then we set the
2511
-        // primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2512
-        // primary registration object (that way we know if we need to show create button or not)
2513
-        if (! $this->_registration->is_primary_registrant()) {
2514
-            $primary_registration = $this->_registration->get_primary_registration();
2515
-            $primary_attendee = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2516
-                : null;
2517
-            if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2518
-                // in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2519
-                // custom attendee object so let's not worry about the primary reg.
2520
-                $primary_registration = null;
2521
-            }
2522
-        } else {
2523
-            $primary_registration = null;
2524
-        }
2525
-        $this->_template_args['ATT_ID'] = $attendee->ID();
2526
-        $this->_template_args['fname'] = $attendee->fname();
2527
-        $this->_template_args['lname'] = $attendee->lname();
2528
-        $this->_template_args['email'] = $attendee->email();
2529
-        $this->_template_args['phone'] = $attendee->phone();
2530
-        $this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2531
-        // edit link
2532
-        $this->_template_args['att_edit_link'] = EE_Admin_Page::add_query_args_and_nonce(
2533
-            array(
2534
-                'action' => 'edit_attendee',
2535
-                'post'   => $attendee->ID(),
2536
-            ),
2537
-            REG_ADMIN_URL
2538
-        );
2539
-        $this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2540
-        // create link
2541
-        $this->_template_args['create_link'] = $primary_registration instanceof EE_Registration
2542
-            ? EE_Admin_Page::add_query_args_and_nonce(
2543
-                array(
2544
-                    'action'  => 'duplicate_attendee',
2545
-                    '_REG_ID' => $this->_registration->ID(),
2546
-                ),
2547
-                REG_ADMIN_URL
2548
-            ) : '';
2549
-        $this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2550
-        $this->_template_args['att_check'] = $att_check;
2551
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2552
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2553
-    }
2554
-
2555
-
2556
-    /**
2557
-     * trash or restore registrations
2558
-     *
2559
-     * @param  boolean $trash whether to archive or restore
2560
-     * @return void
2561
-     * @throws EE_Error
2562
-     * @throws InvalidArgumentException
2563
-     * @throws InvalidDataTypeException
2564
-     * @throws InvalidInterfaceException
2565
-     * @throws RuntimeException
2566
-     * @access protected
2567
-     */
2568
-    protected function _trash_or_restore_registrations($trash = true)
2569
-    {
2570
-        // if empty _REG_ID then get out because there's nothing to do
2571
-        if (empty($this->_req_data['_REG_ID'])) {
2572
-            EE_Error::add_error(
2573
-                sprintf(
2574
-                    esc_html__(
2575
-                        'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2576
-                        'event_espresso'
2577
-                    ),
2578
-                    $trash ? 'trash' : 'restore'
2579
-                ),
2580
-                __FILE__,
2581
-                __LINE__,
2582
-                __FUNCTION__
2583
-            );
2584
-            $this->_redirect_after_action(false, '', '', array(), true);
2585
-        }
2586
-        $success = 0;
2587
-        $overwrite_msgs = false;
2588
-        // Checkboxes
2589
-        if (! is_array($this->_req_data['_REG_ID'])) {
2590
-            $this->_req_data['_REG_ID'] = array($this->_req_data['_REG_ID']);
2591
-        }
2592
-        $reg_count = count($this->_req_data['_REG_ID']);
2593
-        // cycle thru checkboxes
2594
-        foreach ($this->_req_data['_REG_ID'] as $REG_ID) {
2595
-            /** @var EE_Registration $REG */
2596
-            $REG = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
2597
-            $payments = $REG->registration_payments();
2598
-            if (! empty($payments)) {
2599
-                $name = $REG->attendee() instanceof EE_Attendee
2600
-                    ? $REG->attendee()->full_name()
2601
-                    : esc_html__('Unknown Attendee', 'event_espresso');
2602
-                $overwrite_msgs = true;
2603
-                EE_Error::add_error(
2604
-                    sprintf(
2605
-                        esc_html__(
2606
-                            '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.',
2607
-                            'event_espresso'
2608
-                        ),
2609
-                        $name
2610
-                    ),
2611
-                    __FILE__,
2612
-                    __FUNCTION__,
2613
-                    __LINE__
2614
-                );
2615
-                // can't trash this registration because it has payments.
2616
-                continue;
2617
-            }
2618
-            $updated = $trash ? $REG->delete() : $REG->restore();
2619
-            if ($updated) {
2620
-                $success++;
2621
-            }
2622
-        }
2623
-        $this->_redirect_after_action(
2624
-            $success === $reg_count, // were ALL registrations affected?
2625
-            $success > 1
2626
-                ? esc_html__('Registrations', 'event_espresso')
2627
-                : esc_html__('Registration', 'event_espresso'),
2628
-            $trash
2629
-                ? esc_html__('moved to the trash', 'event_espresso')
2630
-                : esc_html__('restored', 'event_espresso'),
2631
-            $this->mergeExistingRequestParamsWithRedirectArgs(array('action' => 'default')),
2632
-            $overwrite_msgs
2633
-        );
2634
-    }
2635
-
2636
-
2637
-    /**
2638
-     * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2639
-     * registration but also.
2640
-     * 1. Removing relations to EE_Attendee
2641
-     * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2642
-     * ALSO trashed.
2643
-     * 3. Deleting permanently any related Line items but only if the above conditions are met.
2644
-     * 4. Removing relationships between all tickets and the related registrations
2645
-     * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2646
-     * 6. Deleting permanently any related Checkins.
2647
-     *
2648
-     * @return void
2649
-     * @throws EE_Error
2650
-     * @throws InvalidArgumentException
2651
-     * @throws InvalidDataTypeException
2652
-     * @throws InvalidInterfaceException
2653
-     * @throws ReflectionException
2654
-     */
2655
-    protected function _delete_registrations()
2656
-    {
2657
-        $REG_MDL = $this->getRegistrationModel();
2658
-        $success = 1;
2659
-        // Checkboxes
2660
-        if (! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2661
-            // if array has more than one element than success message should be plural
2662
-            $success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
2663
-            // cycle thru checkboxes
2664
-            foreach ($this->_req_data['_REG_ID'] as $REG_ID) {
2665
-                $REG = $REG_MDL->get_one_by_ID($REG_ID);
2666
-                if (! $REG instanceof EE_Registration) {
2667
-                    continue;
2668
-                }
2669
-                $deleted = $this->_delete_registration($REG);
2670
-                if (! $deleted) {
2671
-                    $success = 0;
2672
-                }
2673
-            }
2674
-        } else {
2675
-            // grab single id and delete
2676
-            $REG_ID = $this->_req_data['_REG_ID'];
2677
-            /** @var EE_Registration $REG */
2678
-            $REG = $REG_MDL->get_one_by_ID($REG_ID);
2679
-            $deleted = $this->_delete_registration($REG);
2680
-            if (! $deleted) {
2681
-                $success = 0;
2682
-            }
2683
-        }
2684
-        $what = $success > 1
2685
-            ? esc_html__('Registrations', 'event_espresso')
2686
-            : esc_html__('Registration', 'event_espresso');
2687
-        $action_desc = esc_html__('permanently deleted.', 'event_espresso');
2688
-        $this->_redirect_after_action(
2689
-            $success,
2690
-            $what,
2691
-            $action_desc,
2692
-            $this->mergeExistingRequestParamsWithRedirectArgs(['action' => 'default']),
2693
-            true
2694
-        );
2695
-    }
2696
-
2697
-
2698
-    /**
2699
-     * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2700
-     * models get affected.
2701
-     *
2702
-     * @param EE_Registration $REG registration to be deleted permanently
2703
-     * @return bool true = successful deletion, false = fail.
2704
-     * @throws EE_Error
2705
-     * @throws InvalidArgumentException
2706
-     * @throws InvalidDataTypeException
2707
-     * @throws InvalidInterfaceException
2708
-     * @throws ReflectionException
2709
-     */
2710
-    protected function _delete_registration(EE_Registration $REG)
2711
-    {
2712
-        // first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2713
-        // registrations on the transaction that are NOT trashed.
2714
-        $TXN = $REG->get_first_related('Transaction');
2715
-        if (! $TXN instanceof EE_Transaction) {
2716
-            EE_Error::add_error(
2717
-                sprintf(
2718
-                    esc_html__(
2719
-                        'Unable to permanently delete registration %d because its related transaction has already been deleted. If you can restore the related transaction to the database then this registration can be deleted.',
2720
-                        'event_espresso'
2721
-                    ),
2722
-                    $REG->id()
2723
-                ),
2724
-                __FILE__,
2725
-                __FUNCTION__,
2726
-                __LINE__
2727
-            );
2728
-            return false;
2729
-        }
2730
-        $REGS = $TXN->get_many_related('Registration');
2731
-        $all_trashed = true;
2732
-        foreach ($REGS as $registration) {
2733
-            if (! $registration->get('REG_deleted')) {
2734
-                $all_trashed = false;
2735
-            }
2736
-        }
2737
-        if (! $all_trashed) {
2738
-            EE_Error::add_error(
2739
-                esc_html__(
2740
-                    '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.',
2741
-                    'event_espresso'
2742
-                ),
2743
-                __FILE__,
2744
-                __FUNCTION__,
2745
-                __LINE__
2746
-            );
2747
-            return false;
2748
-        }
2749
-        // k made it here so that means we can delete all the related transactions and their answers (but let's do them
2750
-        // separately from THIS one).
2751
-        foreach ($REGS as $registration) {
2752
-            // delete related answers
2753
-            $registration->delete_related_permanently('Answer');
2754
-            // remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2755
-            $attendee = $registration->get_first_related('Attendee');
2756
-            if ($attendee instanceof EE_Attendee) {
2757
-                $registration->_remove_relation_to($attendee, 'Attendee');
2758
-            }
2759
-            // now remove relationships to tickets on this registration.
2760
-            $registration->_remove_relations('Ticket');
2761
-            // now delete permanently the checkins related to this registration.
2762
-            $registration->delete_related_permanently('Checkin');
2763
-            if ($registration->ID() === $REG->ID()) {
2764
-                continue;
2765
-            } //we don't want to delete permanently the existing registration just yet.
2766
-            // remove relation to transaction for these registrations if NOT the existing registrations
2767
-            $registration->_remove_relations('Transaction');
2768
-            // delete permanently any related messages.
2769
-            $registration->delete_related_permanently('Message');
2770
-            // now delete this registration permanently
2771
-            $registration->delete_permanently();
2772
-        }
2773
-        // now all related registrations on the transaction are handled.  So let's just handle this registration itself
2774
-        // (the transaction and line items should be all that's left).
2775
-        // delete the line items related to the transaction for this registration.
2776
-        $TXN->delete_related_permanently('Line_Item');
2777
-        // we need to remove all the relationships on the transaction
2778
-        $TXN->delete_related_permanently('Payment');
2779
-        $TXN->delete_related_permanently('Extra_Meta');
2780
-        $TXN->delete_related_permanently('Message');
2781
-        // now we can delete this REG permanently (and the transaction of course)
2782
-        $REG->delete_related_permanently('Transaction');
2783
-        return $REG->delete_permanently();
2784
-    }
2785
-
2786
-
2787
-    /**
2788
-     *    generates HTML for the Register New Attendee Admin page
2789
-     *
2790
-     * @access private
2791
-     * @throws DomainException
2792
-     * @throws EE_Error
2793
-     * @throws InvalidArgumentException
2794
-     * @throws InvalidDataTypeException
2795
-     * @throws InvalidInterfaceException
2796
-     * @throws ReflectionException
2797
-     */
2798
-    public function new_registration()
2799
-    {
2800
-        if (! $this->_set_reg_event()) {
2801
-            throw new EE_Error(
2802
-                esc_html__(
2803
-                    'Unable to continue with registering because there is no Event ID in the request',
2804
-                    'event_espresso'
2805
-                )
2806
-            );
2807
-        }
2808
-        EE_Registry::instance()->REQ->set_espresso_page(true);
2809
-        // gotta start with a clean slate if we're not coming here via ajax
2810
-        if (! defined('DOING_AJAX')
2811
-            && (! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2812
-        ) {
2813
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2814
-        }
2815
-        $this->_template_args['event_name'] = '';
2816
-        // event name
2817
-        if ($this->_reg_event) {
2818
-            $this->_template_args['event_name'] = $this->_reg_event->name();
2819
-            $edit_event_url = self::add_query_args_and_nonce(
2820
-                array(
2821
-                    'action' => 'edit',
2822
-                    'post'   => $this->_reg_event->ID(),
2823
-                ),
2824
-                EVENTS_ADMIN_URL
2825
-            );
2826
-            $edit_event_lnk = '<a href="'
2827
-                              . $edit_event_url
2828
-                              . '" title="'
2829
-                              . esc_attr__('Edit ', 'event_espresso')
2830
-                              . $this->_reg_event->name()
2831
-                              . '">'
2832
-                              . esc_html__('Edit Event', 'event_espresso')
2833
-                              . '</a>';
2834
-            $this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2835
-                                                   . $edit_event_lnk
2836
-                                                   . '</span>';
2837
-        }
2838
-        $this->_template_args['step_content'] = $this->_get_registration_step_content();
2839
-        if (defined('DOING_AJAX')) {
2840
-            $this->_return_json();
2841
-        }
2842
-        // grab header
2843
-        $template_path =
2844
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2845
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2846
-            $template_path,
2847
-            $this->_template_args,
2848
-            true
2849
-        );
2850
-        // $this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2851
-        // the details template wrapper
2852
-        $this->display_admin_page_with_sidebar();
2853
-    }
2854
-
2855
-
2856
-    /**
2857
-     * This returns the content for a registration step
2858
-     *
2859
-     * @access protected
2860
-     * @return string html
2861
-     * @throws DomainException
2862
-     * @throws EE_Error
2863
-     * @throws InvalidArgumentException
2864
-     * @throws InvalidDataTypeException
2865
-     * @throws InvalidInterfaceException
2866
-     */
2867
-    protected function _get_registration_step_content()
2868
-    {
2869
-        if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
2870
-            $warning_msg = sprintf(
2871
-                esc_html__(
2872
-                    '%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',
2873
-                    'event_espresso'
2874
-                ),
2875
-                '<br />',
2876
-                '<h3 class="important-notice">',
2877
-                '</h3>',
2878
-                '<div class="float-right">',
2879
-                '<span id="redirect_timer" class="important-notice">30</span>',
2880
-                '</div>',
2881
-                '<b>',
2882
-                '</b>'
2883
-            );
2884
-            return '
2301
+	}
2302
+
2303
+
2304
+	/**
2305
+	 * Updates the registration's custom questions according to the form info, if the form is submitted.
2306
+	 * If it's not a post, the "view_registrations" route will be called next on the SAME request
2307
+	 * to display the page
2308
+	 *
2309
+	 * @access protected
2310
+	 * @return void
2311
+	 * @throws EE_Error
2312
+	 * @throws InvalidArgumentException
2313
+	 * @throws InvalidDataTypeException
2314
+	 * @throws InvalidInterfaceException
2315
+	 * @throws ReflectionException
2316
+	 */
2317
+	protected function _update_attendee_registration_form()
2318
+	{
2319
+		do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2320
+		if ($_SERVER['REQUEST_METHOD'] === 'POST') {
2321
+			$REG_ID = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : false;
2322
+			$success = $this->_save_reg_custom_questions_form($REG_ID);
2323
+			if ($success) {
2324
+				$what = esc_html__('Registration Form', 'event_espresso');
2325
+				$route = $REG_ID ? array('action' => 'view_registration', '_REG_ID' => $REG_ID)
2326
+					: array('action' => 'default');
2327
+				$this->_redirect_after_action($success, $what, esc_html__('updated', 'event_espresso'), $route);
2328
+			}
2329
+		}
2330
+	}
2331
+
2332
+
2333
+	/**
2334
+	 * Gets the form for saving registrations custom questions (if done
2335
+	 * previously retrieves the cached form object, which may have validation errors in it)
2336
+	 *
2337
+	 * @param int $REG_ID
2338
+	 * @return EE_Registration_Custom_Questions_Form
2339
+	 * @throws EE_Error
2340
+	 * @throws InvalidArgumentException
2341
+	 * @throws InvalidDataTypeException
2342
+	 * @throws InvalidInterfaceException
2343
+	 */
2344
+	protected function _get_reg_custom_questions_form($REG_ID)
2345
+	{
2346
+		if (! $this->_reg_custom_questions_form) {
2347
+			require_once(REG_ADMIN . 'form_sections/EE_Registration_Custom_Questions_Form.form.php');
2348
+			$this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2349
+				$this->getRegistrationModel()->get_one_by_ID($REG_ID)
2350
+			);
2351
+			$this->_reg_custom_questions_form->_construct_finalize(null, null);
2352
+		}
2353
+		return $this->_reg_custom_questions_form;
2354
+	}
2355
+
2356
+
2357
+	/**
2358
+	 * Saves
2359
+	 *
2360
+	 * @access private
2361
+	 * @param bool $REG_ID
2362
+	 * @return bool
2363
+	 * @throws EE_Error
2364
+	 * @throws InvalidArgumentException
2365
+	 * @throws InvalidDataTypeException
2366
+	 * @throws InvalidInterfaceException
2367
+	 * @throws ReflectionException
2368
+	 */
2369
+	private function _save_reg_custom_questions_form($REG_ID = false)
2370
+	{
2371
+		if (! $REG_ID) {
2372
+			EE_Error::add_error(
2373
+				esc_html__(
2374
+					'An error occurred. No registration ID was received.',
2375
+					'event_espresso'
2376
+				),
2377
+				__FILE__,
2378
+				__FUNCTION__,
2379
+				__LINE__
2380
+			);
2381
+		}
2382
+		$form = $this->_get_reg_custom_questions_form($REG_ID);
2383
+		$form->receive_form_submission($this->_req_data);
2384
+		$success = false;
2385
+		if ($form->is_valid()) {
2386
+			foreach ($form->subforms() as $question_group_id => $question_group_form) {
2387
+				foreach ($question_group_form->inputs() as $question_id => $input) {
2388
+					$where_conditions = array(
2389
+						'QST_ID' => $question_id,
2390
+						'REG_ID' => $REG_ID,
2391
+					);
2392
+					$possibly_new_values = array(
2393
+						'ANS_value' => $input->normalized_value(),
2394
+					);
2395
+					$answer = EEM_Answer::instance()->get_one(array($where_conditions));
2396
+					if ($answer instanceof EE_Answer) {
2397
+						$success = $answer->save($possibly_new_values);
2398
+					} else {
2399
+						// insert it then
2400
+						$cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2401
+						$answer = EE_Answer::new_instance($cols_n_vals);
2402
+						$success = $answer->save();
2403
+					}
2404
+				}
2405
+			}
2406
+		} else {
2407
+			EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2408
+		}
2409
+		return $success;
2410
+	}
2411
+
2412
+
2413
+	/**
2414
+	 *        generates HTML for the Registration main meta box
2415
+	 *
2416
+	 * @access public
2417
+	 * @return void
2418
+	 * @throws DomainException
2419
+	 * @throws EE_Error
2420
+	 * @throws InvalidArgumentException
2421
+	 * @throws InvalidDataTypeException
2422
+	 * @throws InvalidInterfaceException
2423
+	 * @throws ReflectionException
2424
+	 */
2425
+	public function _reg_attendees_meta_box()
2426
+	{
2427
+		$REG = $this->getRegistrationModel();
2428
+		// get all other registrations on this transaction, and cache
2429
+		// the attendees for them so we don't have to run another query using force_join
2430
+		$registrations = $REG->get_all(
2431
+			array(
2432
+				array(
2433
+					'TXN_ID' => $this->_registration->transaction_ID(),
2434
+					'REG_ID' => array('!=', $this->_registration->ID()),
2435
+				),
2436
+				'force_join' => array('Attendee'),
2437
+				'default_where_conditions' => 'other_models_only',
2438
+			)
2439
+		);
2440
+		$this->_template_args['attendees'] = array();
2441
+		$this->_template_args['attendee_notice'] = '';
2442
+		if (empty($registrations)
2443
+			|| (is_array($registrations)
2444
+				&& ! EEH_Array::get_one_item_from_array($registrations))
2445
+		) {
2446
+			EE_Error::add_error(
2447
+				esc_html__(
2448
+					'There are no records attached to this registration. Something may have gone wrong with the registration',
2449
+					'event_espresso'
2450
+				),
2451
+				__FILE__,
2452
+				__FUNCTION__,
2453
+				__LINE__
2454
+			);
2455
+			$this->_template_args['attendee_notice'] = EE_Error::get_notices();
2456
+		} else {
2457
+			$att_nmbr = 1;
2458
+			foreach ($registrations as $registration) {
2459
+				/* @var $registration EE_Registration */
2460
+				$attendee = $registration->attendee()
2461
+					? $registration->attendee()
2462
+					: $this->getAttendeeModel()->create_default_object();
2463
+				$this->_template_args['attendees'][ $att_nmbr ]['STS_ID'] = $registration->status_ID();
2464
+				$this->_template_args['attendees'][ $att_nmbr ]['fname'] = $attendee->fname();
2465
+				$this->_template_args['attendees'][ $att_nmbr ]['lname'] = $attendee->lname();
2466
+				$this->_template_args['attendees'][ $att_nmbr ]['email'] = $attendee->email();
2467
+				$this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2468
+				$this->_template_args['attendees'][ $att_nmbr ]['address'] = implode(
2469
+					', ',
2470
+					$attendee->full_address_as_array()
2471
+				);
2472
+				$this->_template_args['attendees'][ $att_nmbr ]['att_link'] = self::add_query_args_and_nonce(
2473
+					array(
2474
+						'action' => 'edit_attendee',
2475
+						'post'   => $attendee->ID(),
2476
+					),
2477
+					REG_ADMIN_URL
2478
+				);
2479
+				$this->_template_args['attendees'][ $att_nmbr ]['event_name'] = $registration->event_obj() instanceof EE_Event
2480
+					? $registration->event_obj()->name()
2481
+					: '';
2482
+				$att_nmbr++;
2483
+			}
2484
+			$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2485
+		}
2486
+		$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2487
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2488
+	}
2489
+
2490
+
2491
+	/**
2492
+	 *        generates HTML for the Edit Registration side meta box
2493
+	 *
2494
+	 * @access public
2495
+	 * @return void
2496
+	 * @throws DomainException
2497
+	 * @throws EE_Error
2498
+	 * @throws InvalidArgumentException
2499
+	 * @throws InvalidDataTypeException
2500
+	 * @throws InvalidInterfaceException
2501
+	 * @throws ReflectionException
2502
+	 */
2503
+	public function _reg_registrant_side_meta_box()
2504
+	{
2505
+		/*@var $attendee EE_Attendee */
2506
+		$att_check = $this->_registration->attendee();
2507
+		$attendee = $att_check instanceof EE_Attendee
2508
+			? $att_check
2509
+			: $this->getAttendeeModel()->create_default_object();
2510
+		// now let's determine if this is not the primary registration.  If it isn't then we set the
2511
+		// primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2512
+		// primary registration object (that way we know if we need to show create button or not)
2513
+		if (! $this->_registration->is_primary_registrant()) {
2514
+			$primary_registration = $this->_registration->get_primary_registration();
2515
+			$primary_attendee = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2516
+				: null;
2517
+			if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2518
+				// in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2519
+				// custom attendee object so let's not worry about the primary reg.
2520
+				$primary_registration = null;
2521
+			}
2522
+		} else {
2523
+			$primary_registration = null;
2524
+		}
2525
+		$this->_template_args['ATT_ID'] = $attendee->ID();
2526
+		$this->_template_args['fname'] = $attendee->fname();
2527
+		$this->_template_args['lname'] = $attendee->lname();
2528
+		$this->_template_args['email'] = $attendee->email();
2529
+		$this->_template_args['phone'] = $attendee->phone();
2530
+		$this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2531
+		// edit link
2532
+		$this->_template_args['att_edit_link'] = EE_Admin_Page::add_query_args_and_nonce(
2533
+			array(
2534
+				'action' => 'edit_attendee',
2535
+				'post'   => $attendee->ID(),
2536
+			),
2537
+			REG_ADMIN_URL
2538
+		);
2539
+		$this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2540
+		// create link
2541
+		$this->_template_args['create_link'] = $primary_registration instanceof EE_Registration
2542
+			? EE_Admin_Page::add_query_args_and_nonce(
2543
+				array(
2544
+					'action'  => 'duplicate_attendee',
2545
+					'_REG_ID' => $this->_registration->ID(),
2546
+				),
2547
+				REG_ADMIN_URL
2548
+			) : '';
2549
+		$this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2550
+		$this->_template_args['att_check'] = $att_check;
2551
+		$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2552
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2553
+	}
2554
+
2555
+
2556
+	/**
2557
+	 * trash or restore registrations
2558
+	 *
2559
+	 * @param  boolean $trash whether to archive or restore
2560
+	 * @return void
2561
+	 * @throws EE_Error
2562
+	 * @throws InvalidArgumentException
2563
+	 * @throws InvalidDataTypeException
2564
+	 * @throws InvalidInterfaceException
2565
+	 * @throws RuntimeException
2566
+	 * @access protected
2567
+	 */
2568
+	protected function _trash_or_restore_registrations($trash = true)
2569
+	{
2570
+		// if empty _REG_ID then get out because there's nothing to do
2571
+		if (empty($this->_req_data['_REG_ID'])) {
2572
+			EE_Error::add_error(
2573
+				sprintf(
2574
+					esc_html__(
2575
+						'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2576
+						'event_espresso'
2577
+					),
2578
+					$trash ? 'trash' : 'restore'
2579
+				),
2580
+				__FILE__,
2581
+				__LINE__,
2582
+				__FUNCTION__
2583
+			);
2584
+			$this->_redirect_after_action(false, '', '', array(), true);
2585
+		}
2586
+		$success = 0;
2587
+		$overwrite_msgs = false;
2588
+		// Checkboxes
2589
+		if (! is_array($this->_req_data['_REG_ID'])) {
2590
+			$this->_req_data['_REG_ID'] = array($this->_req_data['_REG_ID']);
2591
+		}
2592
+		$reg_count = count($this->_req_data['_REG_ID']);
2593
+		// cycle thru checkboxes
2594
+		foreach ($this->_req_data['_REG_ID'] as $REG_ID) {
2595
+			/** @var EE_Registration $REG */
2596
+			$REG = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
2597
+			$payments = $REG->registration_payments();
2598
+			if (! empty($payments)) {
2599
+				$name = $REG->attendee() instanceof EE_Attendee
2600
+					? $REG->attendee()->full_name()
2601
+					: esc_html__('Unknown Attendee', 'event_espresso');
2602
+				$overwrite_msgs = true;
2603
+				EE_Error::add_error(
2604
+					sprintf(
2605
+						esc_html__(
2606
+							'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.',
2607
+							'event_espresso'
2608
+						),
2609
+						$name
2610
+					),
2611
+					__FILE__,
2612
+					__FUNCTION__,
2613
+					__LINE__
2614
+				);
2615
+				// can't trash this registration because it has payments.
2616
+				continue;
2617
+			}
2618
+			$updated = $trash ? $REG->delete() : $REG->restore();
2619
+			if ($updated) {
2620
+				$success++;
2621
+			}
2622
+		}
2623
+		$this->_redirect_after_action(
2624
+			$success === $reg_count, // were ALL registrations affected?
2625
+			$success > 1
2626
+				? esc_html__('Registrations', 'event_espresso')
2627
+				: esc_html__('Registration', 'event_espresso'),
2628
+			$trash
2629
+				? esc_html__('moved to the trash', 'event_espresso')
2630
+				: esc_html__('restored', 'event_espresso'),
2631
+			$this->mergeExistingRequestParamsWithRedirectArgs(array('action' => 'default')),
2632
+			$overwrite_msgs
2633
+		);
2634
+	}
2635
+
2636
+
2637
+	/**
2638
+	 * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2639
+	 * registration but also.
2640
+	 * 1. Removing relations to EE_Attendee
2641
+	 * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2642
+	 * ALSO trashed.
2643
+	 * 3. Deleting permanently any related Line items but only if the above conditions are met.
2644
+	 * 4. Removing relationships between all tickets and the related registrations
2645
+	 * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2646
+	 * 6. Deleting permanently any related Checkins.
2647
+	 *
2648
+	 * @return void
2649
+	 * @throws EE_Error
2650
+	 * @throws InvalidArgumentException
2651
+	 * @throws InvalidDataTypeException
2652
+	 * @throws InvalidInterfaceException
2653
+	 * @throws ReflectionException
2654
+	 */
2655
+	protected function _delete_registrations()
2656
+	{
2657
+		$REG_MDL = $this->getRegistrationModel();
2658
+		$success = 1;
2659
+		// Checkboxes
2660
+		if (! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2661
+			// if array has more than one element than success message should be plural
2662
+			$success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
2663
+			// cycle thru checkboxes
2664
+			foreach ($this->_req_data['_REG_ID'] as $REG_ID) {
2665
+				$REG = $REG_MDL->get_one_by_ID($REG_ID);
2666
+				if (! $REG instanceof EE_Registration) {
2667
+					continue;
2668
+				}
2669
+				$deleted = $this->_delete_registration($REG);
2670
+				if (! $deleted) {
2671
+					$success = 0;
2672
+				}
2673
+			}
2674
+		} else {
2675
+			// grab single id and delete
2676
+			$REG_ID = $this->_req_data['_REG_ID'];
2677
+			/** @var EE_Registration $REG */
2678
+			$REG = $REG_MDL->get_one_by_ID($REG_ID);
2679
+			$deleted = $this->_delete_registration($REG);
2680
+			if (! $deleted) {
2681
+				$success = 0;
2682
+			}
2683
+		}
2684
+		$what = $success > 1
2685
+			? esc_html__('Registrations', 'event_espresso')
2686
+			: esc_html__('Registration', 'event_espresso');
2687
+		$action_desc = esc_html__('permanently deleted.', 'event_espresso');
2688
+		$this->_redirect_after_action(
2689
+			$success,
2690
+			$what,
2691
+			$action_desc,
2692
+			$this->mergeExistingRequestParamsWithRedirectArgs(['action' => 'default']),
2693
+			true
2694
+		);
2695
+	}
2696
+
2697
+
2698
+	/**
2699
+	 * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2700
+	 * models get affected.
2701
+	 *
2702
+	 * @param EE_Registration $REG registration to be deleted permanently
2703
+	 * @return bool true = successful deletion, false = fail.
2704
+	 * @throws EE_Error
2705
+	 * @throws InvalidArgumentException
2706
+	 * @throws InvalidDataTypeException
2707
+	 * @throws InvalidInterfaceException
2708
+	 * @throws ReflectionException
2709
+	 */
2710
+	protected function _delete_registration(EE_Registration $REG)
2711
+	{
2712
+		// first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2713
+		// registrations on the transaction that are NOT trashed.
2714
+		$TXN = $REG->get_first_related('Transaction');
2715
+		if (! $TXN instanceof EE_Transaction) {
2716
+			EE_Error::add_error(
2717
+				sprintf(
2718
+					esc_html__(
2719
+						'Unable to permanently delete registration %d because its related transaction has already been deleted. If you can restore the related transaction to the database then this registration can be deleted.',
2720
+						'event_espresso'
2721
+					),
2722
+					$REG->id()
2723
+				),
2724
+				__FILE__,
2725
+				__FUNCTION__,
2726
+				__LINE__
2727
+			);
2728
+			return false;
2729
+		}
2730
+		$REGS = $TXN->get_many_related('Registration');
2731
+		$all_trashed = true;
2732
+		foreach ($REGS as $registration) {
2733
+			if (! $registration->get('REG_deleted')) {
2734
+				$all_trashed = false;
2735
+			}
2736
+		}
2737
+		if (! $all_trashed) {
2738
+			EE_Error::add_error(
2739
+				esc_html__(
2740
+					'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.',
2741
+					'event_espresso'
2742
+				),
2743
+				__FILE__,
2744
+				__FUNCTION__,
2745
+				__LINE__
2746
+			);
2747
+			return false;
2748
+		}
2749
+		// k made it here so that means we can delete all the related transactions and their answers (but let's do them
2750
+		// separately from THIS one).
2751
+		foreach ($REGS as $registration) {
2752
+			// delete related answers
2753
+			$registration->delete_related_permanently('Answer');
2754
+			// remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2755
+			$attendee = $registration->get_first_related('Attendee');
2756
+			if ($attendee instanceof EE_Attendee) {
2757
+				$registration->_remove_relation_to($attendee, 'Attendee');
2758
+			}
2759
+			// now remove relationships to tickets on this registration.
2760
+			$registration->_remove_relations('Ticket');
2761
+			// now delete permanently the checkins related to this registration.
2762
+			$registration->delete_related_permanently('Checkin');
2763
+			if ($registration->ID() === $REG->ID()) {
2764
+				continue;
2765
+			} //we don't want to delete permanently the existing registration just yet.
2766
+			// remove relation to transaction for these registrations if NOT the existing registrations
2767
+			$registration->_remove_relations('Transaction');
2768
+			// delete permanently any related messages.
2769
+			$registration->delete_related_permanently('Message');
2770
+			// now delete this registration permanently
2771
+			$registration->delete_permanently();
2772
+		}
2773
+		// now all related registrations on the transaction are handled.  So let's just handle this registration itself
2774
+		// (the transaction and line items should be all that's left).
2775
+		// delete the line items related to the transaction for this registration.
2776
+		$TXN->delete_related_permanently('Line_Item');
2777
+		// we need to remove all the relationships on the transaction
2778
+		$TXN->delete_related_permanently('Payment');
2779
+		$TXN->delete_related_permanently('Extra_Meta');
2780
+		$TXN->delete_related_permanently('Message');
2781
+		// now we can delete this REG permanently (and the transaction of course)
2782
+		$REG->delete_related_permanently('Transaction');
2783
+		return $REG->delete_permanently();
2784
+	}
2785
+
2786
+
2787
+	/**
2788
+	 *    generates HTML for the Register New Attendee Admin page
2789
+	 *
2790
+	 * @access private
2791
+	 * @throws DomainException
2792
+	 * @throws EE_Error
2793
+	 * @throws InvalidArgumentException
2794
+	 * @throws InvalidDataTypeException
2795
+	 * @throws InvalidInterfaceException
2796
+	 * @throws ReflectionException
2797
+	 */
2798
+	public function new_registration()
2799
+	{
2800
+		if (! $this->_set_reg_event()) {
2801
+			throw new EE_Error(
2802
+				esc_html__(
2803
+					'Unable to continue with registering because there is no Event ID in the request',
2804
+					'event_espresso'
2805
+				)
2806
+			);
2807
+		}
2808
+		EE_Registry::instance()->REQ->set_espresso_page(true);
2809
+		// gotta start with a clean slate if we're not coming here via ajax
2810
+		if (! defined('DOING_AJAX')
2811
+			&& (! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2812
+		) {
2813
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2814
+		}
2815
+		$this->_template_args['event_name'] = '';
2816
+		// event name
2817
+		if ($this->_reg_event) {
2818
+			$this->_template_args['event_name'] = $this->_reg_event->name();
2819
+			$edit_event_url = self::add_query_args_and_nonce(
2820
+				array(
2821
+					'action' => 'edit',
2822
+					'post'   => $this->_reg_event->ID(),
2823
+				),
2824
+				EVENTS_ADMIN_URL
2825
+			);
2826
+			$edit_event_lnk = '<a href="'
2827
+							  . $edit_event_url
2828
+							  . '" title="'
2829
+							  . esc_attr__('Edit ', 'event_espresso')
2830
+							  . $this->_reg_event->name()
2831
+							  . '">'
2832
+							  . esc_html__('Edit Event', 'event_espresso')
2833
+							  . '</a>';
2834
+			$this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2835
+												   . $edit_event_lnk
2836
+												   . '</span>';
2837
+		}
2838
+		$this->_template_args['step_content'] = $this->_get_registration_step_content();
2839
+		if (defined('DOING_AJAX')) {
2840
+			$this->_return_json();
2841
+		}
2842
+		// grab header
2843
+		$template_path =
2844
+			REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2845
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2846
+			$template_path,
2847
+			$this->_template_args,
2848
+			true
2849
+		);
2850
+		// $this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2851
+		// the details template wrapper
2852
+		$this->display_admin_page_with_sidebar();
2853
+	}
2854
+
2855
+
2856
+	/**
2857
+	 * This returns the content for a registration step
2858
+	 *
2859
+	 * @access protected
2860
+	 * @return string html
2861
+	 * @throws DomainException
2862
+	 * @throws EE_Error
2863
+	 * @throws InvalidArgumentException
2864
+	 * @throws InvalidDataTypeException
2865
+	 * @throws InvalidInterfaceException
2866
+	 */
2867
+	protected function _get_registration_step_content()
2868
+	{
2869
+		if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
2870
+			$warning_msg = sprintf(
2871
+				esc_html__(
2872
+					'%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',
2873
+					'event_espresso'
2874
+				),
2875
+				'<br />',
2876
+				'<h3 class="important-notice">',
2877
+				'</h3>',
2878
+				'<div class="float-right">',
2879
+				'<span id="redirect_timer" class="important-notice">30</span>',
2880
+				'</div>',
2881
+				'<b>',
2882
+				'</b>'
2883
+			);
2884
+			return '
2885 2885
 	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg . '</p></div>
2886 2886
 	<script >
2887 2887
 		// WHOAH !!! it appears that someone is using the back button from the Transaction admin page
@@ -2894,868 +2894,868 @@  discard block
 block discarded – undo
2894 2894
 	        }
2895 2895
 	    }, 800 );
2896 2896
 	</script >';
2897
-        }
2898
-        $template_args = array(
2899
-            'title'                    => '',
2900
-            'content'                  => '',
2901
-            'step_button_text'         => '',
2902
-            'show_notification_toggle' => false,
2903
-        );
2904
-        // to indicate we're processing a new registration
2905
-        $hidden_fields = array(
2906
-            'processing_registration' => array(
2907
-                'type'  => 'hidden',
2908
-                'value' => 0,
2909
-            ),
2910
-            'event_id'                => array(
2911
-                'type'  => 'hidden',
2912
-                'value' => $this->_reg_event->ID(),
2913
-            ),
2914
-        );
2915
-        // if the cart is empty then we know we're at step one so we'll display ticket selector
2916
-        $cart = EE_Registry::instance()->SSN->cart();
2917
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
2918
-        switch ($step) {
2919
-            case 'ticket':
2920
-                $hidden_fields['processing_registration']['value'] = 1;
2921
-                $template_args['title'] = esc_html__(
2922
-                    'Step One: Select the Ticket for this registration',
2923
-                    'event_espresso'
2924
-                );
2925
-                $template_args['content'] =
2926
-                    EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
2927
-                $template_args['content'] .= '</div>';
2928
-                $template_args['step_button_text'] = esc_html__(
2929
-                    'Add Tickets and Continue to Registrant Details',
2930
-                    'event_espresso'
2931
-                );
2932
-                $template_args['show_notification_toggle'] = false;
2933
-                break;
2934
-            case 'questions':
2935
-                $hidden_fields['processing_registration']['value'] = 2;
2936
-                $template_args['title'] = esc_html__(
2937
-                    'Step Two: Add Registrant Details for this Registration',
2938
-                    'event_espresso'
2939
-                );
2940
-                // in theory we should be able to run EED_SPCO at this point because the cart should have been setup
2941
-                // properly by the first process_reg_step run.
2942
-                $template_args['content'] =
2943
-                    EED_Single_Page_Checkout::registration_checkout_for_admin();
2944
-                $template_args['step_button_text'] = esc_html__(
2945
-                    'Save Registration and Continue to Details',
2946
-                    'event_espresso'
2947
-                );
2948
-                $template_args['show_notification_toggle'] = true;
2949
-                break;
2950
-        }
2951
-        // we come back to the process_registration_step route.
2952
-        $this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
2953
-        return EEH_Template::display_template(
2954
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
2955
-            $template_args,
2956
-            true
2957
-        );
2958
-    }
2959
-
2960
-
2961
-    /**
2962
-     *        set_reg_event
2963
-     *
2964
-     * @access private
2965
-     * @return bool
2966
-     * @throws EE_Error
2967
-     * @throws InvalidArgumentException
2968
-     * @throws InvalidDataTypeException
2969
-     * @throws InvalidInterfaceException
2970
-     */
2971
-    private function _set_reg_event()
2972
-    {
2973
-        if (is_object($this->_reg_event)) {
2974
-            return true;
2975
-        }
2976
-        $EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
2977
-        if (! $EVT_ID) {
2978
-            return false;
2979
-        }
2980
-        $this->_reg_event = $this->getEventModel()->get_one_by_ID($EVT_ID);
2981
-        return true;
2982
-    }
2983
-
2984
-
2985
-    /**
2986
-     * process_reg_step
2987
-     *
2988
-     * @access        public
2989
-     * @return string
2990
-     * @throws DomainException
2991
-     * @throws EE_Error
2992
-     * @throws InvalidArgumentException
2993
-     * @throws InvalidDataTypeException
2994
-     * @throws InvalidInterfaceException
2995
-     * @throws ReflectionException
2996
-     * @throws RuntimeException
2997
-     */
2998
-    public function process_reg_step()
2999
-    {
3000
-        EE_System::do_not_cache();
3001
-        $this->_set_reg_event();
3002
-        EE_Registry::instance()->REQ->set_espresso_page(true);
3003
-        EE_Registry::instance()->REQ->set('uts', time());
3004
-        // what step are we on?
3005
-        $cart = EE_Registry::instance()->SSN->cart();
3006
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3007
-        // if doing ajax then we need to verify the nonce
3008
-        if (defined('DOING_AJAX')) {
3009
-            $nonce = isset($this->_req_data[ $this->_req_nonce ])
3010
-                ? sanitize_text_field($this->_req_data[ $this->_req_nonce ]) : '';
3011
-            $this->_verify_nonce($nonce, $this->_req_nonce);
3012
-        }
3013
-        switch ($step) {
3014
-            case 'ticket':
3015
-                // process ticket selection
3016
-                $success = EED_Ticket_Selector::instance()->process_ticket_selections();
3017
-                if ($success) {
3018
-                    EE_Error::add_success(
3019
-                        esc_html__(
3020
-                            'Tickets Selected. Now complete the registration.',
3021
-                            'event_espresso'
3022
-                        )
3023
-                    );
3024
-                } else {
3025
-                    $query_args['step_error'] = $this->_req_data['step_error'] = true;
3026
-                }
3027
-                if (defined('DOING_AJAX')) {
3028
-                    $this->new_registration(); // display next step
3029
-                } else {
3030
-                    $query_args = array(
3031
-                        'action'                  => 'new_registration',
3032
-                        'processing_registration' => 1,
3033
-                        'event_id'                => $this->_reg_event->ID(),
3034
-                        'uts'                     => time(),
3035
-                    );
3036
-                    $this->_redirect_after_action(
3037
-                        false,
3038
-                        '',
3039
-                        '',
3040
-                        $query_args,
3041
-                        true
3042
-                    );
3043
-                }
3044
-                break;
3045
-            case 'questions':
3046
-                if (! isset(
3047
-                    $this->_req_data['txn_reg_status_change'],
3048
-                    $this->_req_data['txn_reg_status_change']['send_notifications']
3049
-                )
3050
-                ) {
3051
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
3052
-                }
3053
-                // process registration
3054
-                $transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
3055
-                if ($cart instanceof EE_Cart) {
3056
-                    $grand_total = $cart->get_cart_grand_total();
3057
-                    if ($grand_total instanceof EE_Line_Item) {
3058
-                        $grand_total->save_this_and_descendants_to_txn();
3059
-                    }
3060
-                }
3061
-                if (! $transaction instanceof EE_Transaction) {
3062
-                    $query_args = array(
3063
-                        'action'                  => 'new_registration',
3064
-                        'processing_registration' => 2,
3065
-                        'event_id'                => $this->_reg_event->ID(),
3066
-                        'uts'                     => time(),
3067
-                    );
3068
-                    if (defined('DOING_AJAX')) {
3069
-                        // display registration form again because there are errors (maybe validation?)
3070
-                        $this->new_registration();
3071
-                        return;
3072
-                    }
3073
-                    $this->_redirect_after_action(
3074
-                        false,
3075
-                        '',
3076
-                        '',
3077
-                        $query_args,
3078
-                        true
3079
-                    );
3080
-                    return;
3081
-                }
3082
-                // maybe update status, and make sure to save transaction if not done already
3083
-                if (! $transaction->update_status_based_on_total_paid()) {
3084
-                    $transaction->save();
3085
-                }
3086
-                EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3087
-                $this->_req_data = array();
3088
-                $query_args = array(
3089
-                    'action'        => 'redirect_to_txn',
3090
-                    'TXN_ID'        => $transaction->ID(),
3091
-                    'EVT_ID'        => $this->_reg_event->ID(),
3092
-                    'event_name'    => urlencode($this->_reg_event->name()),
3093
-                    'redirect_from' => 'new_registration',
3094
-                );
3095
-                $this->_redirect_after_action(false, '', '', $query_args, true);
3096
-                break;
3097
-        }
3098
-        // what are you looking here for?  Should be nothing to do at this point.
3099
-    }
3100
-
3101
-
3102
-    /**
3103
-     * redirect_to_txn
3104
-     *
3105
-     * @access public
3106
-     * @return void
3107
-     * @throws EE_Error
3108
-     * @throws InvalidArgumentException
3109
-     * @throws InvalidDataTypeException
3110
-     * @throws InvalidInterfaceException
3111
-     * @throws ReflectionException
3112
-     */
3113
-    public function redirect_to_txn()
3114
-    {
3115
-        EE_System::do_not_cache();
3116
-        EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3117
-        $query_args = array(
3118
-            'action' => 'view_transaction',
3119
-            'TXN_ID' => isset($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : 0,
3120
-            'page'   => 'espresso_transactions',
3121
-        );
3122
-        if (isset($this->_req_data['EVT_ID'], $this->_req_data['redirect_from'])) {
3123
-            $query_args['EVT_ID'] = $this->_req_data['EVT_ID'];
3124
-            $query_args['event_name'] = urlencode($this->_req_data['event_name']);
3125
-            $query_args['redirect_from'] = $this->_req_data['redirect_from'];
3126
-        }
3127
-        EE_Error::add_success(
3128
-            esc_html__(
3129
-                'Registration Created.  Please review the transaction and add any payments as necessary',
3130
-                'event_espresso'
3131
-            )
3132
-        );
3133
-        $this->_redirect_after_action(false, '', '', $query_args, true);
3134
-    }
3135
-
3136
-
3137
-    /**
3138
-     *        generates HTML for the Attendee Contact List
3139
-     *
3140
-     * @access protected
3141
-     * @return void
3142
-     * @throws DomainException
3143
-     * @throws EE_Error
3144
-     */
3145
-    protected function _attendee_contact_list_table()
3146
-    {
3147
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3148
-        $this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
3149
-        $this->display_admin_list_table_page_with_no_sidebar();
3150
-    }
3151
-
3152
-
3153
-    /**
3154
-     *        get_attendees
3155
-     *
3156
-     * @param      $per_page
3157
-     * @param bool $count whether to return count or data.
3158
-     * @param bool $trash
3159
-     * @return array
3160
-     * @throws EE_Error
3161
-     * @throws InvalidArgumentException
3162
-     * @throws InvalidDataTypeException
3163
-     * @throws InvalidInterfaceException
3164
-     * @access public
3165
-     */
3166
-    public function get_attendees($per_page, $count = false, $trash = false)
3167
-    {
3168
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3169
-        require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3170
-        $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
3171
-        switch ($this->_req_data['orderby']) {
3172
-            case 'ATT_ID':
3173
-                $orderby = 'ATT_ID';
3174
-                break;
3175
-            case 'ATT_fname':
3176
-                $orderby = 'ATT_fname';
3177
-                break;
3178
-            case 'ATT_email':
3179
-                $orderby = 'ATT_email';
3180
-                break;
3181
-            case 'ATT_city':
3182
-                $orderby = 'ATT_city';
3183
-                break;
3184
-            case 'STA_ID':
3185
-                $orderby = 'STA_ID';
3186
-                break;
3187
-            case 'CNT_ID':
3188
-                $orderby = 'CNT_ID';
3189
-                break;
3190
-            case 'Registration_Count':
3191
-                $orderby = 'Registration_Count';
3192
-                break;
3193
-            default:
3194
-                $orderby = 'ATT_lname';
3195
-        }
3196
-        $sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
3197
-            ? $this->_req_data['order']
3198
-            : 'ASC';
3199
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
3200
-            ? $this->_req_data['paged']
3201
-            : 1;
3202
-        $per_page = isset($per_page) && ! empty($per_page) ? $per_page : 10;
3203
-        $per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
3204
-            ? $this->_req_data['perpage']
3205
-            : $per_page;
3206
-        $_where = array();
3207
-        if (! empty($this->_req_data['s'])) {
3208
-            $sstr = '%' . $this->_req_data['s'] . '%';
3209
-            $_where['OR'] = array(
3210
-                'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3211
-                'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
3212
-                'Registration.Event.EVT_short_desc' => array('LIKE', $sstr),
3213
-                'ATT_fname'                         => array('LIKE', $sstr),
3214
-                'ATT_lname'                         => array('LIKE', $sstr),
3215
-                'ATT_short_bio'                     => array('LIKE', $sstr),
3216
-                'ATT_email'                         => array('LIKE', $sstr),
3217
-                'ATT_address'                       => array('LIKE', $sstr),
3218
-                'ATT_address2'                      => array('LIKE', $sstr),
3219
-                'ATT_city'                          => array('LIKE', $sstr),
3220
-                'Country.CNT_name'                  => array('LIKE', $sstr),
3221
-                'State.STA_name'                    => array('LIKE', $sstr),
3222
-                'ATT_phone'                         => array('LIKE', $sstr),
3223
-                'Registration.REG_final_price'      => array('LIKE', $sstr),
3224
-                'Registration.REG_code'             => array('LIKE', $sstr),
3225
-                'Registration.REG_group_size'       => array('LIKE', $sstr),
3226
-            );
3227
-        }
3228
-        $offset = ($current_page - 1) * $per_page;
3229
-        $limit = $count ? null : array($offset, $per_page);
3230
-        $query_args = array(
3231
-            $_where,
3232
-            'extra_selects' => array('Registration_Count' => array('Registration.REG_ID', 'count', '%d')),
3233
-            'limit'         => $limit,
3234
-        );
3235
-        if (! $count) {
3236
-            $query_args['order_by'] = array($orderby => $sort);
3237
-        }
3238
-        if ($trash) {
3239
-            $query_args[0]['status'] = array('!=', 'publish');
3240
-            $all_attendees = $count
3241
-                ? $this->getAttendeeModel()->count($query_args, 'ATT_ID', true)
3242
-                : $this->getAttendeeModel()->get_all($query_args);
3243
-        } else {
3244
-            $query_args[0]['status'] = array('IN', array('publish'));
3245
-            $all_attendees = $count
3246
-                ? $this->getAttendeeModel()->count($query_args, 'ATT_ID', true)
3247
-                : $this->getAttendeeModel()->get_all($query_args);
3248
-        }
3249
-        return $all_attendees;
3250
-    }
3251
-
3252
-
3253
-    /**
3254
-     * This is just taking care of resending the registration confirmation
3255
-     *
3256
-     * @access protected
3257
-     * @return void
3258
-     * @throws EE_Error
3259
-     * @throws InvalidArgumentException
3260
-     * @throws InvalidDataTypeException
3261
-     * @throws InvalidInterfaceException
3262
-     * @throws ReflectionException
3263
-     */
3264
-    protected function _resend_registration()
3265
-    {
3266
-        $this->_process_resend_registration();
3267
-        $query_args = isset($this->_req_data['redirect_to'])
3268
-            ? array('action' => $this->_req_data['redirect_to'], '_REG_ID' => $this->_req_data['_REG_ID'])
3269
-            : array('action' => 'default');
3270
-        $this->_redirect_after_action(false, '', '', $query_args, true);
3271
-    }
3272
-
3273
-    /**
3274
-     * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3275
-     * to use when selecting registrations
3276
-     *
3277
-     * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3278
-     *                                                     the query parameters from the request
3279
-     * @return void ends the request with a redirect or download
3280
-     */
3281
-    public function _registrations_report_base($method_name_for_getting_query_params)
3282
-    {
3283
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3284
-            wp_redirect(
3285
-                EE_Admin_Page::add_query_args_and_nonce(
3286
-                    array(
3287
-                        'page'        => 'espresso_batch',
3288
-                        'batch'       => 'file',
3289
-                        'EVT_ID'      => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3290
-                        'filters'     => urlencode(
3291
-                            serialize(
3292
-                                $this->$method_name_for_getting_query_params(
3293
-                                    EEH_Array::is_set(
3294
-                                        $this->_req_data,
3295
-                                        'filters',
3296
-                                        array()
3297
-                                    )
3298
-                                )
3299
-                            )
3300
-                        ),
3301
-                        'use_filters' => EEH_Array::is_set($this->_req_data, 'use_filters', false),
3302
-                        'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\RegistrationsReport'),
3303
-                        'return_url'  => urlencode($this->_req_data['return_url']),
3304
-                    )
3305
-                )
3306
-            );
3307
-        } else {
3308
-            $new_request_args = array(
3309
-                'export' => 'report',
3310
-                'action' => 'registrations_report_for_event',
3311
-                'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3312
-            );
3313
-            $this->_req_data = array_merge($this->_req_data, $new_request_args);
3314
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3315
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3316
-                $EE_Export = EE_Export::instance($this->_req_data);
3317
-                $EE_Export->export();
3318
-            }
3319
-        }
3320
-    }
3321
-
3322
-
3323
-    /**
3324
-     * Creates a registration report using only query parameters in the request
3325
-     *
3326
-     * @return void
3327
-     */
3328
-    public function _registrations_report()
3329
-    {
3330
-        $this->_registrations_report_base('_get_registration_query_parameters');
3331
-    }
3332
-
3333
-
3334
-    public function _contact_list_export()
3335
-    {
3336
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3337
-            require_once(EE_CLASSES . 'EE_Export.class.php');
3338
-            $EE_Export = EE_Export::instance($this->_req_data);
3339
-            $EE_Export->export_attendees();
3340
-        }
3341
-    }
3342
-
3343
-
3344
-    public function _contact_list_report()
3345
-    {
3346
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3347
-            wp_redirect(
3348
-                EE_Admin_Page::add_query_args_and_nonce(
3349
-                    array(
3350
-                        'page'        => 'espresso_batch',
3351
-                        'batch'       => 'file',
3352
-                        'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\AttendeesReport'),
3353
-                        'return_url'  => urlencode($this->_req_data['return_url']),
3354
-                    )
3355
-                )
3356
-            );
3357
-        } else {
3358
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3359
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3360
-                $EE_Export = EE_Export::instance($this->_req_data);
3361
-                $EE_Export->report_attendees();
3362
-            }
3363
-        }
3364
-    }
3365
-
3366
-
3367
-
3368
-
3369
-
3370
-    /***************************************        ATTENDEE DETAILS        ***************************************/
3371
-    /**
3372
-     * This duplicates the attendee object for the given incoming registration id and attendee_id.
3373
-     *
3374
-     * @return void
3375
-     * @throws EE_Error
3376
-     * @throws InvalidArgumentException
3377
-     * @throws InvalidDataTypeException
3378
-     * @throws InvalidInterfaceException
3379
-     * @throws ReflectionException
3380
-     */
3381
-    protected function _duplicate_attendee()
3382
-    {
3383
-        $action = ! empty($this->_req_data['return']) ? $this->_req_data['return'] : 'default';
3384
-        // verify we have necessary info
3385
-        if (empty($this->_req_data['_REG_ID'])) {
3386
-            EE_Error::add_error(
3387
-                esc_html__(
3388
-                    'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3389
-                    'event_espresso'
3390
-                ),
3391
-                __FILE__,
3392
-                __LINE__,
3393
-                __FUNCTION__
3394
-            );
3395
-            $query_args = array('action' => $action);
3396
-            $this->_redirect_after_action('', '', '', $query_args, true);
3397
-        }
3398
-        // okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3399
-        $registration = $this->getRegistrationModel()->get_one_by_ID($this->_req_data['_REG_ID']);
3400
-        $attendee = $registration->attendee();
3401
-        // remove relation of existing attendee on registration
3402
-        $registration->_remove_relation_to($attendee, 'Attendee');
3403
-        // new attendee
3404
-        $new_attendee = clone $attendee;
3405
-        $new_attendee->set('ATT_ID', 0);
3406
-        $new_attendee->save();
3407
-        // add new attendee to reg
3408
-        $registration->_add_relation_to($new_attendee, 'Attendee');
3409
-        EE_Error::add_success(
3410
-            esc_html__(
3411
-                'New Contact record created.  Now make any edits you wish to make for this contact.',
3412
-                'event_espresso'
3413
-            )
3414
-        );
3415
-        // redirect to edit page for attendee
3416
-        $query_args = array('post' => $new_attendee->ID(), 'action' => 'edit_attendee');
3417
-        $this->_redirect_after_action('', '', '', $query_args, true);
3418
-    }
3419
-
3420
-
3421
-    /**
3422
-     * Callback invoked by parent EE_Admin_CPT class hooked in on `save_post` wp hook.
3423
-     *
3424
-     * @param int     $post_id
3425
-     * @param WP_POST $post
3426
-     * @throws DomainException
3427
-     * @throws EE_Error
3428
-     * @throws InvalidArgumentException
3429
-     * @throws InvalidDataTypeException
3430
-     * @throws InvalidInterfaceException
3431
-     * @throws LogicException
3432
-     * @throws InvalidFormSubmissionException
3433
-     * @throws ReflectionException
3434
-     */
3435
-    protected function _insert_update_cpt_item($post_id, $post)
3436
-    {
3437
-        $success = true;
3438
-        $attendee = $post instanceof WP_Post && $post->post_type === 'espresso_attendees'
3439
-            ? $this->getAttendeeModel()->get_one_by_ID($post_id)
3440
-            : null;
3441
-        // for attendee updates
3442
-        if ($attendee instanceof EE_Attendee) {
3443
-            // note we should only be UPDATING attendees at this point.
3444
-            $updated_fields = array(
3445
-                'ATT_fname'     => $this->_req_data['ATT_fname'],
3446
-                'ATT_lname'     => $this->_req_data['ATT_lname'],
3447
-                'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3448
-                'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3449
-                'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3450
-                'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
3451
-                'STA_ID'        => isset($this->_req_data['STA_ID']) ? $this->_req_data['STA_ID'] : '',
3452
-                'CNT_ISO'       => isset($this->_req_data['CNT_ISO']) ? $this->_req_data['CNT_ISO'] : '',
3453
-                'ATT_zip'       => isset($this->_req_data['ATT_zip']) ? $this->_req_data['ATT_zip'] : '',
3454
-            );
3455
-            foreach ($updated_fields as $field => $value) {
3456
-                $attendee->set($field, $value);
3457
-            }
3458
-
3459
-            // process contact details metabox form handler (which will also save the attendee)
3460
-            $contact_details_form = $this->getAttendeeContactDetailsMetaboxFormHandler($attendee);
3461
-            $success = $contact_details_form->process($this->_req_data);
3462
-
3463
-            $attendee_update_callbacks = apply_filters(
3464
-                'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3465
-                array()
3466
-            );
3467
-            foreach ($attendee_update_callbacks as $a_callback) {
3468
-                if (false === call_user_func_array($a_callback, array($attendee, $this->_req_data))) {
3469
-                    throw new EE_Error(
3470
-                        sprintf(
3471
-                            esc_html__(
3472
-                                '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.',
3473
-                                'event_espresso'
3474
-                            ),
3475
-                            $a_callback
3476
-                        )
3477
-                    );
3478
-                }
3479
-            }
3480
-        }
3481
-
3482
-        if ($success === false) {
3483
-            EE_Error::add_error(
3484
-                esc_html__(
3485
-                    'Something went wrong with updating the meta table data for the registration.',
3486
-                    'event_espresso'
3487
-                ),
3488
-                __FILE__,
3489
-                __FUNCTION__,
3490
-                __LINE__
3491
-            );
3492
-        }
3493
-    }
3494
-
3495
-
3496
-    public function trash_cpt_item($post_id)
3497
-    {
3498
-    }
3499
-
3500
-
3501
-    public function delete_cpt_item($post_id)
3502
-    {
3503
-    }
3504
-
3505
-
3506
-    public function restore_cpt_item($post_id)
3507
-    {
3508
-    }
3509
-
3510
-
3511
-    protected function _restore_cpt_item($post_id, $revision_id)
3512
-    {
3513
-    }
3514
-
3515
-
3516
-    /**
3517
-     * @throws EE_Error
3518
-     * @since 4.10.2.p
3519
-     */
3520
-    public function attendee_editor_metaboxes()
3521
-    {
3522
-        $this->verify_cpt_object();
3523
-        remove_meta_box(
3524
-            'postexcerpt',
3525
-            $this->_cpt_routes[ $this->_req_action ],
3526
-            'normal'
3527
-        );
3528
-        remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal', 'core');
3529
-        if (post_type_supports('espresso_attendees', 'excerpt')) {
3530
-            add_meta_box(
3531
-                'postexcerpt',
3532
-                esc_html__('Short Biography', 'event_espresso'),
3533
-                'post_excerpt_meta_box',
3534
-                $this->_cpt_routes[ $this->_req_action ],
3535
-                'normal'
3536
-            );
3537
-        }
3538
-        if (post_type_supports('espresso_attendees', 'comments')) {
3539
-            add_meta_box(
3540
-                'commentsdiv',
3541
-                esc_html__('Notes on the Contact', 'event_espresso'),
3542
-                'post_comment_meta_box',
3543
-                $this->_cpt_routes[ $this->_req_action ],
3544
-                'normal',
3545
-                'core'
3546
-            );
3547
-        }
3548
-        add_meta_box(
3549
-            'attendee_contact_info',
3550
-            esc_html__('Contact Info', 'event_espresso'),
3551
-            array($this, 'attendee_contact_info'),
3552
-            $this->_cpt_routes[ $this->_req_action ],
3553
-            'side',
3554
-            'core'
3555
-        );
3556
-        add_meta_box(
3557
-            'attendee_details_address',
3558
-            esc_html__('Address Details', 'event_espresso'),
3559
-            array($this, 'attendee_address_details'),
3560
-            $this->_cpt_routes[ $this->_req_action ],
3561
-            'normal',
3562
-            'core'
3563
-        );
3564
-        add_meta_box(
3565
-            'attendee_registrations',
3566
-            esc_html__('Registrations for this Contact', 'event_espresso'),
3567
-            array($this, 'attendee_registrations_meta_box'),
3568
-            $this->_cpt_routes[ $this->_req_action ],
3569
-            'normal',
3570
-            'high'
3571
-        );
3572
-    }
3573
-
3574
-
3575
-    /**
3576
-     * Metabox for attendee contact info
3577
-     *
3578
-     * @param  WP_Post $post wp post object
3579
-     * @return string attendee contact info ( and form )
3580
-     * @throws EE_Error
3581
-     * @throws InvalidArgumentException
3582
-     * @throws InvalidDataTypeException
3583
-     * @throws InvalidInterfaceException
3584
-     * @throws LogicException
3585
-     * @throws DomainException
3586
-     */
3587
-    public function attendee_contact_info($post)
3588
-    {
3589
-        // get attendee object ( should already have it )
3590
-        $form = $this->getAttendeeContactDetailsMetaboxFormHandler($this->_cpt_model_obj);
3591
-        $form->enqueueStylesAndScripts();
3592
-        echo $form->display();
3593
-    }
3594
-
3595
-
3596
-    /**
3597
-     * Return form handler for the contact details metabox
3598
-     *
3599
-     * @param EE_Attendee $attendee
3600
-     * @return AttendeeContactDetailsMetaboxFormHandler
3601
-     * @throws DomainException
3602
-     * @throws InvalidArgumentException
3603
-     * @throws InvalidDataTypeException
3604
-     * @throws InvalidInterfaceException
3605
-     */
3606
-    protected function getAttendeeContactDetailsMetaboxFormHandler(EE_Attendee $attendee)
3607
-    {
3608
-        return new AttendeeContactDetailsMetaboxFormHandler($attendee, EE_Registry::instance());
3609
-    }
3610
-
3611
-
3612
-    /**
3613
-     * Metabox for attendee details
3614
-     *
3615
-     * @param  WP_Post $post wp post object
3616
-     * @throws DomainException
3617
-     */
3618
-    public function attendee_address_details($post)
3619
-    {
3620
-        // get attendee object (should already have it)
3621
-        $this->_template_args['attendee'] = $this->_cpt_model_obj;
3622
-        $this->_template_args['state_html'] = EEH_Form_Fields::generate_form_input(
3623
-            new EE_Question_Form_Input(
3624
-                EE_Question::new_instance(
3625
-                    array(
3626
-                        'QST_ID'           => 0,
3627
-                        'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3628
-                        'QST_system'       => 'admin-state',
3629
-                    )
3630
-                ),
3631
-                EE_Answer::new_instance(
3632
-                    array(
3633
-                        'ANS_ID'    => 0,
3634
-                        'ANS_value' => $this->_cpt_model_obj->state_ID(),
3635
-                    )
3636
-                ),
3637
-                array(
3638
-                    'input_id'       => 'STA_ID',
3639
-                    'input_name'     => 'STA_ID',
3640
-                    'input_prefix'   => '',
3641
-                    'append_qstn_id' => false,
3642
-                )
3643
-            )
3644
-        );
3645
-        $this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3646
-            new EE_Question_Form_Input(
3647
-                EE_Question::new_instance(
3648
-                    array(
3649
-                        'QST_ID'           => 0,
3650
-                        'QST_display_text' => esc_html__('Country', 'event_espresso'),
3651
-                        'QST_system'       => 'admin-country',
3652
-                    )
3653
-                ),
3654
-                EE_Answer::new_instance(
3655
-                    array(
3656
-                        'ANS_ID'    => 0,
3657
-                        'ANS_value' => $this->_cpt_model_obj->country_ID(),
3658
-                    )
3659
-                ),
3660
-                array(
3661
-                    'input_id'       => 'CNT_ISO',
3662
-                    'input_name'     => 'CNT_ISO',
3663
-                    'input_prefix'   => '',
3664
-                    'append_qstn_id' => false,
3665
-                )
3666
-            )
3667
-        );
3668
-        $template =
3669
-            REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3670
-        EEH_Template::display_template($template, $this->_template_args);
3671
-    }
3672
-
3673
-
3674
-    /**
3675
-     *        _attendee_details
3676
-     *
3677
-     * @access protected
3678
-     * @param $post
3679
-     * @return void
3680
-     * @throws DomainException
3681
-     * @throws EE_Error
3682
-     * @throws InvalidArgumentException
3683
-     * @throws InvalidDataTypeException
3684
-     * @throws InvalidInterfaceException
3685
-     * @throws ReflectionException
3686
-     */
3687
-    public function attendee_registrations_meta_box($post)
3688
-    {
3689
-        $this->_template_args['attendee'] = $this->_cpt_model_obj;
3690
-        $this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3691
-        $template =
3692
-            REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3693
-        EEH_Template::display_template($template, $this->_template_args);
3694
-    }
3695
-
3696
-
3697
-    /**
3698
-     * add in the form fields for the attendee edit
3699
-     *
3700
-     * @param  WP_Post $post wp post object
3701
-     * @return string html for new form.
3702
-     * @throws DomainException
3703
-     */
3704
-    public function after_title_form_fields($post)
3705
-    {
3706
-        if ($post->post_type === 'espresso_attendees') {
3707
-            $template = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3708
-            $template_args['attendee'] = $this->_cpt_model_obj;
3709
-            EEH_Template::display_template($template, $template_args);
3710
-        }
3711
-    }
3712
-
3713
-
3714
-    /**
3715
-     *        _trash_or_restore_attendee
3716
-     *
3717
-     * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3718
-     * @return void
3719
-     * @throws EE_Error
3720
-     * @throws InvalidArgumentException
3721
-     * @throws InvalidDataTypeException
3722
-     * @throws InvalidInterfaceException
3723
-     * @throws ReflectionException
3724
-     * @access protected
3725
-     */
3726
-    protected function _trash_or_restore_attendees($trash = true)
3727
-    {
3728
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3729
-        $success = 1;
3730
-        // Checkboxes
3731
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3732
-            // if array has more than one element than success message should be plural
3733
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3734
-            // cycle thru checkboxes
3735
-            foreach ($this->_req_data['checkbox'] as $ATT_ID) {
3736
-                $updated = $trash ? $this->getAttendeeModel()->update_by_ID(array('status' => 'trash'), $ATT_ID)
3737
-                    : $this->getAttendeeModel()->update_by_ID(array('status' => 'publish'), $ATT_ID);
3738
-                if (! $updated) {
3739
-                    $success = 0;
3740
-                }
3741
-            }
3742
-        } else {
3743
-            // grab single id and delete
3744
-            $ATT_ID = absint($this->_req_data['ATT_ID']);
3745
-            // get attendee
3746
-            $att = $this->getAttendeeModel()->get_one_by_ID($ATT_ID);
3747
-            $updated = $trash ? $att->set_status('trash') : $att->set_status('publish');
3748
-            $updated = $att->save() && $updated;
3749
-            if (! $updated) {
3750
-                $success = 0;
3751
-            }
3752
-        }
3753
-        $what = $success > 1
3754
-            ? esc_html__('Contacts', 'event_espresso')
3755
-            : esc_html__('Contact', 'event_espresso');
3756
-        $action_desc = $trash
3757
-            ? esc_html__('moved to the trash', 'event_espresso')
3758
-            : esc_html__('restored', 'event_espresso');
3759
-        $this->_redirect_after_action($success, $what, $action_desc, array('action' => 'contact_list'));
3760
-    }
2897
+		}
2898
+		$template_args = array(
2899
+			'title'                    => '',
2900
+			'content'                  => '',
2901
+			'step_button_text'         => '',
2902
+			'show_notification_toggle' => false,
2903
+		);
2904
+		// to indicate we're processing a new registration
2905
+		$hidden_fields = array(
2906
+			'processing_registration' => array(
2907
+				'type'  => 'hidden',
2908
+				'value' => 0,
2909
+			),
2910
+			'event_id'                => array(
2911
+				'type'  => 'hidden',
2912
+				'value' => $this->_reg_event->ID(),
2913
+			),
2914
+		);
2915
+		// if the cart is empty then we know we're at step one so we'll display ticket selector
2916
+		$cart = EE_Registry::instance()->SSN->cart();
2917
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
2918
+		switch ($step) {
2919
+			case 'ticket':
2920
+				$hidden_fields['processing_registration']['value'] = 1;
2921
+				$template_args['title'] = esc_html__(
2922
+					'Step One: Select the Ticket for this registration',
2923
+					'event_espresso'
2924
+				);
2925
+				$template_args['content'] =
2926
+					EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
2927
+				$template_args['content'] .= '</div>';
2928
+				$template_args['step_button_text'] = esc_html__(
2929
+					'Add Tickets and Continue to Registrant Details',
2930
+					'event_espresso'
2931
+				);
2932
+				$template_args['show_notification_toggle'] = false;
2933
+				break;
2934
+			case 'questions':
2935
+				$hidden_fields['processing_registration']['value'] = 2;
2936
+				$template_args['title'] = esc_html__(
2937
+					'Step Two: Add Registrant Details for this Registration',
2938
+					'event_espresso'
2939
+				);
2940
+				// in theory we should be able to run EED_SPCO at this point because the cart should have been setup
2941
+				// properly by the first process_reg_step run.
2942
+				$template_args['content'] =
2943
+					EED_Single_Page_Checkout::registration_checkout_for_admin();
2944
+				$template_args['step_button_text'] = esc_html__(
2945
+					'Save Registration and Continue to Details',
2946
+					'event_espresso'
2947
+				);
2948
+				$template_args['show_notification_toggle'] = true;
2949
+				break;
2950
+		}
2951
+		// we come back to the process_registration_step route.
2952
+		$this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
2953
+		return EEH_Template::display_template(
2954
+			REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
2955
+			$template_args,
2956
+			true
2957
+		);
2958
+	}
2959
+
2960
+
2961
+	/**
2962
+	 *        set_reg_event
2963
+	 *
2964
+	 * @access private
2965
+	 * @return bool
2966
+	 * @throws EE_Error
2967
+	 * @throws InvalidArgumentException
2968
+	 * @throws InvalidDataTypeException
2969
+	 * @throws InvalidInterfaceException
2970
+	 */
2971
+	private function _set_reg_event()
2972
+	{
2973
+		if (is_object($this->_reg_event)) {
2974
+			return true;
2975
+		}
2976
+		$EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
2977
+		if (! $EVT_ID) {
2978
+			return false;
2979
+		}
2980
+		$this->_reg_event = $this->getEventModel()->get_one_by_ID($EVT_ID);
2981
+		return true;
2982
+	}
2983
+
2984
+
2985
+	/**
2986
+	 * process_reg_step
2987
+	 *
2988
+	 * @access        public
2989
+	 * @return string
2990
+	 * @throws DomainException
2991
+	 * @throws EE_Error
2992
+	 * @throws InvalidArgumentException
2993
+	 * @throws InvalidDataTypeException
2994
+	 * @throws InvalidInterfaceException
2995
+	 * @throws ReflectionException
2996
+	 * @throws RuntimeException
2997
+	 */
2998
+	public function process_reg_step()
2999
+	{
3000
+		EE_System::do_not_cache();
3001
+		$this->_set_reg_event();
3002
+		EE_Registry::instance()->REQ->set_espresso_page(true);
3003
+		EE_Registry::instance()->REQ->set('uts', time());
3004
+		// what step are we on?
3005
+		$cart = EE_Registry::instance()->SSN->cart();
3006
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3007
+		// if doing ajax then we need to verify the nonce
3008
+		if (defined('DOING_AJAX')) {
3009
+			$nonce = isset($this->_req_data[ $this->_req_nonce ])
3010
+				? sanitize_text_field($this->_req_data[ $this->_req_nonce ]) : '';
3011
+			$this->_verify_nonce($nonce, $this->_req_nonce);
3012
+		}
3013
+		switch ($step) {
3014
+			case 'ticket':
3015
+				// process ticket selection
3016
+				$success = EED_Ticket_Selector::instance()->process_ticket_selections();
3017
+				if ($success) {
3018
+					EE_Error::add_success(
3019
+						esc_html__(
3020
+							'Tickets Selected. Now complete the registration.',
3021
+							'event_espresso'
3022
+						)
3023
+					);
3024
+				} else {
3025
+					$query_args['step_error'] = $this->_req_data['step_error'] = true;
3026
+				}
3027
+				if (defined('DOING_AJAX')) {
3028
+					$this->new_registration(); // display next step
3029
+				} else {
3030
+					$query_args = array(
3031
+						'action'                  => 'new_registration',
3032
+						'processing_registration' => 1,
3033
+						'event_id'                => $this->_reg_event->ID(),
3034
+						'uts'                     => time(),
3035
+					);
3036
+					$this->_redirect_after_action(
3037
+						false,
3038
+						'',
3039
+						'',
3040
+						$query_args,
3041
+						true
3042
+					);
3043
+				}
3044
+				break;
3045
+			case 'questions':
3046
+				if (! isset(
3047
+					$this->_req_data['txn_reg_status_change'],
3048
+					$this->_req_data['txn_reg_status_change']['send_notifications']
3049
+				)
3050
+				) {
3051
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
3052
+				}
3053
+				// process registration
3054
+				$transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
3055
+				if ($cart instanceof EE_Cart) {
3056
+					$grand_total = $cart->get_cart_grand_total();
3057
+					if ($grand_total instanceof EE_Line_Item) {
3058
+						$grand_total->save_this_and_descendants_to_txn();
3059
+					}
3060
+				}
3061
+				if (! $transaction instanceof EE_Transaction) {
3062
+					$query_args = array(
3063
+						'action'                  => 'new_registration',
3064
+						'processing_registration' => 2,
3065
+						'event_id'                => $this->_reg_event->ID(),
3066
+						'uts'                     => time(),
3067
+					);
3068
+					if (defined('DOING_AJAX')) {
3069
+						// display registration form again because there are errors (maybe validation?)
3070
+						$this->new_registration();
3071
+						return;
3072
+					}
3073
+					$this->_redirect_after_action(
3074
+						false,
3075
+						'',
3076
+						'',
3077
+						$query_args,
3078
+						true
3079
+					);
3080
+					return;
3081
+				}
3082
+				// maybe update status, and make sure to save transaction if not done already
3083
+				if (! $transaction->update_status_based_on_total_paid()) {
3084
+					$transaction->save();
3085
+				}
3086
+				EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3087
+				$this->_req_data = array();
3088
+				$query_args = array(
3089
+					'action'        => 'redirect_to_txn',
3090
+					'TXN_ID'        => $transaction->ID(),
3091
+					'EVT_ID'        => $this->_reg_event->ID(),
3092
+					'event_name'    => urlencode($this->_reg_event->name()),
3093
+					'redirect_from' => 'new_registration',
3094
+				);
3095
+				$this->_redirect_after_action(false, '', '', $query_args, true);
3096
+				break;
3097
+		}
3098
+		// what are you looking here for?  Should be nothing to do at this point.
3099
+	}
3100
+
3101
+
3102
+	/**
3103
+	 * redirect_to_txn
3104
+	 *
3105
+	 * @access public
3106
+	 * @return void
3107
+	 * @throws EE_Error
3108
+	 * @throws InvalidArgumentException
3109
+	 * @throws InvalidDataTypeException
3110
+	 * @throws InvalidInterfaceException
3111
+	 * @throws ReflectionException
3112
+	 */
3113
+	public function redirect_to_txn()
3114
+	{
3115
+		EE_System::do_not_cache();
3116
+		EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3117
+		$query_args = array(
3118
+			'action' => 'view_transaction',
3119
+			'TXN_ID' => isset($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : 0,
3120
+			'page'   => 'espresso_transactions',
3121
+		);
3122
+		if (isset($this->_req_data['EVT_ID'], $this->_req_data['redirect_from'])) {
3123
+			$query_args['EVT_ID'] = $this->_req_data['EVT_ID'];
3124
+			$query_args['event_name'] = urlencode($this->_req_data['event_name']);
3125
+			$query_args['redirect_from'] = $this->_req_data['redirect_from'];
3126
+		}
3127
+		EE_Error::add_success(
3128
+			esc_html__(
3129
+				'Registration Created.  Please review the transaction and add any payments as necessary',
3130
+				'event_espresso'
3131
+			)
3132
+		);
3133
+		$this->_redirect_after_action(false, '', '', $query_args, true);
3134
+	}
3135
+
3136
+
3137
+	/**
3138
+	 *        generates HTML for the Attendee Contact List
3139
+	 *
3140
+	 * @access protected
3141
+	 * @return void
3142
+	 * @throws DomainException
3143
+	 * @throws EE_Error
3144
+	 */
3145
+	protected function _attendee_contact_list_table()
3146
+	{
3147
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3148
+		$this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
3149
+		$this->display_admin_list_table_page_with_no_sidebar();
3150
+	}
3151
+
3152
+
3153
+	/**
3154
+	 *        get_attendees
3155
+	 *
3156
+	 * @param      $per_page
3157
+	 * @param bool $count whether to return count or data.
3158
+	 * @param bool $trash
3159
+	 * @return array
3160
+	 * @throws EE_Error
3161
+	 * @throws InvalidArgumentException
3162
+	 * @throws InvalidDataTypeException
3163
+	 * @throws InvalidInterfaceException
3164
+	 * @access public
3165
+	 */
3166
+	public function get_attendees($per_page, $count = false, $trash = false)
3167
+	{
3168
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3169
+		require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3170
+		$this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
3171
+		switch ($this->_req_data['orderby']) {
3172
+			case 'ATT_ID':
3173
+				$orderby = 'ATT_ID';
3174
+				break;
3175
+			case 'ATT_fname':
3176
+				$orderby = 'ATT_fname';
3177
+				break;
3178
+			case 'ATT_email':
3179
+				$orderby = 'ATT_email';
3180
+				break;
3181
+			case 'ATT_city':
3182
+				$orderby = 'ATT_city';
3183
+				break;
3184
+			case 'STA_ID':
3185
+				$orderby = 'STA_ID';
3186
+				break;
3187
+			case 'CNT_ID':
3188
+				$orderby = 'CNT_ID';
3189
+				break;
3190
+			case 'Registration_Count':
3191
+				$orderby = 'Registration_Count';
3192
+				break;
3193
+			default:
3194
+				$orderby = 'ATT_lname';
3195
+		}
3196
+		$sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
3197
+			? $this->_req_data['order']
3198
+			: 'ASC';
3199
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
3200
+			? $this->_req_data['paged']
3201
+			: 1;
3202
+		$per_page = isset($per_page) && ! empty($per_page) ? $per_page : 10;
3203
+		$per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
3204
+			? $this->_req_data['perpage']
3205
+			: $per_page;
3206
+		$_where = array();
3207
+		if (! empty($this->_req_data['s'])) {
3208
+			$sstr = '%' . $this->_req_data['s'] . '%';
3209
+			$_where['OR'] = array(
3210
+				'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3211
+				'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
3212
+				'Registration.Event.EVT_short_desc' => array('LIKE', $sstr),
3213
+				'ATT_fname'                         => array('LIKE', $sstr),
3214
+				'ATT_lname'                         => array('LIKE', $sstr),
3215
+				'ATT_short_bio'                     => array('LIKE', $sstr),
3216
+				'ATT_email'                         => array('LIKE', $sstr),
3217
+				'ATT_address'                       => array('LIKE', $sstr),
3218
+				'ATT_address2'                      => array('LIKE', $sstr),
3219
+				'ATT_city'                          => array('LIKE', $sstr),
3220
+				'Country.CNT_name'                  => array('LIKE', $sstr),
3221
+				'State.STA_name'                    => array('LIKE', $sstr),
3222
+				'ATT_phone'                         => array('LIKE', $sstr),
3223
+				'Registration.REG_final_price'      => array('LIKE', $sstr),
3224
+				'Registration.REG_code'             => array('LIKE', $sstr),
3225
+				'Registration.REG_group_size'       => array('LIKE', $sstr),
3226
+			);
3227
+		}
3228
+		$offset = ($current_page - 1) * $per_page;
3229
+		$limit = $count ? null : array($offset, $per_page);
3230
+		$query_args = array(
3231
+			$_where,
3232
+			'extra_selects' => array('Registration_Count' => array('Registration.REG_ID', 'count', '%d')),
3233
+			'limit'         => $limit,
3234
+		);
3235
+		if (! $count) {
3236
+			$query_args['order_by'] = array($orderby => $sort);
3237
+		}
3238
+		if ($trash) {
3239
+			$query_args[0]['status'] = array('!=', 'publish');
3240
+			$all_attendees = $count
3241
+				? $this->getAttendeeModel()->count($query_args, 'ATT_ID', true)
3242
+				: $this->getAttendeeModel()->get_all($query_args);
3243
+		} else {
3244
+			$query_args[0]['status'] = array('IN', array('publish'));
3245
+			$all_attendees = $count
3246
+				? $this->getAttendeeModel()->count($query_args, 'ATT_ID', true)
3247
+				: $this->getAttendeeModel()->get_all($query_args);
3248
+		}
3249
+		return $all_attendees;
3250
+	}
3251
+
3252
+
3253
+	/**
3254
+	 * This is just taking care of resending the registration confirmation
3255
+	 *
3256
+	 * @access protected
3257
+	 * @return void
3258
+	 * @throws EE_Error
3259
+	 * @throws InvalidArgumentException
3260
+	 * @throws InvalidDataTypeException
3261
+	 * @throws InvalidInterfaceException
3262
+	 * @throws ReflectionException
3263
+	 */
3264
+	protected function _resend_registration()
3265
+	{
3266
+		$this->_process_resend_registration();
3267
+		$query_args = isset($this->_req_data['redirect_to'])
3268
+			? array('action' => $this->_req_data['redirect_to'], '_REG_ID' => $this->_req_data['_REG_ID'])
3269
+			: array('action' => 'default');
3270
+		$this->_redirect_after_action(false, '', '', $query_args, true);
3271
+	}
3272
+
3273
+	/**
3274
+	 * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3275
+	 * to use when selecting registrations
3276
+	 *
3277
+	 * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3278
+	 *                                                     the query parameters from the request
3279
+	 * @return void ends the request with a redirect or download
3280
+	 */
3281
+	public function _registrations_report_base($method_name_for_getting_query_params)
3282
+	{
3283
+		if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3284
+			wp_redirect(
3285
+				EE_Admin_Page::add_query_args_and_nonce(
3286
+					array(
3287
+						'page'        => 'espresso_batch',
3288
+						'batch'       => 'file',
3289
+						'EVT_ID'      => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3290
+						'filters'     => urlencode(
3291
+							serialize(
3292
+								$this->$method_name_for_getting_query_params(
3293
+									EEH_Array::is_set(
3294
+										$this->_req_data,
3295
+										'filters',
3296
+										array()
3297
+									)
3298
+								)
3299
+							)
3300
+						),
3301
+						'use_filters' => EEH_Array::is_set($this->_req_data, 'use_filters', false),
3302
+						'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\RegistrationsReport'),
3303
+						'return_url'  => urlencode($this->_req_data['return_url']),
3304
+					)
3305
+				)
3306
+			);
3307
+		} else {
3308
+			$new_request_args = array(
3309
+				'export' => 'report',
3310
+				'action' => 'registrations_report_for_event',
3311
+				'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3312
+			);
3313
+			$this->_req_data = array_merge($this->_req_data, $new_request_args);
3314
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3315
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3316
+				$EE_Export = EE_Export::instance($this->_req_data);
3317
+				$EE_Export->export();
3318
+			}
3319
+		}
3320
+	}
3321
+
3322
+
3323
+	/**
3324
+	 * Creates a registration report using only query parameters in the request
3325
+	 *
3326
+	 * @return void
3327
+	 */
3328
+	public function _registrations_report()
3329
+	{
3330
+		$this->_registrations_report_base('_get_registration_query_parameters');
3331
+	}
3332
+
3333
+
3334
+	public function _contact_list_export()
3335
+	{
3336
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3337
+			require_once(EE_CLASSES . 'EE_Export.class.php');
3338
+			$EE_Export = EE_Export::instance($this->_req_data);
3339
+			$EE_Export->export_attendees();
3340
+		}
3341
+	}
3342
+
3343
+
3344
+	public function _contact_list_report()
3345
+	{
3346
+		if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3347
+			wp_redirect(
3348
+				EE_Admin_Page::add_query_args_and_nonce(
3349
+					array(
3350
+						'page'        => 'espresso_batch',
3351
+						'batch'       => 'file',
3352
+						'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\AttendeesReport'),
3353
+						'return_url'  => urlencode($this->_req_data['return_url']),
3354
+					)
3355
+				)
3356
+			);
3357
+		} else {
3358
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3359
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3360
+				$EE_Export = EE_Export::instance($this->_req_data);
3361
+				$EE_Export->report_attendees();
3362
+			}
3363
+		}
3364
+	}
3365
+
3366
+
3367
+
3368
+
3369
+
3370
+	/***************************************        ATTENDEE DETAILS        ***************************************/
3371
+	/**
3372
+	 * This duplicates the attendee object for the given incoming registration id and attendee_id.
3373
+	 *
3374
+	 * @return void
3375
+	 * @throws EE_Error
3376
+	 * @throws InvalidArgumentException
3377
+	 * @throws InvalidDataTypeException
3378
+	 * @throws InvalidInterfaceException
3379
+	 * @throws ReflectionException
3380
+	 */
3381
+	protected function _duplicate_attendee()
3382
+	{
3383
+		$action = ! empty($this->_req_data['return']) ? $this->_req_data['return'] : 'default';
3384
+		// verify we have necessary info
3385
+		if (empty($this->_req_data['_REG_ID'])) {
3386
+			EE_Error::add_error(
3387
+				esc_html__(
3388
+					'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3389
+					'event_espresso'
3390
+				),
3391
+				__FILE__,
3392
+				__LINE__,
3393
+				__FUNCTION__
3394
+			);
3395
+			$query_args = array('action' => $action);
3396
+			$this->_redirect_after_action('', '', '', $query_args, true);
3397
+		}
3398
+		// okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3399
+		$registration = $this->getRegistrationModel()->get_one_by_ID($this->_req_data['_REG_ID']);
3400
+		$attendee = $registration->attendee();
3401
+		// remove relation of existing attendee on registration
3402
+		$registration->_remove_relation_to($attendee, 'Attendee');
3403
+		// new attendee
3404
+		$new_attendee = clone $attendee;
3405
+		$new_attendee->set('ATT_ID', 0);
3406
+		$new_attendee->save();
3407
+		// add new attendee to reg
3408
+		$registration->_add_relation_to($new_attendee, 'Attendee');
3409
+		EE_Error::add_success(
3410
+			esc_html__(
3411
+				'New Contact record created.  Now make any edits you wish to make for this contact.',
3412
+				'event_espresso'
3413
+			)
3414
+		);
3415
+		// redirect to edit page for attendee
3416
+		$query_args = array('post' => $new_attendee->ID(), 'action' => 'edit_attendee');
3417
+		$this->_redirect_after_action('', '', '', $query_args, true);
3418
+	}
3419
+
3420
+
3421
+	/**
3422
+	 * Callback invoked by parent EE_Admin_CPT class hooked in on `save_post` wp hook.
3423
+	 *
3424
+	 * @param int     $post_id
3425
+	 * @param WP_POST $post
3426
+	 * @throws DomainException
3427
+	 * @throws EE_Error
3428
+	 * @throws InvalidArgumentException
3429
+	 * @throws InvalidDataTypeException
3430
+	 * @throws InvalidInterfaceException
3431
+	 * @throws LogicException
3432
+	 * @throws InvalidFormSubmissionException
3433
+	 * @throws ReflectionException
3434
+	 */
3435
+	protected function _insert_update_cpt_item($post_id, $post)
3436
+	{
3437
+		$success = true;
3438
+		$attendee = $post instanceof WP_Post && $post->post_type === 'espresso_attendees'
3439
+			? $this->getAttendeeModel()->get_one_by_ID($post_id)
3440
+			: null;
3441
+		// for attendee updates
3442
+		if ($attendee instanceof EE_Attendee) {
3443
+			// note we should only be UPDATING attendees at this point.
3444
+			$updated_fields = array(
3445
+				'ATT_fname'     => $this->_req_data['ATT_fname'],
3446
+				'ATT_lname'     => $this->_req_data['ATT_lname'],
3447
+				'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3448
+				'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3449
+				'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3450
+				'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
3451
+				'STA_ID'        => isset($this->_req_data['STA_ID']) ? $this->_req_data['STA_ID'] : '',
3452
+				'CNT_ISO'       => isset($this->_req_data['CNT_ISO']) ? $this->_req_data['CNT_ISO'] : '',
3453
+				'ATT_zip'       => isset($this->_req_data['ATT_zip']) ? $this->_req_data['ATT_zip'] : '',
3454
+			);
3455
+			foreach ($updated_fields as $field => $value) {
3456
+				$attendee->set($field, $value);
3457
+			}
3458
+
3459
+			// process contact details metabox form handler (which will also save the attendee)
3460
+			$contact_details_form = $this->getAttendeeContactDetailsMetaboxFormHandler($attendee);
3461
+			$success = $contact_details_form->process($this->_req_data);
3462
+
3463
+			$attendee_update_callbacks = apply_filters(
3464
+				'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3465
+				array()
3466
+			);
3467
+			foreach ($attendee_update_callbacks as $a_callback) {
3468
+				if (false === call_user_func_array($a_callback, array($attendee, $this->_req_data))) {
3469
+					throw new EE_Error(
3470
+						sprintf(
3471
+							esc_html__(
3472
+								'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.',
3473
+								'event_espresso'
3474
+							),
3475
+							$a_callback
3476
+						)
3477
+					);
3478
+				}
3479
+			}
3480
+		}
3481
+
3482
+		if ($success === false) {
3483
+			EE_Error::add_error(
3484
+				esc_html__(
3485
+					'Something went wrong with updating the meta table data for the registration.',
3486
+					'event_espresso'
3487
+				),
3488
+				__FILE__,
3489
+				__FUNCTION__,
3490
+				__LINE__
3491
+			);
3492
+		}
3493
+	}
3494
+
3495
+
3496
+	public function trash_cpt_item($post_id)
3497
+	{
3498
+	}
3499
+
3500
+
3501
+	public function delete_cpt_item($post_id)
3502
+	{
3503
+	}
3504
+
3505
+
3506
+	public function restore_cpt_item($post_id)
3507
+	{
3508
+	}
3509
+
3510
+
3511
+	protected function _restore_cpt_item($post_id, $revision_id)
3512
+	{
3513
+	}
3514
+
3515
+
3516
+	/**
3517
+	 * @throws EE_Error
3518
+	 * @since 4.10.2.p
3519
+	 */
3520
+	public function attendee_editor_metaboxes()
3521
+	{
3522
+		$this->verify_cpt_object();
3523
+		remove_meta_box(
3524
+			'postexcerpt',
3525
+			$this->_cpt_routes[ $this->_req_action ],
3526
+			'normal'
3527
+		);
3528
+		remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal', 'core');
3529
+		if (post_type_supports('espresso_attendees', 'excerpt')) {
3530
+			add_meta_box(
3531
+				'postexcerpt',
3532
+				esc_html__('Short Biography', 'event_espresso'),
3533
+				'post_excerpt_meta_box',
3534
+				$this->_cpt_routes[ $this->_req_action ],
3535
+				'normal'
3536
+			);
3537
+		}
3538
+		if (post_type_supports('espresso_attendees', 'comments')) {
3539
+			add_meta_box(
3540
+				'commentsdiv',
3541
+				esc_html__('Notes on the Contact', 'event_espresso'),
3542
+				'post_comment_meta_box',
3543
+				$this->_cpt_routes[ $this->_req_action ],
3544
+				'normal',
3545
+				'core'
3546
+			);
3547
+		}
3548
+		add_meta_box(
3549
+			'attendee_contact_info',
3550
+			esc_html__('Contact Info', 'event_espresso'),
3551
+			array($this, 'attendee_contact_info'),
3552
+			$this->_cpt_routes[ $this->_req_action ],
3553
+			'side',
3554
+			'core'
3555
+		);
3556
+		add_meta_box(
3557
+			'attendee_details_address',
3558
+			esc_html__('Address Details', 'event_espresso'),
3559
+			array($this, 'attendee_address_details'),
3560
+			$this->_cpt_routes[ $this->_req_action ],
3561
+			'normal',
3562
+			'core'
3563
+		);
3564
+		add_meta_box(
3565
+			'attendee_registrations',
3566
+			esc_html__('Registrations for this Contact', 'event_espresso'),
3567
+			array($this, 'attendee_registrations_meta_box'),
3568
+			$this->_cpt_routes[ $this->_req_action ],
3569
+			'normal',
3570
+			'high'
3571
+		);
3572
+	}
3573
+
3574
+
3575
+	/**
3576
+	 * Metabox for attendee contact info
3577
+	 *
3578
+	 * @param  WP_Post $post wp post object
3579
+	 * @return string attendee contact info ( and form )
3580
+	 * @throws EE_Error
3581
+	 * @throws InvalidArgumentException
3582
+	 * @throws InvalidDataTypeException
3583
+	 * @throws InvalidInterfaceException
3584
+	 * @throws LogicException
3585
+	 * @throws DomainException
3586
+	 */
3587
+	public function attendee_contact_info($post)
3588
+	{
3589
+		// get attendee object ( should already have it )
3590
+		$form = $this->getAttendeeContactDetailsMetaboxFormHandler($this->_cpt_model_obj);
3591
+		$form->enqueueStylesAndScripts();
3592
+		echo $form->display();
3593
+	}
3594
+
3595
+
3596
+	/**
3597
+	 * Return form handler for the contact details metabox
3598
+	 *
3599
+	 * @param EE_Attendee $attendee
3600
+	 * @return AttendeeContactDetailsMetaboxFormHandler
3601
+	 * @throws DomainException
3602
+	 * @throws InvalidArgumentException
3603
+	 * @throws InvalidDataTypeException
3604
+	 * @throws InvalidInterfaceException
3605
+	 */
3606
+	protected function getAttendeeContactDetailsMetaboxFormHandler(EE_Attendee $attendee)
3607
+	{
3608
+		return new AttendeeContactDetailsMetaboxFormHandler($attendee, EE_Registry::instance());
3609
+	}
3610
+
3611
+
3612
+	/**
3613
+	 * Metabox for attendee details
3614
+	 *
3615
+	 * @param  WP_Post $post wp post object
3616
+	 * @throws DomainException
3617
+	 */
3618
+	public function attendee_address_details($post)
3619
+	{
3620
+		// get attendee object (should already have it)
3621
+		$this->_template_args['attendee'] = $this->_cpt_model_obj;
3622
+		$this->_template_args['state_html'] = EEH_Form_Fields::generate_form_input(
3623
+			new EE_Question_Form_Input(
3624
+				EE_Question::new_instance(
3625
+					array(
3626
+						'QST_ID'           => 0,
3627
+						'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3628
+						'QST_system'       => 'admin-state',
3629
+					)
3630
+				),
3631
+				EE_Answer::new_instance(
3632
+					array(
3633
+						'ANS_ID'    => 0,
3634
+						'ANS_value' => $this->_cpt_model_obj->state_ID(),
3635
+					)
3636
+				),
3637
+				array(
3638
+					'input_id'       => 'STA_ID',
3639
+					'input_name'     => 'STA_ID',
3640
+					'input_prefix'   => '',
3641
+					'append_qstn_id' => false,
3642
+				)
3643
+			)
3644
+		);
3645
+		$this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3646
+			new EE_Question_Form_Input(
3647
+				EE_Question::new_instance(
3648
+					array(
3649
+						'QST_ID'           => 0,
3650
+						'QST_display_text' => esc_html__('Country', 'event_espresso'),
3651
+						'QST_system'       => 'admin-country',
3652
+					)
3653
+				),
3654
+				EE_Answer::new_instance(
3655
+					array(
3656
+						'ANS_ID'    => 0,
3657
+						'ANS_value' => $this->_cpt_model_obj->country_ID(),
3658
+					)
3659
+				),
3660
+				array(
3661
+					'input_id'       => 'CNT_ISO',
3662
+					'input_name'     => 'CNT_ISO',
3663
+					'input_prefix'   => '',
3664
+					'append_qstn_id' => false,
3665
+				)
3666
+			)
3667
+		);
3668
+		$template =
3669
+			REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3670
+		EEH_Template::display_template($template, $this->_template_args);
3671
+	}
3672
+
3673
+
3674
+	/**
3675
+	 *        _attendee_details
3676
+	 *
3677
+	 * @access protected
3678
+	 * @param $post
3679
+	 * @return void
3680
+	 * @throws DomainException
3681
+	 * @throws EE_Error
3682
+	 * @throws InvalidArgumentException
3683
+	 * @throws InvalidDataTypeException
3684
+	 * @throws InvalidInterfaceException
3685
+	 * @throws ReflectionException
3686
+	 */
3687
+	public function attendee_registrations_meta_box($post)
3688
+	{
3689
+		$this->_template_args['attendee'] = $this->_cpt_model_obj;
3690
+		$this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3691
+		$template =
3692
+			REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3693
+		EEH_Template::display_template($template, $this->_template_args);
3694
+	}
3695
+
3696
+
3697
+	/**
3698
+	 * add in the form fields for the attendee edit
3699
+	 *
3700
+	 * @param  WP_Post $post wp post object
3701
+	 * @return string html for new form.
3702
+	 * @throws DomainException
3703
+	 */
3704
+	public function after_title_form_fields($post)
3705
+	{
3706
+		if ($post->post_type === 'espresso_attendees') {
3707
+			$template = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3708
+			$template_args['attendee'] = $this->_cpt_model_obj;
3709
+			EEH_Template::display_template($template, $template_args);
3710
+		}
3711
+	}
3712
+
3713
+
3714
+	/**
3715
+	 *        _trash_or_restore_attendee
3716
+	 *
3717
+	 * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3718
+	 * @return void
3719
+	 * @throws EE_Error
3720
+	 * @throws InvalidArgumentException
3721
+	 * @throws InvalidDataTypeException
3722
+	 * @throws InvalidInterfaceException
3723
+	 * @throws ReflectionException
3724
+	 * @access protected
3725
+	 */
3726
+	protected function _trash_or_restore_attendees($trash = true)
3727
+	{
3728
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3729
+		$success = 1;
3730
+		// Checkboxes
3731
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3732
+			// if array has more than one element than success message should be plural
3733
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3734
+			// cycle thru checkboxes
3735
+			foreach ($this->_req_data['checkbox'] as $ATT_ID) {
3736
+				$updated = $trash ? $this->getAttendeeModel()->update_by_ID(array('status' => 'trash'), $ATT_ID)
3737
+					: $this->getAttendeeModel()->update_by_ID(array('status' => 'publish'), $ATT_ID);
3738
+				if (! $updated) {
3739
+					$success = 0;
3740
+				}
3741
+			}
3742
+		} else {
3743
+			// grab single id and delete
3744
+			$ATT_ID = absint($this->_req_data['ATT_ID']);
3745
+			// get attendee
3746
+			$att = $this->getAttendeeModel()->get_one_by_ID($ATT_ID);
3747
+			$updated = $trash ? $att->set_status('trash') : $att->set_status('publish');
3748
+			$updated = $att->save() && $updated;
3749
+			if (! $updated) {
3750
+				$success = 0;
3751
+			}
3752
+		}
3753
+		$what = $success > 1
3754
+			? esc_html__('Contacts', 'event_espresso')
3755
+			: esc_html__('Contact', 'event_espresso');
3756
+		$action_desc = $trash
3757
+			? esc_html__('moved to the trash', 'event_espresso')
3758
+			: esc_html__('restored', 'event_espresso');
3759
+		$this->_redirect_after_action($success, $what, $action_desc, array('action' => 'contact_list'));
3760
+	}
3761 3761
 }
Please login to merge, or discard this patch.
Spacing   +97 added lines, -97 removed lines patch added patch discarded remove patch
@@ -87,7 +87,7 @@  discard block
 block discarded – undo
87 87
      */
88 88
     protected function getRegistrationModel()
89 89
     {
90
-        if (! $this->registration_model instanceof EEM_Registration) {
90
+        if ( ! $this->registration_model instanceof EEM_Registration) {
91 91
             $this->registration_model = $this->getLoader()->getShared('EEM_Registration');
92 92
         }
93 93
         return $this->registration_model;
@@ -102,7 +102,7 @@  discard block
 block discarded – undo
102 102
      */
103 103
     protected function getAttendeeModel()
104 104
     {
105
-        if (! $this->attendee_model instanceof EEM_Attendee) {
105
+        if ( ! $this->attendee_model instanceof EEM_Attendee) {
106 106
             $this->attendee_model = $this->getLoader()->getShared('EEM_Attendee');
107 107
         }
108 108
         return $this->attendee_model;
@@ -118,7 +118,7 @@  discard block
 block discarded – undo
118 118
      */
119 119
     protected function getEventModel()
120 120
     {
121
-        if (! $this->event_model instanceof EEM_Event) {
121
+        if ( ! $this->event_model instanceof EEM_Event) {
122 122
             $this->event_model = $this->getLoader()->getShared('EEM_Event');
123 123
         }
124 124
         return $this->event_model;
@@ -133,7 +133,7 @@  discard block
 block discarded – undo
133 133
      */
134 134
     protected function getStatusModel()
135 135
     {
136
-        if (! $this->status_model instanceof EEM_Status) {
136
+        if ( ! $this->status_model instanceof EEM_Status) {
137 137
             $this->status_model = $this->getLoader()->getShared('EEM_Status');
138 138
         }
139 139
         return $this->status_model;
@@ -145,7 +145,7 @@  discard block
 block discarded – undo
145 145
         // when adding a new registration...
146 146
         if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'new_registration') {
147 147
             EE_System::do_not_cache();
148
-            if (! isset($this->_req_data['processing_registration'])
148
+            if ( ! isset($this->_req_data['processing_registration'])
149 149
                 || absint($this->_req_data['processing_registration']) !== 1
150 150
             ) {
151 151
                 // and it's NOT the attendee information reg step
@@ -751,7 +751,7 @@  discard block
 block discarded – undo
751 751
         // style
752 752
         wp_register_style(
753 753
             'espresso_reg',
754
-            REG_ASSETS_URL . 'espresso_registrations_admin.css',
754
+            REG_ASSETS_URL.'espresso_registrations_admin.css',
755 755
             array('ee-admin-css'),
756 756
             EVENT_ESPRESSO_VERSION
757 757
         );
@@ -759,7 +759,7 @@  discard block
 block discarded – undo
759 759
         // script
760 760
         wp_register_script(
761 761
             'espresso_reg',
762
-            REG_ASSETS_URL . 'espresso_registrations_admin.js',
762
+            REG_ASSETS_URL.'espresso_registrations_admin.js',
763 763
             array('jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'),
764 764
             EVENT_ESPRESSO_VERSION,
765 765
             true
@@ -783,7 +783,7 @@  discard block
 block discarded – undo
783 783
             'att_publish_text' => sprintf(
784 784
                 /* translators: The date and time */
785 785
                 wp_strip_all_tags(__('Created on: %s', 'event_espresso')),
786
-                '<b>' . $this->_cpt_model_obj->get_datetime('ATT_created') . '</b>'
786
+                '<b>'.$this->_cpt_model_obj->get_datetime('ATT_created').'</b>'
787 787
             ),
788 788
         );
789 789
         wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
@@ -814,7 +814,7 @@  discard block
 block discarded – undo
814 814
         wp_dequeue_style('espresso_reg');
815 815
         wp_register_style(
816 816
             'espresso_att',
817
-            REG_ASSETS_URL . 'espresso_attendees_admin.css',
817
+            REG_ASSETS_URL.'espresso_attendees_admin.css',
818 818
             array('ee-admin-css'),
819 819
             EVENT_ESPRESSO_VERSION
820 820
         );
@@ -826,7 +826,7 @@  discard block
 block discarded – undo
826 826
     {
827 827
         wp_register_script(
828 828
             'ee-spco-for-admin',
829
-            REG_ASSETS_URL . 'spco_for_admin.js',
829
+            REG_ASSETS_URL.'spco_for_admin.js',
830 830
             array('underscore', 'jquery'),
831 831
             EVENT_ESPRESSO_VERSION,
832 832
             true
@@ -1068,7 +1068,7 @@  discard block
 block discarded – undo
1068 1068
         }
1069 1069
         $sc_items = array(
1070 1070
             'approved_status'   => array(
1071
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
1071
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_approved,
1072 1072
                 'desc'  => EEH_Template::pretty_status(
1073 1073
                     EEM_Registration::status_id_approved,
1074 1074
                     false,
@@ -1076,7 +1076,7 @@  discard block
 block discarded – undo
1076 1076
                 ),
1077 1077
             ),
1078 1078
             'pending_status'    => array(
1079
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
1079
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_pending_payment,
1080 1080
                 'desc'  => EEH_Template::pretty_status(
1081 1081
                     EEM_Registration::status_id_pending_payment,
1082 1082
                     false,
@@ -1084,7 +1084,7 @@  discard block
 block discarded – undo
1084 1084
                 ),
1085 1085
             ),
1086 1086
             'wait_list'         => array(
1087
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
1087
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_wait_list,
1088 1088
                 'desc'  => EEH_Template::pretty_status(
1089 1089
                     EEM_Registration::status_id_wait_list,
1090 1090
                     false,
@@ -1092,7 +1092,7 @@  discard block
 block discarded – undo
1092 1092
                 ),
1093 1093
             ),
1094 1094
             'incomplete_status' => array(
1095
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
1095
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_incomplete,
1096 1096
                 'desc'  => EEH_Template::pretty_status(
1097 1097
                     EEM_Registration::status_id_incomplete,
1098 1098
                     false,
@@ -1100,7 +1100,7 @@  discard block
 block discarded – undo
1100 1100
                 ),
1101 1101
             ),
1102 1102
             'not_approved'      => array(
1103
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
1103
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_not_approved,
1104 1104
                 'desc'  => EEH_Template::pretty_status(
1105 1105
                     EEM_Registration::status_id_not_approved,
1106 1106
                     false,
@@ -1108,7 +1108,7 @@  discard block
 block discarded – undo
1108 1108
                 ),
1109 1109
             ),
1110 1110
             'declined_status'   => array(
1111
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
1111
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_declined,
1112 1112
                 'desc'  => EEH_Template::pretty_status(
1113 1113
                     EEM_Registration::status_id_declined,
1114 1114
                     false,
@@ -1116,7 +1116,7 @@  discard block
 block discarded – undo
1116 1116
                 ),
1117 1117
             ),
1118 1118
             'cancelled_status'  => array(
1119
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1119
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_cancelled,
1120 1120
                 'desc'  => EEH_Template::pretty_status(
1121 1121
                     EEM_Registration::status_id_cancelled,
1122 1122
                     false,
@@ -1179,7 +1179,7 @@  discard block
 block discarded – undo
1179 1179
                 $EVT_ID
1180 1180
             )
1181 1181
         ) {
1182
-            $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1182
+            $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
1183 1183
                 'new_registration',
1184 1184
                 'add-registrant',
1185 1185
                 array('event_id' => $EVT_ID),
@@ -1205,7 +1205,7 @@  discard block
 block discarded – undo
1205 1205
         if ($this->_registration instanceof EE_Registration) {
1206 1206
             return true;
1207 1207
         }
1208
-        $REG_ID = (! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1208
+        $REG_ID = ( ! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1209 1209
         if ($this->_registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID)) {
1210 1210
             return true;
1211 1211
         }
@@ -1286,7 +1286,7 @@  discard block
 block discarded – undo
1286 1286
         /** @var EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder $list_table_query_builder */
1287 1287
         $list_table_query_builder = $this->getLoader()->getNew(
1288 1288
             'EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder',
1289
-            [ $request ]
1289
+            [$request]
1290 1290
         );
1291 1291
         return $list_table_query_builder->getQueryParams($per_page, $count);
1292 1292
     }
@@ -1392,7 +1392,7 @@  discard block
 block discarded – undo
1392 1392
                 )
1393 1393
                 : '';
1394 1394
             // grab header
1395
-            $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1395
+            $template_path = REG_TEMPLATE_PATH.'reg_admin_details_header.template.php';
1396 1396
             $this->_template_args['REG_ID'] = $this->_registration->ID();
1397 1397
             $this->_template_args['admin_page_header'] = EEH_Template::display_template(
1398 1398
                 $template_path,
@@ -1544,7 +1544,7 @@  discard block
 block discarded – undo
1544 1544
                                 EEH_HTML::strong(
1545 1545
                                     $this->_registration->pretty_status(),
1546 1546
                                     '',
1547
-                                    'status-' . $this->_registration->status_ID(),
1547
+                                    'status-'.$this->_registration->status_ID(),
1548 1548
                                     'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1549 1549
                                 )
1550 1550
                             )
@@ -1600,14 +1600,14 @@  discard block
 block discarded – undo
1600 1600
     protected function _get_reg_statuses()
1601 1601
     {
1602 1602
         $reg_status_array = $this->getRegistrationModel()->reg_status_array();
1603
-        unset($reg_status_array[ EEM_Registration::status_id_incomplete ]);
1603
+        unset($reg_status_array[EEM_Registration::status_id_incomplete]);
1604 1604
         // get current reg status
1605 1605
         $current_status = $this->_registration->status_ID();
1606 1606
         // is registration for free event? This will determine whether to display the pending payment option
1607 1607
         if ($current_status !== EEM_Registration::status_id_pending_payment
1608 1608
             && EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1609 1609
         ) {
1610
-            unset($reg_status_array[ EEM_Registration::status_id_pending_payment ]);
1610
+            unset($reg_status_array[EEM_Registration::status_id_pending_payment]);
1611 1611
         }
1612 1612
         return $this->getStatusModel()->localized_status($reg_status_array, false, 'sentence');
1613 1613
     }
@@ -1701,7 +1701,7 @@  discard block
 block discarded – undo
1701 1701
         $success = false;
1702 1702
         // typecast $REG_IDs
1703 1703
         $REG_IDs = (array) $REG_IDs;
1704
-        if (! empty($REG_IDs)) {
1704
+        if ( ! empty($REG_IDs)) {
1705 1705
             $success = true;
1706 1706
             // set default status if none is passed
1707 1707
             $status = $status ? $status : EEM_Registration::status_id_pending_payment;
@@ -1864,7 +1864,7 @@  discard block
 block discarded – undo
1864 1864
             $action,
1865 1865
             $notify
1866 1866
         );
1867
-        $method = $action . '_registration';
1867
+        $method = $action.'_registration';
1868 1868
         if (method_exists($this, $method)) {
1869 1869
             $this->$method($notify);
1870 1870
         }
@@ -2143,7 +2143,7 @@  discard block
 block discarded – undo
2143 2143
         $this->_template_args['REG_ID'] = $this->_registration->ID();
2144 2144
         $this->_template_args['event_id'] = $this->_registration->event_ID();
2145 2145
         $template_path =
2146
-            REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2146
+            REG_TEMPLATE_PATH.'reg_admin_details_main_meta_box_reg_details.template.php';
2147 2147
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
2148 2148
     }
2149 2149
 
@@ -2180,7 +2180,7 @@  discard block
 block discarded – undo
2180 2180
             $this->_template_args['reg_questions_form_action'] = 'edit_registration';
2181 2181
             $this->_template_args['REG_ID'] = $this->_registration->ID();
2182 2182
             $template_path =
2183
-                REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2183
+                REG_TEMPLATE_PATH.'reg_admin_details_main_meta_box_reg_questions.template.php';
2184 2184
             echo EEH_Template::display_template($template_path, $this->_template_args, true);
2185 2185
         }
2186 2186
     }
@@ -2197,7 +2197,7 @@  discard block
 block discarded – undo
2197 2197
     public function form_before_question_group($output)
2198 2198
     {
2199 2199
         EE_Error::doing_it_wrong(
2200
-            __CLASS__ . '::' . __FUNCTION__,
2200
+            __CLASS__.'::'.__FUNCTION__,
2201 2201
             esc_html__(
2202 2202
                 '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.',
2203 2203
                 'event_espresso'
@@ -2222,7 +2222,7 @@  discard block
 block discarded – undo
2222 2222
     public function form_after_question_group($output)
2223 2223
     {
2224 2224
         EE_Error::doing_it_wrong(
2225
-            __CLASS__ . '::' . __FUNCTION__,
2225
+            __CLASS__.'::'.__FUNCTION__,
2226 2226
             esc_html__(
2227 2227
                 '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.',
2228 2228
                 'event_espresso'
@@ -2260,7 +2260,7 @@  discard block
 block discarded – undo
2260 2260
     public function form_form_field_label_wrap($label)
2261 2261
     {
2262 2262
         EE_Error::doing_it_wrong(
2263
-            __CLASS__ . '::' . __FUNCTION__,
2263
+            __CLASS__.'::'.__FUNCTION__,
2264 2264
             esc_html__(
2265 2265
                 '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.',
2266 2266
                 'event_espresso'
@@ -2270,7 +2270,7 @@  discard block
 block discarded – undo
2270 2270
         return '
2271 2271
 			<tr>
2272 2272
 				<th>
2273
-					' . $label . '
2273
+					' . $label.'
2274 2274
 				</th>';
2275 2275
     }
2276 2276
 
@@ -2286,7 +2286,7 @@  discard block
 block discarded – undo
2286 2286
     public function form_form_field_input__wrap($input)
2287 2287
     {
2288 2288
         EE_Error::doing_it_wrong(
2289
-            __CLASS__ . '::' . __FUNCTION__,
2289
+            __CLASS__.'::'.__FUNCTION__,
2290 2290
             esc_html__(
2291 2291
                 '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.',
2292 2292
                 'event_espresso'
@@ -2295,7 +2295,7 @@  discard block
 block discarded – undo
2295 2295
         );
2296 2296
         return '
2297 2297
 				<td class="reg-admin-attendee-questions-input-td disabled-input">
2298
-					' . $input . '
2298
+					' . $input.'
2299 2299
 				</td>
2300 2300
 			</tr>';
2301 2301
     }
@@ -2343,8 +2343,8 @@  discard block
 block discarded – undo
2343 2343
      */
2344 2344
     protected function _get_reg_custom_questions_form($REG_ID)
2345 2345
     {
2346
-        if (! $this->_reg_custom_questions_form) {
2347
-            require_once(REG_ADMIN . 'form_sections/EE_Registration_Custom_Questions_Form.form.php');
2346
+        if ( ! $this->_reg_custom_questions_form) {
2347
+            require_once(REG_ADMIN.'form_sections/EE_Registration_Custom_Questions_Form.form.php');
2348 2348
             $this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2349 2349
                 $this->getRegistrationModel()->get_one_by_ID($REG_ID)
2350 2350
             );
@@ -2368,7 +2368,7 @@  discard block
 block discarded – undo
2368 2368
      */
2369 2369
     private function _save_reg_custom_questions_form($REG_ID = false)
2370 2370
     {
2371
-        if (! $REG_ID) {
2371
+        if ( ! $REG_ID) {
2372 2372
             EE_Error::add_error(
2373 2373
                 esc_html__(
2374 2374
                     'An error occurred. No registration ID was received.',
@@ -2460,30 +2460,30 @@  discard block
 block discarded – undo
2460 2460
                 $attendee = $registration->attendee()
2461 2461
                     ? $registration->attendee()
2462 2462
                     : $this->getAttendeeModel()->create_default_object();
2463
-                $this->_template_args['attendees'][ $att_nmbr ]['STS_ID'] = $registration->status_ID();
2464
-                $this->_template_args['attendees'][ $att_nmbr ]['fname'] = $attendee->fname();
2465
-                $this->_template_args['attendees'][ $att_nmbr ]['lname'] = $attendee->lname();
2466
-                $this->_template_args['attendees'][ $att_nmbr ]['email'] = $attendee->email();
2467
-                $this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2468
-                $this->_template_args['attendees'][ $att_nmbr ]['address'] = implode(
2463
+                $this->_template_args['attendees'][$att_nmbr]['STS_ID'] = $registration->status_ID();
2464
+                $this->_template_args['attendees'][$att_nmbr]['fname'] = $attendee->fname();
2465
+                $this->_template_args['attendees'][$att_nmbr]['lname'] = $attendee->lname();
2466
+                $this->_template_args['attendees'][$att_nmbr]['email'] = $attendee->email();
2467
+                $this->_template_args['attendees'][$att_nmbr]['final_price'] = $registration->final_price();
2468
+                $this->_template_args['attendees'][$att_nmbr]['address'] = implode(
2469 2469
                     ', ',
2470 2470
                     $attendee->full_address_as_array()
2471 2471
                 );
2472
-                $this->_template_args['attendees'][ $att_nmbr ]['att_link'] = self::add_query_args_and_nonce(
2472
+                $this->_template_args['attendees'][$att_nmbr]['att_link'] = self::add_query_args_and_nonce(
2473 2473
                     array(
2474 2474
                         'action' => 'edit_attendee',
2475 2475
                         'post'   => $attendee->ID(),
2476 2476
                     ),
2477 2477
                     REG_ADMIN_URL
2478 2478
                 );
2479
-                $this->_template_args['attendees'][ $att_nmbr ]['event_name'] = $registration->event_obj() instanceof EE_Event
2479
+                $this->_template_args['attendees'][$att_nmbr]['event_name'] = $registration->event_obj() instanceof EE_Event
2480 2480
                     ? $registration->event_obj()->name()
2481 2481
                     : '';
2482 2482
                 $att_nmbr++;
2483 2483
             }
2484 2484
             $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2485 2485
         }
2486
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2486
+        $template_path = REG_TEMPLATE_PATH.'reg_admin_details_main_meta_box_attendees.template.php';
2487 2487
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
2488 2488
     }
2489 2489
 
@@ -2510,11 +2510,11 @@  discard block
 block discarded – undo
2510 2510
         // now let's determine if this is not the primary registration.  If it isn't then we set the
2511 2511
         // primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2512 2512
         // primary registration object (that way we know if we need to show create button or not)
2513
-        if (! $this->_registration->is_primary_registrant()) {
2513
+        if ( ! $this->_registration->is_primary_registrant()) {
2514 2514
             $primary_registration = $this->_registration->get_primary_registration();
2515 2515
             $primary_attendee = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2516 2516
                 : null;
2517
-            if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2517
+            if ( ! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2518 2518
                 // in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2519 2519
                 // custom attendee object so let's not worry about the primary reg.
2520 2520
                 $primary_registration = null;
@@ -2548,7 +2548,7 @@  discard block
 block discarded – undo
2548 2548
             ) : '';
2549 2549
         $this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2550 2550
         $this->_template_args['att_check'] = $att_check;
2551
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2551
+        $template_path = REG_TEMPLATE_PATH.'reg_admin_details_side_meta_box_registrant.template.php';
2552 2552
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
2553 2553
     }
2554 2554
 
@@ -2586,7 +2586,7 @@  discard block
 block discarded – undo
2586 2586
         $success = 0;
2587 2587
         $overwrite_msgs = false;
2588 2588
         // Checkboxes
2589
-        if (! is_array($this->_req_data['_REG_ID'])) {
2589
+        if ( ! is_array($this->_req_data['_REG_ID'])) {
2590 2590
             $this->_req_data['_REG_ID'] = array($this->_req_data['_REG_ID']);
2591 2591
         }
2592 2592
         $reg_count = count($this->_req_data['_REG_ID']);
@@ -2595,7 +2595,7 @@  discard block
 block discarded – undo
2595 2595
             /** @var EE_Registration $REG */
2596 2596
             $REG = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
2597 2597
             $payments = $REG->registration_payments();
2598
-            if (! empty($payments)) {
2598
+            if ( ! empty($payments)) {
2599 2599
                 $name = $REG->attendee() instanceof EE_Attendee
2600 2600
                     ? $REG->attendee()->full_name()
2601 2601
                     : esc_html__('Unknown Attendee', 'event_espresso');
@@ -2657,17 +2657,17 @@  discard block
 block discarded – undo
2657 2657
         $REG_MDL = $this->getRegistrationModel();
2658 2658
         $success = 1;
2659 2659
         // Checkboxes
2660
-        if (! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2660
+        if ( ! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2661 2661
             // if array has more than one element than success message should be plural
2662 2662
             $success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
2663 2663
             // cycle thru checkboxes
2664 2664
             foreach ($this->_req_data['_REG_ID'] as $REG_ID) {
2665 2665
                 $REG = $REG_MDL->get_one_by_ID($REG_ID);
2666
-                if (! $REG instanceof EE_Registration) {
2666
+                if ( ! $REG instanceof EE_Registration) {
2667 2667
                     continue;
2668 2668
                 }
2669 2669
                 $deleted = $this->_delete_registration($REG);
2670
-                if (! $deleted) {
2670
+                if ( ! $deleted) {
2671 2671
                     $success = 0;
2672 2672
                 }
2673 2673
             }
@@ -2677,7 +2677,7 @@  discard block
 block discarded – undo
2677 2677
             /** @var EE_Registration $REG */
2678 2678
             $REG = $REG_MDL->get_one_by_ID($REG_ID);
2679 2679
             $deleted = $this->_delete_registration($REG);
2680
-            if (! $deleted) {
2680
+            if ( ! $deleted) {
2681 2681
                 $success = 0;
2682 2682
             }
2683 2683
         }
@@ -2712,7 +2712,7 @@  discard block
 block discarded – undo
2712 2712
         // first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2713 2713
         // registrations on the transaction that are NOT trashed.
2714 2714
         $TXN = $REG->get_first_related('Transaction');
2715
-        if (! $TXN instanceof EE_Transaction) {
2715
+        if ( ! $TXN instanceof EE_Transaction) {
2716 2716
             EE_Error::add_error(
2717 2717
                 sprintf(
2718 2718
                     esc_html__(
@@ -2730,11 +2730,11 @@  discard block
 block discarded – undo
2730 2730
         $REGS = $TXN->get_many_related('Registration');
2731 2731
         $all_trashed = true;
2732 2732
         foreach ($REGS as $registration) {
2733
-            if (! $registration->get('REG_deleted')) {
2733
+            if ( ! $registration->get('REG_deleted')) {
2734 2734
                 $all_trashed = false;
2735 2735
             }
2736 2736
         }
2737
-        if (! $all_trashed) {
2737
+        if ( ! $all_trashed) {
2738 2738
             EE_Error::add_error(
2739 2739
                 esc_html__(
2740 2740
                     '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.',
@@ -2797,7 +2797,7 @@  discard block
 block discarded – undo
2797 2797
      */
2798 2798
     public function new_registration()
2799 2799
     {
2800
-        if (! $this->_set_reg_event()) {
2800
+        if ( ! $this->_set_reg_event()) {
2801 2801
             throw new EE_Error(
2802 2802
                 esc_html__(
2803 2803
                     'Unable to continue with registering because there is no Event ID in the request',
@@ -2807,8 +2807,8 @@  discard block
 block discarded – undo
2807 2807
         }
2808 2808
         EE_Registry::instance()->REQ->set_espresso_page(true);
2809 2809
         // gotta start with a clean slate if we're not coming here via ajax
2810
-        if (! defined('DOING_AJAX')
2811
-            && (! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2810
+        if ( ! defined('DOING_AJAX')
2811
+            && ( ! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2812 2812
         ) {
2813 2813
             EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2814 2814
         }
@@ -2841,7 +2841,7 @@  discard block
 block discarded – undo
2841 2841
         }
2842 2842
         // grab header
2843 2843
         $template_path =
2844
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2844
+            REG_TEMPLATE_PATH.'reg_admin_register_new_attendee.template.php';
2845 2845
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2846 2846
             $template_path,
2847 2847
             $this->_template_args,
@@ -2882,7 +2882,7 @@  discard block
 block discarded – undo
2882 2882
                 '</b>'
2883 2883
             );
2884 2884
             return '
2885
-	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg . '</p></div>
2885
+	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg.'</p></div>
2886 2886
 	<script >
2887 2887
 		// WHOAH !!! it appears that someone is using the back button from the Transaction admin page
2888 2888
 		// after just adding a new registration... we gotta try to put a stop to that !!!
@@ -2951,7 +2951,7 @@  discard block
 block discarded – undo
2951 2951
         // we come back to the process_registration_step route.
2952 2952
         $this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
2953 2953
         return EEH_Template::display_template(
2954
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
2954
+            REG_TEMPLATE_PATH.'reg_admin_register_new_attendee_step_content.template.php',
2955 2955
             $template_args,
2956 2956
             true
2957 2957
         );
@@ -2973,8 +2973,8 @@  discard block
 block discarded – undo
2973 2973
         if (is_object($this->_reg_event)) {
2974 2974
             return true;
2975 2975
         }
2976
-        $EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
2977
-        if (! $EVT_ID) {
2976
+        $EVT_ID = ( ! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
2977
+        if ( ! $EVT_ID) {
2978 2978
             return false;
2979 2979
         }
2980 2980
         $this->_reg_event = $this->getEventModel()->get_one_by_ID($EVT_ID);
@@ -3006,8 +3006,8 @@  discard block
 block discarded – undo
3006 3006
         $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3007 3007
         // if doing ajax then we need to verify the nonce
3008 3008
         if (defined('DOING_AJAX')) {
3009
-            $nonce = isset($this->_req_data[ $this->_req_nonce ])
3010
-                ? sanitize_text_field($this->_req_data[ $this->_req_nonce ]) : '';
3009
+            $nonce = isset($this->_req_data[$this->_req_nonce])
3010
+                ? sanitize_text_field($this->_req_data[$this->_req_nonce]) : '';
3011 3011
             $this->_verify_nonce($nonce, $this->_req_nonce);
3012 3012
         }
3013 3013
         switch ($step) {
@@ -3043,7 +3043,7 @@  discard block
 block discarded – undo
3043 3043
                 }
3044 3044
                 break;
3045 3045
             case 'questions':
3046
-                if (! isset(
3046
+                if ( ! isset(
3047 3047
                     $this->_req_data['txn_reg_status_change'],
3048 3048
                     $this->_req_data['txn_reg_status_change']['send_notifications']
3049 3049
                 )
@@ -3058,7 +3058,7 @@  discard block
 block discarded – undo
3058 3058
                         $grand_total->save_this_and_descendants_to_txn();
3059 3059
                     }
3060 3060
                 }
3061
-                if (! $transaction instanceof EE_Transaction) {
3061
+                if ( ! $transaction instanceof EE_Transaction) {
3062 3062
                     $query_args = array(
3063 3063
                         'action'                  => 'new_registration',
3064 3064
                         'processing_registration' => 2,
@@ -3080,7 +3080,7 @@  discard block
 block discarded – undo
3080 3080
                     return;
3081 3081
                 }
3082 3082
                 // maybe update status, and make sure to save transaction if not done already
3083
-                if (! $transaction->update_status_based_on_total_paid()) {
3083
+                if ( ! $transaction->update_status_based_on_total_paid()) {
3084 3084
                     $transaction->save();
3085 3085
                 }
3086 3086
                 EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
@@ -3166,7 +3166,7 @@  discard block
 block discarded – undo
3166 3166
     public function get_attendees($per_page, $count = false, $trash = false)
3167 3167
     {
3168 3168
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3169
-        require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3169
+        require_once(REG_ADMIN.'EE_Attendee_Contact_List_Table.class.php');
3170 3170
         $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
3171 3171
         switch ($this->_req_data['orderby']) {
3172 3172
             case 'ATT_ID':
@@ -3204,8 +3204,8 @@  discard block
 block discarded – undo
3204 3204
             ? $this->_req_data['perpage']
3205 3205
             : $per_page;
3206 3206
         $_where = array();
3207
-        if (! empty($this->_req_data['s'])) {
3208
-            $sstr = '%' . $this->_req_data['s'] . '%';
3207
+        if ( ! empty($this->_req_data['s'])) {
3208
+            $sstr = '%'.$this->_req_data['s'].'%';
3209 3209
             $_where['OR'] = array(
3210 3210
                 'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3211 3211
                 'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
@@ -3232,7 +3232,7 @@  discard block
 block discarded – undo
3232 3232
             'extra_selects' => array('Registration_Count' => array('Registration.REG_ID', 'count', '%d')),
3233 3233
             'limit'         => $limit,
3234 3234
         );
3235
-        if (! $count) {
3235
+        if ( ! $count) {
3236 3236
             $query_args['order_by'] = array($orderby => $sort);
3237 3237
         }
3238 3238
         if ($trash) {
@@ -3280,7 +3280,7 @@  discard block
 block discarded – undo
3280 3280
      */
3281 3281
     public function _registrations_report_base($method_name_for_getting_query_params)
3282 3282
     {
3283
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3283
+        if ( ! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3284 3284
             wp_redirect(
3285 3285
                 EE_Admin_Page::add_query_args_and_nonce(
3286 3286
                     array(
@@ -3311,8 +3311,8 @@  discard block
 block discarded – undo
3311 3311
                 'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3312 3312
             );
3313 3313
             $this->_req_data = array_merge($this->_req_data, $new_request_args);
3314
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3315
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3314
+            if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
3315
+                require_once(EE_CLASSES.'EE_Export.class.php');
3316 3316
                 $EE_Export = EE_Export::instance($this->_req_data);
3317 3317
                 $EE_Export->export();
3318 3318
             }
@@ -3333,8 +3333,8 @@  discard block
 block discarded – undo
3333 3333
 
3334 3334
     public function _contact_list_export()
3335 3335
     {
3336
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3337
-            require_once(EE_CLASSES . 'EE_Export.class.php');
3336
+        if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
3337
+            require_once(EE_CLASSES.'EE_Export.class.php');
3338 3338
             $EE_Export = EE_Export::instance($this->_req_data);
3339 3339
             $EE_Export->export_attendees();
3340 3340
         }
@@ -3343,7 +3343,7 @@  discard block
 block discarded – undo
3343 3343
 
3344 3344
     public function _contact_list_report()
3345 3345
     {
3346
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3346
+        if ( ! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3347 3347
             wp_redirect(
3348 3348
                 EE_Admin_Page::add_query_args_and_nonce(
3349 3349
                     array(
@@ -3355,8 +3355,8 @@  discard block
 block discarded – undo
3355 3355
                 )
3356 3356
             );
3357 3357
         } else {
3358
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3359
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3358
+            if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
3359
+                require_once(EE_CLASSES.'EE_Export.class.php');
3360 3360
                 $EE_Export = EE_Export::instance($this->_req_data);
3361 3361
                 $EE_Export->report_attendees();
3362 3362
             }
@@ -3444,7 +3444,7 @@  discard block
 block discarded – undo
3444 3444
             $updated_fields = array(
3445 3445
                 'ATT_fname'     => $this->_req_data['ATT_fname'],
3446 3446
                 'ATT_lname'     => $this->_req_data['ATT_lname'],
3447
-                'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3447
+                'ATT_full_name' => $this->_req_data['ATT_fname'].' '.$this->_req_data['ATT_lname'],
3448 3448
                 'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3449 3449
                 'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3450 3450
                 'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
@@ -3522,16 +3522,16 @@  discard block
 block discarded – undo
3522 3522
         $this->verify_cpt_object();
3523 3523
         remove_meta_box(
3524 3524
             'postexcerpt',
3525
-            $this->_cpt_routes[ $this->_req_action ],
3525
+            $this->_cpt_routes[$this->_req_action],
3526 3526
             'normal'
3527 3527
         );
3528
-        remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal', 'core');
3528
+        remove_meta_box('commentstatusdiv', $this->_cpt_routes[$this->_req_action], 'normal', 'core');
3529 3529
         if (post_type_supports('espresso_attendees', 'excerpt')) {
3530 3530
             add_meta_box(
3531 3531
                 'postexcerpt',
3532 3532
                 esc_html__('Short Biography', 'event_espresso'),
3533 3533
                 'post_excerpt_meta_box',
3534
-                $this->_cpt_routes[ $this->_req_action ],
3534
+                $this->_cpt_routes[$this->_req_action],
3535 3535
                 'normal'
3536 3536
             );
3537 3537
         }
@@ -3540,7 +3540,7 @@  discard block
 block discarded – undo
3540 3540
                 'commentsdiv',
3541 3541
                 esc_html__('Notes on the Contact', 'event_espresso'),
3542 3542
                 'post_comment_meta_box',
3543
-                $this->_cpt_routes[ $this->_req_action ],
3543
+                $this->_cpt_routes[$this->_req_action],
3544 3544
                 'normal',
3545 3545
                 'core'
3546 3546
             );
@@ -3549,7 +3549,7 @@  discard block
 block discarded – undo
3549 3549
             'attendee_contact_info',
3550 3550
             esc_html__('Contact Info', 'event_espresso'),
3551 3551
             array($this, 'attendee_contact_info'),
3552
-            $this->_cpt_routes[ $this->_req_action ],
3552
+            $this->_cpt_routes[$this->_req_action],
3553 3553
             'side',
3554 3554
             'core'
3555 3555
         );
@@ -3557,7 +3557,7 @@  discard block
 block discarded – undo
3557 3557
             'attendee_details_address',
3558 3558
             esc_html__('Address Details', 'event_espresso'),
3559 3559
             array($this, 'attendee_address_details'),
3560
-            $this->_cpt_routes[ $this->_req_action ],
3560
+            $this->_cpt_routes[$this->_req_action],
3561 3561
             'normal',
3562 3562
             'core'
3563 3563
         );
@@ -3565,7 +3565,7 @@  discard block
 block discarded – undo
3565 3565
             'attendee_registrations',
3566 3566
             esc_html__('Registrations for this Contact', 'event_espresso'),
3567 3567
             array($this, 'attendee_registrations_meta_box'),
3568
-            $this->_cpt_routes[ $this->_req_action ],
3568
+            $this->_cpt_routes[$this->_req_action],
3569 3569
             'normal',
3570 3570
             'high'
3571 3571
         );
@@ -3666,7 +3666,7 @@  discard block
 block discarded – undo
3666 3666
             )
3667 3667
         );
3668 3668
         $template =
3669
-            REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3669
+            REG_TEMPLATE_PATH.'attendee_address_details_metabox_content.template.php';
3670 3670
         EEH_Template::display_template($template, $this->_template_args);
3671 3671
     }
3672 3672
 
@@ -3689,7 +3689,7 @@  discard block
 block discarded – undo
3689 3689
         $this->_template_args['attendee'] = $this->_cpt_model_obj;
3690 3690
         $this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3691 3691
         $template =
3692
-            REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3692
+            REG_TEMPLATE_PATH.'attendee_registrations_main_meta_box.template.php';
3693 3693
         EEH_Template::display_template($template, $this->_template_args);
3694 3694
     }
3695 3695
 
@@ -3704,7 +3704,7 @@  discard block
 block discarded – undo
3704 3704
     public function after_title_form_fields($post)
3705 3705
     {
3706 3706
         if ($post->post_type === 'espresso_attendees') {
3707
-            $template = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3707
+            $template = REG_TEMPLATE_PATH.'attendee_details_after_title_form_fields.template.php';
3708 3708
             $template_args['attendee'] = $this->_cpt_model_obj;
3709 3709
             EEH_Template::display_template($template, $template_args);
3710 3710
         }
@@ -3728,14 +3728,14 @@  discard block
 block discarded – undo
3728 3728
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3729 3729
         $success = 1;
3730 3730
         // Checkboxes
3731
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3731
+        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3732 3732
             // if array has more than one element than success message should be plural
3733 3733
             $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3734 3734
             // cycle thru checkboxes
3735 3735
             foreach ($this->_req_data['checkbox'] as $ATT_ID) {
3736 3736
                 $updated = $trash ? $this->getAttendeeModel()->update_by_ID(array('status' => 'trash'), $ATT_ID)
3737 3737
                     : $this->getAttendeeModel()->update_by_ID(array('status' => 'publish'), $ATT_ID);
3738
-                if (! $updated) {
3738
+                if ( ! $updated) {
3739 3739
                     $success = 0;
3740 3740
                 }
3741 3741
             }
@@ -3746,7 +3746,7 @@  discard block
 block discarded – undo
3746 3746
             $att = $this->getAttendeeModel()->get_one_by_ID($ATT_ID);
3747 3747
             $updated = $trash ? $att->set_status('trash') : $att->set_status('publish');
3748 3748
             $updated = $att->save() && $updated;
3749
-            if (! $updated) {
3749
+            if ( ! $updated) {
3750 3750
                 $success = 0;
3751 3751
             }
3752 3752
         }
Please login to merge, or discard this patch.
modules/ical/EED_Ical.module.php 2 patches
Indentation   +237 added lines, -237 removed lines patch added patch discarded remove patch
@@ -11,241 +11,241 @@
 block discarded – undo
11 11
 class EED_Ical extends EED_Module
12 12
 {
13 13
 
14
-    const iCal_datetime_format = 'Ymd\THis\Z';
15
-
16
-
17
-    /**
18
-     * @return EED_Ical|EED_Module
19
-     */
20
-    public static function instance()
21
-    {
22
-        return parent::get_instance(__CLASS__);
23
-    }
24
-
25
-
26
-    /**
27
-     *    set_hooks - for hooking into EE Core, other modules, etc
28
-     *
29
-     * @access    public
30
-     * @return    void
31
-     */
32
-    public static function set_hooks()
33
-    {
34
-        // create download buttons
35
-        add_filter(
36
-            'FHEE__espresso_list_of_event_dates__datetime_html',
37
-            array('EED_Ical', 'generate_add_to_iCal_button'),
38
-            10,
39
-            2
40
-        );
41
-        // process ics download request
42
-        EE_Config::register_route('download_ics_file', 'EED_Ical', 'download_ics_file');
43
-    }
44
-
45
-
46
-    /**
47
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
48
-     *
49
-     * @access    public
50
-     * @return    void
51
-     */
52
-    public static function set_hooks_admin()
53
-    {
54
-    }
55
-
56
-
57
-    /**
58
-     *    run - initial module setup
59
-     *
60
-     * @access    public
61
-     * @param    WP $WP
62
-     * @return    void
63
-     */
64
-    public function run($WP)
65
-    {
66
-    }
67
-
68
-
69
-    /**
70
-     *    generate_add_to_iCal_button
71
-     *
72
-     * @access    public
73
-     * @param $html
74
-     * @param $datetime
75
-     * @return    string
76
-     * @throws \EE_Error
77
-     */
78
-    public static function generate_add_to_iCal_button($html, $datetime)
79
-    {
80
-        // first verify a proper datetime object has been received
81
-        if ($datetime instanceof EE_Datetime) {
82
-            // set whether a link or submit button is shown
83
-            $iCal_type = apply_filters('FHEE__EED_Ical__generate_add_to_iCal_button__iCal_type', 'submit');
84
-            // generate a link to the route we registered in set_hooks()
85
-            $URL = add_query_arg(array('ee' => 'download_ics_file', 'ics_id' => $datetime->ID()), site_url());
86
-            // what type ?
87
-            switch ($iCal_type) {
88
-                // submit buttons appear as buttons and are very compatible with a theme's style
89
-                case 'submit':
90
-                    $html .= '<form id="download-iCal-frm-' . $datetime->ID();
91
-                    $html .= '" class="download-iCal-frm" action="' . $URL . '" method="post" >';
92
-                    $html .= '<input type="submit" class="ee-ical-sbmt" value="&#xf145;" title="';
93
-                    $html .= esc_html__('Add to iCal Calendar', 'event_espresso') . '"/>';
94
-                    $html .= '</form>';
95
-                    break;
96
-                // buttons are just links that have been styled to appear as buttons,
97
-                // but may not be blend with a theme as well as submit buttons
98
-                case 'button':
99
-                    $html .= '<a class="ee-ical-btn small ee-button ee-roundish" href="' . $URL;
100
-                    $html .= '" title="' . esc_html__('Add to iCal Calendar', 'event_espresso') . '">';
101
-                    $html .= ' <span class="dashicons dashicons-calendar"></span>';
102
-                    $html .= '</a>';
103
-                    break;
104
-                // links are just links that use the calendar dashicon
105
-                case 'icon':
106
-                    $html .= '<a class="ee-ical-lnk" href="' . $URL . '" title="';
107
-                    $html .= esc_html__('Add to iCal Calendar', 'event_espresso') . '">';
108
-                    $html .= ' <span class="dashicons dashicons-calendar"></span>';
109
-                    $html .= '</a>';
110
-                    break;
111
-            }
112
-        }
113
-        return $html;
114
-    }
115
-
116
-
117
-    /**
118
-     *    download_ics_file
119
-     *
120
-     * @access    public
121
-     * @return    void
122
-     * @throws \EE_Error
123
-     */
124
-    public static function download_ics_file()
125
-    {
126
-        if (EE_Registry::instance()->REQ->is_set('ics_id')) {
127
-            $DTT_ID = absint(EE_Registry::instance()->REQ->get('ics_id'));
128
-            $datetime = EE_Registry::instance()->load_model('Datetime')->get_one_by_ID($DTT_ID);
129
-            if ($datetime instanceof EE_Datetime) {
130
-                // get related event, venues, and event categories
131
-                $event = $datetime->event();
132
-                if ($event instanceof EE_Event) {
133
-                    // get related category Term object and it's name
134
-                    $category = $event->first_event_category();
135
-                    if ($category instanceof EE_Term) {
136
-                        $category = $category->name();
137
-                    }
138
-                    $location = '';
139
-                    // get first related venue and convert to CSV string
140
-                    $venue = $event->venues(array('limit' => 1));
141
-                    if (is_array($venue) && ! empty($venue)) {
142
-                        $venue = array_shift($venue);
143
-                        if ($venue instanceof EE_Venue) {
144
-                            $location = espresso_venue_raw_address('inline', $venue->ID(), false);
145
-                        }
146
-                    }
147
-
148
-                    // Generate filename
149
-                    $filename = $event->slug() . '-' . $datetime->start_date('Y-m-d') . '.ics';
150
-
151
-                    // Check the datetime status has not been cancelled and set the ics value accordingly
152
-                    $status = $datetime->get_active_status();
153
-                    $status = $status === EE_Datetime::cancelled ? 'CANCELLED' : 'CONFIRMED';
154
-
155
-                    // Create array of ics details, escape strings, convert timestamps to ics format, etc
156
-                    $ics_data = array(
157
-                        'ORGANIZER_NAME' => EE_Registry::instance()->CFG->organization->name,
158
-                        'UID'            => md5($event->name() . $event->ID() . $datetime->ID()),
159
-                        'ORGANIZER'      => EE_Registry::instance()->CFG->organization->email,
160
-                        'DTSTAMP'        => date(EED_Ical::iCal_datetime_format),
161
-                        'LOCATION'       => $location,
162
-                        'SUMMARY'        => $event->name(),
163
-                        'DESCRIPTION'    => wp_strip_all_tags($event->description()),
164
-                        'STATUS'         => $status,
165
-                        'CATEGORIES'     => $category,
166
-                        'URL;VALUE=URI'  => get_permalink($event->ID()),
167
-                        'DTSTART'        => date(EED_Ical::iCal_datetime_format, $datetime->start()),
168
-                        'DTEND'          => date(EED_Ical::iCal_datetime_format, $datetime->end()),
169
-                    );
170
-
171
-                    // Filter the values used within the ics output.
172
-                    // NOTE - all values within ics_data will be escaped automatically.
173
-                    $ics_data = apply_filters('FHEE__EED_Ical__download_ics_file_ics_data', $ics_data, $datetime);
174
-
175
-                    // Escape all ics data
176
-                    foreach ($ics_data as $key => $value) {
177
-                        // Description is escaped differently from all all values
178
-                        if ($key === 'DESCRIPTION') {
179
-                            $ics_data[ $key ] = EED_Ical::_escape_ICal_description(wp_strip_all_tags($value));
180
-                        } else {
181
-                            $ics_data[ $key ] = EED_Ical::_escape_ICal_data($value);
182
-                        }
183
-                    }
184
-
185
-                    // Pull the organizer name from ics_data and remove it from the array.
186
-                    $organizer_name = isset($ics_data['ORGANIZER_NAME']) ? $ics_data['ORGANIZER_NAME'] : '';
187
-                    unset($ics_data['ORGANIZER_NAME']);
188
-
189
-                    // set headers
190
-                    header('Content-type: text/calendar; charset=utf-8');
191
-                    header('Content-Disposition: attachment; filename="' . $filename . '"');
192
-                    header('Cache-Control: private, max-age=0, must-revalidate');
193
-                    header('Pragma: public');
194
-                    header('Content-Type: application/octet-stream');
195
-                    header('Content-Type: application/force-download');
196
-                    header('Cache-Control: no-cache, must-revalidate');
197
-                    header('Content-Transfer-Encoding: binary');
198
-                    header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // past date
199
-                    ini_set('zlib.output_compression', '0');
200
-                    // echo the output
201
-                    echo "BEGIN:VCALENDAR\r\n";
202
-                    echo "VERSION:2.0\r\n";
203
-                    echo "PRODID:-//{$organizer_name}//NONSGML PDA Calendar Version 1.0//EN\r\n";
204
-                    echo "CALSCALE:GREGORIAN\r\n";
205
-                    echo "BEGIN:VEVENT\r\n";
206
-
207
-                    // Output all remaining values from ics_data.
208
-                    foreach ($ics_data as $key => $value) {
209
-                        echo $key . ':' . $value . "\r\n";
210
-                    }
211
-
212
-                    echo "END:VEVENT\r\n";
213
-                    echo "END:VCALENDAR\r\n";
214
-                }
215
-            }
216
-        }
217
-        die();
218
-    }
219
-
220
-
221
-    /**
222
-     *    _escape_ICal_data
223
-     *
224
-     * @access    private
225
-     * @param    string $string
226
-     * @return    string
227
-     */
228
-    private static function _escape_ICal_data($string = '')
229
-    {
230
-        return preg_replace('/([\,;])/', '\\\$1', $string);
231
-    }
232
-
233
-    /**
234
-     *    _escape_ICal_description
235
-     *
236
-     * @access    private
237
-     * @param    string $description
238
-     * @return    string
239
-     */
240
-    private static function _escape_ICal_description($description = '')
241
-    {
242
-
243
-        // Escape special chars within the description
244
-        $description = EED_Ical::_escape_ICal_data($description);
245
-
246
-        // Remove line breaks and output in iCal format
247
-        $description = str_replace(array("\r\n", "\n"), '\n', $description);
248
-
249
-        return $description;
250
-    }
14
+	const iCal_datetime_format = 'Ymd\THis\Z';
15
+
16
+
17
+	/**
18
+	 * @return EED_Ical|EED_Module
19
+	 */
20
+	public static function instance()
21
+	{
22
+		return parent::get_instance(__CLASS__);
23
+	}
24
+
25
+
26
+	/**
27
+	 *    set_hooks - for hooking into EE Core, other modules, etc
28
+	 *
29
+	 * @access    public
30
+	 * @return    void
31
+	 */
32
+	public static function set_hooks()
33
+	{
34
+		// create download buttons
35
+		add_filter(
36
+			'FHEE__espresso_list_of_event_dates__datetime_html',
37
+			array('EED_Ical', 'generate_add_to_iCal_button'),
38
+			10,
39
+			2
40
+		);
41
+		// process ics download request
42
+		EE_Config::register_route('download_ics_file', 'EED_Ical', 'download_ics_file');
43
+	}
44
+
45
+
46
+	/**
47
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
48
+	 *
49
+	 * @access    public
50
+	 * @return    void
51
+	 */
52
+	public static function set_hooks_admin()
53
+	{
54
+	}
55
+
56
+
57
+	/**
58
+	 *    run - initial module setup
59
+	 *
60
+	 * @access    public
61
+	 * @param    WP $WP
62
+	 * @return    void
63
+	 */
64
+	public function run($WP)
65
+	{
66
+	}
67
+
68
+
69
+	/**
70
+	 *    generate_add_to_iCal_button
71
+	 *
72
+	 * @access    public
73
+	 * @param $html
74
+	 * @param $datetime
75
+	 * @return    string
76
+	 * @throws \EE_Error
77
+	 */
78
+	public static function generate_add_to_iCal_button($html, $datetime)
79
+	{
80
+		// first verify a proper datetime object has been received
81
+		if ($datetime instanceof EE_Datetime) {
82
+			// set whether a link or submit button is shown
83
+			$iCal_type = apply_filters('FHEE__EED_Ical__generate_add_to_iCal_button__iCal_type', 'submit');
84
+			// generate a link to the route we registered in set_hooks()
85
+			$URL = add_query_arg(array('ee' => 'download_ics_file', 'ics_id' => $datetime->ID()), site_url());
86
+			// what type ?
87
+			switch ($iCal_type) {
88
+				// submit buttons appear as buttons and are very compatible with a theme's style
89
+				case 'submit':
90
+					$html .= '<form id="download-iCal-frm-' . $datetime->ID();
91
+					$html .= '" class="download-iCal-frm" action="' . $URL . '" method="post" >';
92
+					$html .= '<input type="submit" class="ee-ical-sbmt" value="&#xf145;" title="';
93
+					$html .= esc_html__('Add to iCal Calendar', 'event_espresso') . '"/>';
94
+					$html .= '</form>';
95
+					break;
96
+				// buttons are just links that have been styled to appear as buttons,
97
+				// but may not be blend with a theme as well as submit buttons
98
+				case 'button':
99
+					$html .= '<a class="ee-ical-btn small ee-button ee-roundish" href="' . $URL;
100
+					$html .= '" title="' . esc_html__('Add to iCal Calendar', 'event_espresso') . '">';
101
+					$html .= ' <span class="dashicons dashicons-calendar"></span>';
102
+					$html .= '</a>';
103
+					break;
104
+				// links are just links that use the calendar dashicon
105
+				case 'icon':
106
+					$html .= '<a class="ee-ical-lnk" href="' . $URL . '" title="';
107
+					$html .= esc_html__('Add to iCal Calendar', 'event_espresso') . '">';
108
+					$html .= ' <span class="dashicons dashicons-calendar"></span>';
109
+					$html .= '</a>';
110
+					break;
111
+			}
112
+		}
113
+		return $html;
114
+	}
115
+
116
+
117
+	/**
118
+	 *    download_ics_file
119
+	 *
120
+	 * @access    public
121
+	 * @return    void
122
+	 * @throws \EE_Error
123
+	 */
124
+	public static function download_ics_file()
125
+	{
126
+		if (EE_Registry::instance()->REQ->is_set('ics_id')) {
127
+			$DTT_ID = absint(EE_Registry::instance()->REQ->get('ics_id'));
128
+			$datetime = EE_Registry::instance()->load_model('Datetime')->get_one_by_ID($DTT_ID);
129
+			if ($datetime instanceof EE_Datetime) {
130
+				// get related event, venues, and event categories
131
+				$event = $datetime->event();
132
+				if ($event instanceof EE_Event) {
133
+					// get related category Term object and it's name
134
+					$category = $event->first_event_category();
135
+					if ($category instanceof EE_Term) {
136
+						$category = $category->name();
137
+					}
138
+					$location = '';
139
+					// get first related venue and convert to CSV string
140
+					$venue = $event->venues(array('limit' => 1));
141
+					if (is_array($venue) && ! empty($venue)) {
142
+						$venue = array_shift($venue);
143
+						if ($venue instanceof EE_Venue) {
144
+							$location = espresso_venue_raw_address('inline', $venue->ID(), false);
145
+						}
146
+					}
147
+
148
+					// Generate filename
149
+					$filename = $event->slug() . '-' . $datetime->start_date('Y-m-d') . '.ics';
150
+
151
+					// Check the datetime status has not been cancelled and set the ics value accordingly
152
+					$status = $datetime->get_active_status();
153
+					$status = $status === EE_Datetime::cancelled ? 'CANCELLED' : 'CONFIRMED';
154
+
155
+					// Create array of ics details, escape strings, convert timestamps to ics format, etc
156
+					$ics_data = array(
157
+						'ORGANIZER_NAME' => EE_Registry::instance()->CFG->organization->name,
158
+						'UID'            => md5($event->name() . $event->ID() . $datetime->ID()),
159
+						'ORGANIZER'      => EE_Registry::instance()->CFG->organization->email,
160
+						'DTSTAMP'        => date(EED_Ical::iCal_datetime_format),
161
+						'LOCATION'       => $location,
162
+						'SUMMARY'        => $event->name(),
163
+						'DESCRIPTION'    => wp_strip_all_tags($event->description()),
164
+						'STATUS'         => $status,
165
+						'CATEGORIES'     => $category,
166
+						'URL;VALUE=URI'  => get_permalink($event->ID()),
167
+						'DTSTART'        => date(EED_Ical::iCal_datetime_format, $datetime->start()),
168
+						'DTEND'          => date(EED_Ical::iCal_datetime_format, $datetime->end()),
169
+					);
170
+
171
+					// Filter the values used within the ics output.
172
+					// NOTE - all values within ics_data will be escaped automatically.
173
+					$ics_data = apply_filters('FHEE__EED_Ical__download_ics_file_ics_data', $ics_data, $datetime);
174
+
175
+					// Escape all ics data
176
+					foreach ($ics_data as $key => $value) {
177
+						// Description is escaped differently from all all values
178
+						if ($key === 'DESCRIPTION') {
179
+							$ics_data[ $key ] = EED_Ical::_escape_ICal_description(wp_strip_all_tags($value));
180
+						} else {
181
+							$ics_data[ $key ] = EED_Ical::_escape_ICal_data($value);
182
+						}
183
+					}
184
+
185
+					// Pull the organizer name from ics_data and remove it from the array.
186
+					$organizer_name = isset($ics_data['ORGANIZER_NAME']) ? $ics_data['ORGANIZER_NAME'] : '';
187
+					unset($ics_data['ORGANIZER_NAME']);
188
+
189
+					// set headers
190
+					header('Content-type: text/calendar; charset=utf-8');
191
+					header('Content-Disposition: attachment; filename="' . $filename . '"');
192
+					header('Cache-Control: private, max-age=0, must-revalidate');
193
+					header('Pragma: public');
194
+					header('Content-Type: application/octet-stream');
195
+					header('Content-Type: application/force-download');
196
+					header('Cache-Control: no-cache, must-revalidate');
197
+					header('Content-Transfer-Encoding: binary');
198
+					header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // past date
199
+					ini_set('zlib.output_compression', '0');
200
+					// echo the output
201
+					echo "BEGIN:VCALENDAR\r\n";
202
+					echo "VERSION:2.0\r\n";
203
+					echo "PRODID:-//{$organizer_name}//NONSGML PDA Calendar Version 1.0//EN\r\n";
204
+					echo "CALSCALE:GREGORIAN\r\n";
205
+					echo "BEGIN:VEVENT\r\n";
206
+
207
+					// Output all remaining values from ics_data.
208
+					foreach ($ics_data as $key => $value) {
209
+						echo $key . ':' . $value . "\r\n";
210
+					}
211
+
212
+					echo "END:VEVENT\r\n";
213
+					echo "END:VCALENDAR\r\n";
214
+				}
215
+			}
216
+		}
217
+		die();
218
+	}
219
+
220
+
221
+	/**
222
+	 *    _escape_ICal_data
223
+	 *
224
+	 * @access    private
225
+	 * @param    string $string
226
+	 * @return    string
227
+	 */
228
+	private static function _escape_ICal_data($string = '')
229
+	{
230
+		return preg_replace('/([\,;])/', '\\\$1', $string);
231
+	}
232
+
233
+	/**
234
+	 *    _escape_ICal_description
235
+	 *
236
+	 * @access    private
237
+	 * @param    string $description
238
+	 * @return    string
239
+	 */
240
+	private static function _escape_ICal_description($description = '')
241
+	{
242
+
243
+		// Escape special chars within the description
244
+		$description = EED_Ical::_escape_ICal_data($description);
245
+
246
+		// Remove line breaks and output in iCal format
247
+		$description = str_replace(array("\r\n", "\n"), '\n', $description);
248
+
249
+		return $description;
250
+	}
251 251
 }
Please login to merge, or discard this patch.
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -87,24 +87,24 @@  discard block
 block discarded – undo
87 87
             switch ($iCal_type) {
88 88
                 // submit buttons appear as buttons and are very compatible with a theme's style
89 89
                 case 'submit':
90
-                    $html .= '<form id="download-iCal-frm-' . $datetime->ID();
91
-                    $html .= '" class="download-iCal-frm" action="' . $URL . '" method="post" >';
90
+                    $html .= '<form id="download-iCal-frm-'.$datetime->ID();
91
+                    $html .= '" class="download-iCal-frm" action="'.$URL.'" method="post" >';
92 92
                     $html .= '<input type="submit" class="ee-ical-sbmt" value="&#xf145;" title="';
93
-                    $html .= esc_html__('Add to iCal Calendar', 'event_espresso') . '"/>';
93
+                    $html .= esc_html__('Add to iCal Calendar', 'event_espresso').'"/>';
94 94
                     $html .= '</form>';
95 95
                     break;
96 96
                 // buttons are just links that have been styled to appear as buttons,
97 97
                 // but may not be blend with a theme as well as submit buttons
98 98
                 case 'button':
99
-                    $html .= '<a class="ee-ical-btn small ee-button ee-roundish" href="' . $URL;
100
-                    $html .= '" title="' . esc_html__('Add to iCal Calendar', 'event_espresso') . '">';
99
+                    $html .= '<a class="ee-ical-btn small ee-button ee-roundish" href="'.$URL;
100
+                    $html .= '" title="'.esc_html__('Add to iCal Calendar', 'event_espresso').'">';
101 101
                     $html .= ' <span class="dashicons dashicons-calendar"></span>';
102 102
                     $html .= '</a>';
103 103
                     break;
104 104
                 // links are just links that use the calendar dashicon
105 105
                 case 'icon':
106
-                    $html .= '<a class="ee-ical-lnk" href="' . $URL . '" title="';
107
-                    $html .= esc_html__('Add to iCal Calendar', 'event_espresso') . '">';
106
+                    $html .= '<a class="ee-ical-lnk" href="'.$URL.'" title="';
107
+                    $html .= esc_html__('Add to iCal Calendar', 'event_espresso').'">';
108 108
                     $html .= ' <span class="dashicons dashicons-calendar"></span>';
109 109
                     $html .= '</a>';
110 110
                     break;
@@ -146,7 +146,7 @@  discard block
 block discarded – undo
146 146
                     }
147 147
 
148 148
                     // Generate filename
149
-                    $filename = $event->slug() . '-' . $datetime->start_date('Y-m-d') . '.ics';
149
+                    $filename = $event->slug().'-'.$datetime->start_date('Y-m-d').'.ics';
150 150
 
151 151
                     // Check the datetime status has not been cancelled and set the ics value accordingly
152 152
                     $status = $datetime->get_active_status();
@@ -155,7 +155,7 @@  discard block
 block discarded – undo
155 155
                     // Create array of ics details, escape strings, convert timestamps to ics format, etc
156 156
                     $ics_data = array(
157 157
                         'ORGANIZER_NAME' => EE_Registry::instance()->CFG->organization->name,
158
-                        'UID'            => md5($event->name() . $event->ID() . $datetime->ID()),
158
+                        'UID'            => md5($event->name().$event->ID().$datetime->ID()),
159 159
                         'ORGANIZER'      => EE_Registry::instance()->CFG->organization->email,
160 160
                         'DTSTAMP'        => date(EED_Ical::iCal_datetime_format),
161 161
                         'LOCATION'       => $location,
@@ -176,9 +176,9 @@  discard block
 block discarded – undo
176 176
                     foreach ($ics_data as $key => $value) {
177 177
                         // Description is escaped differently from all all values
178 178
                         if ($key === 'DESCRIPTION') {
179
-                            $ics_data[ $key ] = EED_Ical::_escape_ICal_description(wp_strip_all_tags($value));
179
+                            $ics_data[$key] = EED_Ical::_escape_ICal_description(wp_strip_all_tags($value));
180 180
                         } else {
181
-                            $ics_data[ $key ] = EED_Ical::_escape_ICal_data($value);
181
+                            $ics_data[$key] = EED_Ical::_escape_ICal_data($value);
182 182
                         }
183 183
                     }
184 184
 
@@ -188,7 +188,7 @@  discard block
 block discarded – undo
188 188
 
189 189
                     // set headers
190 190
                     header('Content-type: text/calendar; charset=utf-8');
191
-                    header('Content-Disposition: attachment; filename="' . $filename . '"');
191
+                    header('Content-Disposition: attachment; filename="'.$filename.'"');
192 192
                     header('Cache-Control: private, max-age=0, must-revalidate');
193 193
                     header('Pragma: public');
194 194
                     header('Content-Type: application/octet-stream');
@@ -206,7 +206,7 @@  discard block
 block discarded – undo
206 206
 
207 207
                     // Output all remaining values from ics_data.
208 208
                     foreach ($ics_data as $key => $value) {
209
-                        echo $key . ':' . $value . "\r\n";
209
+                        echo $key.':'.$value."\r\n";
210 210
                     }
211 211
 
212 212
                     echo "END:VEVENT\r\n";
Please login to merge, or discard this patch.
admin_pages/events/Events_Admin_Page.core.php 2 patches
Spacing   +65 added lines, -65 removed lines patch added patch discarded remove patch
@@ -548,11 +548,11 @@  discard block
 block discarded – undo
548 548
     {
549 549
         wp_register_style(
550 550
             'events-admin-css',
551
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
551
+            EVENTS_ASSETS_URL.'events-admin-page.css',
552 552
             array(),
553 553
             EVENT_ESPRESSO_VERSION
554 554
         );
555
-        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
555
+        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL.'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
556 556
         wp_enqueue_style('events-admin-css');
557 557
         wp_enqueue_style('ee-cat-admin');
558 558
         // todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
@@ -560,7 +560,7 @@  discard block
 block discarded – undo
560 560
         // scripts
561 561
         wp_register_script(
562 562
             'event_editor_js',
563
-            EVENTS_ASSETS_URL . 'event_editor.js',
563
+            EVENTS_ASSETS_URL.'event_editor.js',
564 564
             array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
565 565
             EVENT_ESPRESSO_VERSION,
566 566
             true
@@ -586,7 +586,7 @@  discard block
 block discarded – undo
586 586
         wp_enqueue_style('espresso-ui-theme');
587 587
         wp_register_style(
588 588
             'event-editor-css',
589
-            EVENTS_ASSETS_URL . 'event-editor.css',
589
+            EVENTS_ASSETS_URL.'event-editor.css',
590 590
             array('ee-admin-css'),
591 591
             EVENT_ESPRESSO_VERSION
592 592
         );
@@ -594,7 +594,7 @@  discard block
 block discarded – undo
594 594
         // scripts
595 595
         wp_register_script(
596 596
             'event-datetime-metabox',
597
-            EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
597
+            EVENTS_ASSETS_URL.'event-datetime-metabox.js',
598 598
             array('event_editor_js', 'ee-datepicker'),
599 599
             EVENT_ESPRESSO_VERSION
600 600
         );
@@ -663,7 +663,7 @@  discard block
 block discarded – undo
663 663
     public function verify_event_edit($event = null, $req_type = '')
664 664
     {
665 665
         // don't need to do this when processing
666
-        if (! empty($req_type)) {
666
+        if ( ! empty($req_type)) {
667 667
             return;
668 668
         }
669 669
         // no event?
@@ -672,7 +672,7 @@  discard block
 block discarded – undo
672 672
             $event = $this->_cpt_model_obj;
673 673
         }
674 674
         // STILL no event?
675
-        if (! $event instanceof EE_Event) {
675
+        if ( ! $event instanceof EE_Event) {
676 676
             return;
677 677
         }
678 678
         $orig_status = $event->status();
@@ -710,7 +710,7 @@  discard block
 block discarded – undo
710 710
             );
711 711
         }
712 712
         // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
713
-        if (! $event->tickets_on_sale()) {
713
+        if ( ! $event->tickets_on_sale()) {
714 714
             return;
715 715
         }
716 716
         // made it here so show warning
@@ -755,7 +755,7 @@  discard block
 block discarded – undo
755 755
     {
756 756
         $has_timezone_string = get_option('timezone_string');
757 757
         // only nag them about setting their timezone if it's their first event, and they haven't already done it
758
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
758
+        if ( ! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
759 759
             EE_Error::add_attention(
760 760
                 sprintf(
761 761
                     __(
@@ -839,31 +839,31 @@  discard block
 block discarded – undo
839 839
         $items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
840 840
         $statuses = array(
841 841
             'sold_out_status'  => array(
842
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
842
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::sold_out,
843 843
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
844 844
             ),
845 845
             'active_status'    => array(
846
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
846
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::active,
847 847
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
848 848
             ),
849 849
             'upcoming_status'  => array(
850
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
850
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::upcoming,
851 851
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
852 852
             ),
853 853
             'postponed_status' => array(
854
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
854
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::postponed,
855 855
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
856 856
             ),
857 857
             'cancelled_status' => array(
858
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
858
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::cancelled,
859 859
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
860 860
             ),
861 861
             'expired_status'   => array(
862
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
862
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::expired,
863 863
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
864 864
             ),
865 865
             'inactive_status'  => array(
866
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
866
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::inactive,
867 867
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
868 868
             ),
869 869
         );
@@ -877,7 +877,7 @@  discard block
 block discarded – undo
877 877
      */
878 878
     private function _event_model()
879 879
     {
880
-        if (! $this->_event_model instanceof EEM_Event) {
880
+        if ( ! $this->_event_model instanceof EEM_Event) {
881 881
             $this->_event_model = EE_Registry::instance()->load_model('Event');
882 882
         }
883 883
         return $this->_event_model;
@@ -897,7 +897,7 @@  discard block
 block discarded – undo
897 897
     public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
898 898
     {
899 899
         // make sure this is only when editing
900
-        if (! empty($id)) {
900
+        if ( ! empty($id)) {
901 901
             $post = get_post($id);
902 902
             $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
903 903
                        . esc_html__('Shortcode', 'event_espresso')
@@ -931,7 +931,7 @@  discard block
 block discarded – undo
931 931
                     'button'
932 932
                 );
933 933
         $this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
934
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
934
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
935 935
             'create_new',
936 936
             'add',
937 937
             array(),
@@ -1071,7 +1071,7 @@  discard block
 block discarded – undo
1071 1071
      */
1072 1072
     protected function _default_venue_update(\EE_Event $evtobj, $data)
1073 1073
     {
1074
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1074
+        require_once(EE_MODELS.'EEM_Venue.model.php');
1075 1075
         $venue_model = EE_Registry::instance()->load_model('Venue');
1076 1076
         $rows_affected = null;
1077 1077
         $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
@@ -1102,7 +1102,7 @@  discard block
 block discarded – undo
1102 1102
             'status'              => 'publish',
1103 1103
         );
1104 1104
         // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1105
-        if (! empty($venue_id)) {
1105
+        if ( ! empty($venue_id)) {
1106 1106
             $update_where = array($venue_model->primary_key_name() => $venue_id);
1107 1107
             $rows_affected = $venue_model->update($venue_array, array($update_where));
1108 1108
             // we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
@@ -1144,7 +1144,7 @@  discard block
 block discarded – undo
1144 1144
                 'DTT_order'     => $row,
1145 1145
             );
1146 1146
             // if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1147
-            if (! empty($dtt['DTT_ID'])) {
1147
+            if ( ! empty($dtt['DTT_ID'])) {
1148 1148
                 $DTM = EE_Registry::instance()
1149 1149
                                   ->load_model('Datetime', array($evtobj->get_timezone()))
1150 1150
                                   ->get_one_by_ID($dtt['DTT_ID']);
@@ -1154,7 +1154,7 @@  discard block
 block discarded – undo
1154 1154
                     $DTM->set($field, $value);
1155 1155
                 }
1156 1156
                 // make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1157
-                $saved_dtts[ $DTM->ID() ] = $DTM;
1157
+                $saved_dtts[$DTM->ID()] = $DTM;
1158 1158
             } else {
1159 1159
                 $DTM = EE_Registry::instance()->load_class(
1160 1160
                     'Datetime',
@@ -1187,14 +1187,14 @@  discard block
 block discarded – undo
1187 1187
         foreach ($data['edit_tickets'] as $row => $tkt) {
1188 1188
             $incoming_date_formats = array('Y-m-d', 'h:i a');
1189 1189
             $update_prices = false;
1190
-            $ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1191
-                ? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1190
+            $ticket_price = isset($data['edit_prices'][$row][1]['PRC_amount'])
1191
+                ? $data['edit_prices'][$row][1]['PRC_amount'] : 0;
1192 1192
             // trim inputs to ensure any excess whitespace is removed.
1193 1193
             $tkt = array_map('trim', $tkt);
1194 1194
             if (empty($tkt['TKT_start_date'])) {
1195 1195
                 // let's use now in the set timezone.
1196 1196
                 $now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1197
-                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1197
+                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0].' '.$incoming_date_formats[1]);
1198 1198
             }
1199 1199
             if (empty($tkt['TKT_end_date'])) {
1200 1200
                 // use the start date of the first datetime
@@ -1229,7 +1229,7 @@  discard block
 block discarded – undo
1229 1229
             // if we have a TKT_ID then we need to get that existing TKT_obj and update it
1230 1230
             // we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1231 1231
             // keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1232
-            if (! empty($tkt['TKT_ID'])) {
1232
+            if ( ! empty($tkt['TKT_ID'])) {
1233 1233
                 $TKT = EE_Registry::instance()
1234 1234
                                   ->load_model('Ticket', array($evtobj->get_timezone()))
1235 1235
                                   ->get_one_by_ID($tkt['TKT_ID']);
@@ -1264,7 +1264,7 @@  discard block
 block discarded – undo
1264 1264
                         $TKT->set('TKT_deleted', 1);
1265 1265
                         $TKT->save();
1266 1266
                         // make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1267
-                        $saved_tickets[ $TKT->ID() ] = $TKT;
1267
+                        $saved_tickets[$TKT->ID()] = $TKT;
1268 1268
                         // create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1269 1269
                         $TKT = clone $TKT;
1270 1270
                         $TKT->set('TKT_ID', 0);
@@ -1309,9 +1309,9 @@  discard block
 block discarded – undo
1309 1309
             }
1310 1310
             // initially let's add the ticket to the dtt
1311 1311
             $saved_dtt->_add_relation_to($TKT, 'Ticket');
1312
-            $saved_tickets[ $TKT->ID() ] = $TKT;
1312
+            $saved_tickets[$TKT->ID()] = $TKT;
1313 1313
             // add prices to ticket
1314
-            $this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1314
+            $this->_add_prices_to_ticket($data['edit_prices'][$row], $TKT, $update_prices);
1315 1315
         }
1316 1316
         // however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1317 1317
         $old_tickets = isset($old_tickets[0]) && $old_tickets[0] == '' ? array() : $old_tickets;
@@ -1468,7 +1468,7 @@  discard block
 block discarded – undo
1468 1468
         $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1469 1469
         // load template
1470 1470
         EEH_Template::display_template(
1471
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1471
+            EVENTS_TEMPLATE_PATH.'event_publish_box_extras.template.php',
1472 1472
             $publish_box_extra_args
1473 1473
         );
1474 1474
     }
@@ -1560,7 +1560,7 @@  discard block
 block discarded – undo
1560 1560
                     'default_where_conditions' => 'none',
1561 1561
                 )
1562 1562
             );
1563
-            if (! empty($related_tickets)) {
1563
+            if ( ! empty($related_tickets)) {
1564 1564
                 $template_args['total_ticket_rows'] = count($related_tickets);
1565 1565
                 $row = 0;
1566 1566
                 foreach ($related_tickets as $ticket) {
@@ -1594,7 +1594,7 @@  discard block
 block discarded – undo
1594 1594
         );
1595 1595
         $template = apply_filters(
1596 1596
             'FHEE__Events_Admin_Page__ticket_metabox__template',
1597
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1597
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_main.template.php'
1598 1598
         );
1599 1599
         EEH_Template::display_template($template, $template_args);
1600 1600
     }
@@ -1612,7 +1612,7 @@  discard block
 block discarded – undo
1612 1612
     private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1613 1613
     {
1614 1614
         $template_args = array(
1615
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1615
+            'tkt_status_class'    => ' tkt-status-'.$ticket->ticket_status(),
1616 1616
             'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1617 1617
                 : '',
1618 1618
             'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
@@ -1624,10 +1624,10 @@  discard block
 block discarded – undo
1624 1624
             'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1625 1625
             'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1626 1626
             'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1627
-            'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1628
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1627
+            'trash_icon'          => ($skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')))
1628
+                                     && ( ! empty($ticket) && $ticket->get('TKT_sold') === 0)
1629 1629
                 ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1630
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1630
+            'disabled'            => $skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1631 1631
                 : ' disabled=disabled',
1632 1632
         );
1633 1633
         $price = $ticket->ID() !== 0
@@ -1654,7 +1654,7 @@  discard block
 block discarded – undo
1654 1654
                     array('order_by' => array('DTT_EVT_start' => 'ASC'))
1655 1655
                 )
1656 1656
                 : null;
1657
-            if (! empty($earliest_dtt)) {
1657
+            if ( ! empty($earliest_dtt)) {
1658 1658
                 $template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1659 1659
             } else {
1660 1660
                 $template_args['TKT_end_date'] = date(
@@ -1666,7 +1666,7 @@  discard block
 block discarded – undo
1666 1666
         $template_args = array_merge($template_args, $price_args);
1667 1667
         $template = apply_filters(
1668 1668
             'FHEE__Events_Admin_Page__get_ticket_row__template',
1669
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1669
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_ticket_row.template.php',
1670 1670
             $ticket
1671 1671
         );
1672 1672
         return EEH_Template::display_template($template, $template_args, true);
@@ -1720,7 +1720,7 @@  discard block
 block discarded – undo
1720 1720
             $default_reg_status_values
1721 1721
         );
1722 1722
         EEH_Template::display_template(
1723
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1723
+            EVENTS_TEMPLATE_PATH.'event_registration_options.template.php',
1724 1724
             $template_args
1725 1725
         );
1726 1726
     }
@@ -1742,7 +1742,7 @@  discard block
 block discarded – undo
1742 1742
     {
1743 1743
         $EEME = $this->_event_model();
1744 1744
         $offset = ($current_page - 1) * $per_page;
1745
-        $limit = $count ? null : $offset . ',' . $per_page;
1745
+        $limit = $count ? null : $offset.','.$per_page;
1746 1746
         $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1747 1747
         $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC";
1748 1748
         if (isset($this->_req_data['month_range'])) {
@@ -1771,7 +1771,7 @@  discard block
 block discarded – undo
1771 1771
         // categories?
1772 1772
         $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1773 1773
             ? $this->_req_data['EVT_CAT'] : null;
1774
-        if (! empty($category)) {
1774
+        if ( ! empty($category)) {
1775 1775
             $where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1776 1776
             $where['Term_Taxonomy.term_id'] = $category;
1777 1777
         }
@@ -1779,7 +1779,7 @@  discard block
 block discarded – undo
1779 1779
         $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1780 1780
         if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') {
1781 1781
             $DateTime = new DateTime(
1782
-                $year_r . '-' . $month_r . '-01 00:00:00',
1782
+                $year_r.'-'.$month_r.'-01 00:00:00',
1783 1783
                 new DateTimeZone('UTC')
1784 1784
             );
1785 1785
             $start = $DateTime->getTimestamp();
@@ -1805,11 +1805,11 @@  discard block
 block discarded – undo
1805 1805
                             ->format(implode(' ', $start_formats));
1806 1806
             $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1807 1807
         }
1808
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1808
+        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1809 1809
             $where['EVT_wp_user'] = get_current_user_id();
1810 1810
         } else {
1811
-            if (! isset($where['status'])) {
1812
-                if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1811
+            if ( ! isset($where['status'])) {
1812
+                if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1813 1813
                     $where['OR'] = array(
1814 1814
                         'status*restrict_private' => array('!=', 'private'),
1815 1815
                         'AND'                     => array(
@@ -1829,7 +1829,7 @@  discard block
 block discarded – undo
1829 1829
         }
1830 1830
         // search query handling
1831 1831
         if (isset($this->_req_data['s'])) {
1832
-            $search_string = '%' . $this->_req_data['s'] . '%';
1832
+            $search_string = '%'.$this->_req_data['s'].'%';
1833 1833
             $where['OR'] = array(
1834 1834
                 'EVT_name'       => array('LIKE', $search_string),
1835 1835
                 'EVT_desc'       => array('LIKE', $search_string),
@@ -1925,7 +1925,7 @@  discard block
 block discarded – undo
1925 1925
             // clean status
1926 1926
             $event_status = sanitize_key($event_status);
1927 1927
             // grab status
1928
-            if (! empty($event_status)) {
1928
+            if ( ! empty($event_status)) {
1929 1929
                 $success = $this->_change_event_status($EVT_ID, $event_status);
1930 1930
             } else {
1931 1931
                 $success = false;
@@ -1962,7 +1962,7 @@  discard block
 block discarded – undo
1962 1962
         // clean status
1963 1963
         $event_status = sanitize_key($event_status);
1964 1964
         // grab status
1965
-        if (! empty($event_status)) {
1965
+        if ( ! empty($event_status)) {
1966 1966
             $success = true;
1967 1967
             // determine the event id and set to array.
1968 1968
             $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
@@ -2009,7 +2009,7 @@  discard block
 block discarded – undo
2009 2009
     private function _change_event_status($EVT_ID = 0, $event_status = '')
2010 2010
     {
2011 2011
         // grab event id
2012
-        if (! $EVT_ID) {
2012
+        if ( ! $EVT_ID) {
2013 2013
             $msg = esc_html__(
2014 2014
                 'An error occurred. No Event ID or an invalid Event ID was received.',
2015 2015
                 'event_espresso'
@@ -2075,8 +2075,8 @@  discard block
 block discarded – undo
2075 2075
             // get list of events with no prices
2076 2076
             $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2077 2077
             // remove this event from the list of events with no prices
2078
-            if (isset($espresso_no_ticket_prices[ $EVT_ID ])) {
2079
-                unset($espresso_no_ticket_prices[ $EVT_ID ]);
2078
+            if (isset($espresso_no_ticket_prices[$EVT_ID])) {
2079
+                unset($espresso_no_ticket_prices[$EVT_ID]);
2080 2080
             }
2081 2081
             update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2082 2082
         } else {
@@ -2118,7 +2118,7 @@  discard block
 block discarded – undo
2118 2118
                 $results = $this->_permanently_delete_event($EVT_ID);
2119 2119
                 $success = $results !== false ? $success : false;
2120 2120
                 // remove this event from the list of events with no prices
2121
-                unset($espresso_no_ticket_prices[ $EVT_ID ]);
2121
+                unset($espresso_no_ticket_prices[$EVT_ID]);
2122 2122
             } else {
2123 2123
                 $success = false;
2124 2124
                 $msg = esc_html__(
@@ -2145,7 +2145,7 @@  discard block
 block discarded – undo
2145 2145
     private function _permanently_delete_event($EVT_ID = 0)
2146 2146
     {
2147 2147
         // grab event id
2148
-        if (! $EVT_ID) {
2148
+        if ( ! $EVT_ID) {
2149 2149
             $msg = esc_html__(
2150 2150
                 'An error occurred. No Event ID or an invalid Event ID was received.',
2151 2151
                 'event_espresso'
@@ -2153,12 +2153,12 @@  discard block
 block discarded – undo
2153 2153
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2154 2154
             return false;
2155 2155
         }
2156
-        if (! $this->_cpt_model_obj instanceof EE_Event
2156
+        if ( ! $this->_cpt_model_obj instanceof EE_Event
2157 2157
             || $this->_cpt_model_obj->ID() !== $EVT_ID
2158 2158
         ) {
2159 2159
             $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2160 2160
         }
2161
-        if (! $this->_cpt_model_obj instanceof EE_Event) {
2161
+        if ( ! $this->_cpt_model_obj instanceof EE_Event) {
2162 2162
             return false;
2163 2163
         }
2164 2164
         // need to delete related tickets and prices first.
@@ -2180,7 +2180,7 @@  discard block
 block discarded – undo
2180 2180
         }
2181 2181
         // any attached question groups?
2182 2182
         $question_groups = $this->_cpt_model_obj->get_many_related('Question_Group');
2183
-        if (! empty($question_groups)) {
2183
+        if ( ! empty($question_groups)) {
2184 2184
             foreach ($question_groups as $question_group) {
2185 2185
                 $this->_cpt_model_obj->_remove_relation_to($question_group, 'Question_Group');
2186 2186
             }
@@ -2391,7 +2391,7 @@  discard block
 block discarded – undo
2391 2391
                                                 . esc_html__(
2392 2392
                                                     'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2393 2393
                                                     'event_espresso'
2394
-                                                ) . '</strong>';
2394
+                                                ).'</strong>';
2395 2395
         $this->display_admin_caf_preview_page('template_settings_tab');
2396 2396
     }
2397 2397
 
@@ -2411,12 +2411,12 @@  discard block
 block discarded – undo
2411 2411
         // set default category object
2412 2412
         $this->_set_empty_category_object();
2413 2413
         // only set if we've got an id
2414
-        if (! isset($this->_req_data['EVT_CAT_ID'])) {
2414
+        if ( ! isset($this->_req_data['EVT_CAT_ID'])) {
2415 2415
             return;
2416 2416
         }
2417 2417
         $category_id = absint($this->_req_data['EVT_CAT_ID']);
2418 2418
         $term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2419
-        if (! empty($term)) {
2419
+        if ( ! empty($term)) {
2420 2420
             $this->_category->category_name = $term->name;
2421 2421
             $this->_category->category_identifier = $term->slug;
2422 2422
             $this->_category->category_desc = $term->description;
@@ -2444,7 +2444,7 @@  discard block
 block discarded – undo
2444 2444
     {
2445 2445
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2446 2446
         $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2447
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2447
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
2448 2448
             'add_category',
2449 2449
             'add_category',
2450 2450
             array(),
@@ -2518,7 +2518,7 @@  discard block
 block discarded – undo
2518 2518
             'disable'                  => '',
2519 2519
             'disabled_message'         => false,
2520 2520
         );
2521
-        $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2521
+        $template = EVENTS_TEMPLATE_PATH.'event_category_details.template.php';
2522 2522
         return EEH_Template::display_template($template, $template_args, true);
2523 2523
     }
2524 2524
 
@@ -2603,7 +2603,7 @@  discard block
 block discarded – undo
2603 2603
         $insert_ids = $update
2604 2604
             ? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2605 2605
             : wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2606
-        if (! is_array($insert_ids)) {
2606
+        if ( ! is_array($insert_ids)) {
2607 2607
             $msg = esc_html__(
2608 2608
                 'An error occurred and the category has not been saved to the database.',
2609 2609
                 'event_espresso'
@@ -2634,7 +2634,7 @@  discard block
 block discarded – undo
2634 2634
         $limit = ($current_page - 1) * $per_page;
2635 2635
         $where = array('taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2636 2636
         if (isset($this->_req_data['s'])) {
2637
-            $sstr = '%' . $this->_req_data['s'] . '%';
2637
+            $sstr = '%'.$this->_req_data['s'].'%';
2638 2638
             $where['OR'] = array(
2639 2639
                 'Term.name'   => array('LIKE', $sstr),
2640 2640
                 'description' => array('LIKE', $sstr),
@@ -2643,7 +2643,7 @@  discard block
 block discarded – undo
2643 2643
         $query_params = array(
2644 2644
             $where,
2645 2645
             'order_by'   => array($orderby => $order),
2646
-            'limit'      => $limit . ',' . $per_page,
2646
+            'limit'      => $limit.','.$per_page,
2647 2647
             'force_join' => array('Term'),
2648 2648
         );
2649 2649
         $categories = $count
Please login to merge, or discard this patch.
Indentation   +2671 added lines, -2671 removed lines patch added patch discarded remove patch
@@ -12,2675 +12,2675 @@
 block discarded – undo
12 12
 class Events_Admin_Page extends EE_Admin_Page_CPT
13 13
 {
14 14
 
15
-    /**
16
-     * This will hold the event object for event_details screen.
17
-     *
18
-     * @access protected
19
-     * @var EE_Event $_event
20
-     */
21
-    protected $_event;
22
-
23
-
24
-    /**
25
-     * This will hold the category object for category_details screen.
26
-     *
27
-     * @var stdClass $_category
28
-     */
29
-    protected $_category;
30
-
31
-
32
-    /**
33
-     * This will hold the event model instance
34
-     *
35
-     * @var EEM_Event $_event_model
36
-     */
37
-    protected $_event_model;
38
-
39
-
40
-    /**
41
-     * @var EE_Event
42
-     */
43
-    protected $_cpt_model_obj = false;
44
-
45
-
46
-    /**
47
-     * Initialize page props for this admin page group.
48
-     */
49
-    protected function _init_page_props()
50
-    {
51
-        $this->page_slug = EVENTS_PG_SLUG;
52
-        $this->page_label = EVENTS_LABEL;
53
-        $this->_admin_base_url = EVENTS_ADMIN_URL;
54
-        $this->_admin_base_path = EVENTS_ADMIN;
55
-        $this->_cpt_model_names = array(
56
-            'create_new' => 'EEM_Event',
57
-            'edit'       => 'EEM_Event',
58
-        );
59
-        $this->_cpt_edit_routes = array(
60
-            'espresso_events' => 'edit',
61
-        );
62
-        add_action(
63
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
64
-            array($this, 'verify_event_edit'),
65
-            10,
66
-            2
67
-        );
68
-    }
69
-
70
-
71
-    /**
72
-     * Sets the ajax hooks used for this admin page group.
73
-     */
74
-    protected function _ajax_hooks()
75
-    {
76
-        add_action('wp_ajax_ee_save_timezone_setting', array($this, 'save_timezonestring_setting'));
77
-    }
78
-
79
-
80
-    /**
81
-     * Sets the page properties for this admin page group.
82
-     */
83
-    protected function _define_page_props()
84
-    {
85
-        $this->_admin_page_title = EVENTS_LABEL;
86
-        $this->_labels = array(
87
-            'buttons'      => array(
88
-                'add'             => esc_html__('Add New Event', 'event_espresso'),
89
-                'edit'            => esc_html__('Edit Event', 'event_espresso'),
90
-                'delete'          => esc_html__('Delete Event', 'event_espresso'),
91
-                'add_category'    => esc_html__('Add New Category', 'event_espresso'),
92
-                'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
93
-                'delete_category' => esc_html__('Delete Category', 'event_espresso'),
94
-            ),
95
-            'editor_title' => array(
96
-                'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
97
-            ),
98
-            'publishbox'   => array(
99
-                'create_new'        => esc_html__('Save New Event', 'event_espresso'),
100
-                'edit'              => esc_html__('Update Event', 'event_espresso'),
101
-                'add_category'      => esc_html__('Save New Category', 'event_espresso'),
102
-                'edit_category'     => esc_html__('Update Category', 'event_espresso'),
103
-                'template_settings' => esc_html__('Update Settings', 'event_espresso'),
104
-            ),
105
-        );
106
-    }
107
-
108
-
109
-    /**
110
-     * Sets the page routes property for this admin page group.
111
-     */
112
-    protected function _set_page_routes()
113
-    {
114
-        // load formatter helper
115
-        // load field generator helper
116
-        // is there a evt_id in the request?
117
-        $evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
118
-            ? $this->_req_data['EVT_ID']
119
-            : 0;
120
-        $evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
121
-        $this->_page_routes = array(
122
-            'default'                       => array(
123
-                'func'       => '_events_overview_list_table',
124
-                'capability' => 'ee_read_events',
125
-            ),
126
-            'create_new'                    => array(
127
-                'func'       => '_create_new_cpt_item',
128
-                'capability' => 'ee_edit_events',
129
-            ),
130
-            'edit'                          => array(
131
-                'func'       => '_edit_cpt_item',
132
-                'capability' => 'ee_edit_event',
133
-                'obj_id'     => $evt_id,
134
-            ),
135
-            'copy_event'                    => array(
136
-                'func'       => '_copy_events',
137
-                'capability' => 'ee_edit_event',
138
-                'obj_id'     => $evt_id,
139
-                'noheader'   => true,
140
-            ),
141
-            'trash_event'                   => array(
142
-                'func'       => '_trash_or_restore_event',
143
-                'args'       => array('event_status' => 'trash'),
144
-                'capability' => 'ee_delete_event',
145
-                'obj_id'     => $evt_id,
146
-                'noheader'   => true,
147
-            ),
148
-            'trash_events'                  => array(
149
-                'func'       => '_trash_or_restore_events',
150
-                'args'       => array('event_status' => 'trash'),
151
-                'capability' => 'ee_delete_events',
152
-                'noheader'   => true,
153
-            ),
154
-            'restore_event'                 => array(
155
-                'func'       => '_trash_or_restore_event',
156
-                'args'       => array('event_status' => 'draft'),
157
-                'capability' => 'ee_delete_event',
158
-                'obj_id'     => $evt_id,
159
-                'noheader'   => true,
160
-            ),
161
-            'restore_events'                => array(
162
-                'func'       => '_trash_or_restore_events',
163
-                'args'       => array('event_status' => 'draft'),
164
-                'capability' => 'ee_delete_events',
165
-                'noheader'   => true,
166
-            ),
167
-            'delete_event'                  => array(
168
-                'func'       => '_delete_event',
169
-                'capability' => 'ee_delete_event',
170
-                'obj_id'     => $evt_id,
171
-                'noheader'   => true,
172
-            ),
173
-            'delete_events'                 => array(
174
-                'func'       => '_delete_events',
175
-                'capability' => 'ee_delete_events',
176
-                'noheader'   => true,
177
-            ),
178
-            'view_report'                   => array(
179
-                'func'      => '_view_report',
180
-                'capablity' => 'ee_edit_events',
181
-            ),
182
-            'default_event_settings'        => array(
183
-                'func'       => '_default_event_settings',
184
-                'capability' => 'manage_options',
185
-            ),
186
-            'update_default_event_settings' => array(
187
-                'func'       => '_update_default_event_settings',
188
-                'capability' => 'manage_options',
189
-                'noheader'   => true,
190
-            ),
191
-            'template_settings'             => array(
192
-                'func'       => '_template_settings',
193
-                'capability' => 'manage_options',
194
-            ),
195
-            // event category tab related
196
-            'add_category'                  => array(
197
-                'func'       => '_category_details',
198
-                'capability' => 'ee_edit_event_category',
199
-                'args'       => array('add'),
200
-            ),
201
-            'edit_category'                 => array(
202
-                'func'       => '_category_details',
203
-                'capability' => 'ee_edit_event_category',
204
-                'args'       => array('edit'),
205
-            ),
206
-            'delete_categories'             => array(
207
-                'func'       => '_delete_categories',
208
-                'capability' => 'ee_delete_event_category',
209
-                'noheader'   => true,
210
-            ),
211
-            'delete_category'               => array(
212
-                'func'       => '_delete_categories',
213
-                'capability' => 'ee_delete_event_category',
214
-                'noheader'   => true,
215
-            ),
216
-            'insert_category'               => array(
217
-                'func'       => '_insert_or_update_category',
218
-                'args'       => array('new_category' => true),
219
-                'capability' => 'ee_edit_event_category',
220
-                'noheader'   => true,
221
-            ),
222
-            'update_category'               => array(
223
-                'func'       => '_insert_or_update_category',
224
-                'args'       => array('new_category' => false),
225
-                'capability' => 'ee_edit_event_category',
226
-                'noheader'   => true,
227
-            ),
228
-            'category_list'                 => array(
229
-                'func'       => '_category_list_table',
230
-                'capability' => 'ee_manage_event_categories',
231
-            ),
232
-        );
233
-    }
234
-
235
-
236
-    /**
237
-     * Set the _page_config property for this admin page group.
238
-     */
239
-    protected function _set_page_config()
240
-    {
241
-        $this->_page_config = array(
242
-            'default'                => array(
243
-                'nav'           => array(
244
-                    'label' => esc_html__('Overview', 'event_espresso'),
245
-                    'order' => 10,
246
-                ),
247
-                'list_table'    => 'Events_Admin_List_Table',
248
-                'help_tabs'     => array(
249
-                    'events_overview_help_tab'                       => array(
250
-                        'title'    => esc_html__('Events Overview', 'event_espresso'),
251
-                        'filename' => 'events_overview',
252
-                    ),
253
-                    'events_overview_table_column_headings_help_tab' => array(
254
-                        'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
255
-                        'filename' => 'events_overview_table_column_headings',
256
-                    ),
257
-                    'events_overview_filters_help_tab'               => array(
258
-                        'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
259
-                        'filename' => 'events_overview_filters',
260
-                    ),
261
-                    'events_overview_view_help_tab'                  => array(
262
-                        'title'    => esc_html__('Events Overview Views', 'event_espresso'),
263
-                        'filename' => 'events_overview_views',
264
-                    ),
265
-                    'events_overview_other_help_tab'                 => array(
266
-                        'title'    => esc_html__('Events Overview Other', 'event_espresso'),
267
-                        'filename' => 'events_overview_other',
268
-                    ),
269
-                ),
270
-                'help_tour'     => array(
271
-                    'Event_Overview_Help_Tour',
272
-                    // 'New_Features_Test_Help_Tour' for testing multiple help tour
273
-                ),
274
-                'qtips'         => array(
275
-                    'EE_Event_List_Table_Tips',
276
-                ),
277
-                'require_nonce' => false,
278
-            ),
279
-            'create_new'             => array(
280
-                'nav'           => array(
281
-                    'label'      => esc_html__('Add Event', 'event_espresso'),
282
-                    'order'      => 5,
283
-                    'persistent' => false,
284
-                ),
285
-                'metaboxes'     => array('_register_event_editor_meta_boxes'),
286
-                'help_tabs'     => array(
287
-                    'event_editor_help_tab'                            => array(
288
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
289
-                        'filename' => 'event_editor',
290
-                    ),
291
-                    'event_editor_title_richtexteditor_help_tab'       => array(
292
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
293
-                        'filename' => 'event_editor_title_richtexteditor',
294
-                    ),
295
-                    'event_editor_venue_details_help_tab'              => array(
296
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
297
-                        'filename' => 'event_editor_venue_details',
298
-                    ),
299
-                    'event_editor_event_datetimes_help_tab'            => array(
300
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
301
-                        'filename' => 'event_editor_event_datetimes',
302
-                    ),
303
-                    'event_editor_event_tickets_help_tab'              => array(
304
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
305
-                        'filename' => 'event_editor_event_tickets',
306
-                    ),
307
-                    'event_editor_event_registration_options_help_tab' => array(
308
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
309
-                        'filename' => 'event_editor_event_registration_options',
310
-                    ),
311
-                    'event_editor_tags_categories_help_tab'            => array(
312
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
313
-                        'filename' => 'event_editor_tags_categories',
314
-                    ),
315
-                    'event_editor_questions_registrants_help_tab'      => array(
316
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
317
-                        'filename' => 'event_editor_questions_registrants',
318
-                    ),
319
-                    'event_editor_save_new_event_help_tab'             => array(
320
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
321
-                        'filename' => 'event_editor_save_new_event',
322
-                    ),
323
-                    'event_editor_other_help_tab'                      => array(
324
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
325
-                        'filename' => 'event_editor_other',
326
-                    ),
327
-                ),
328
-                'help_tour'     => array(
329
-                    'Event_Editor_Help_Tour',
330
-                ),
331
-                'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
332
-                'require_nonce' => false,
333
-            ),
334
-            'edit'                   => array(
335
-                'nav'           => array(
336
-                    'label'      => esc_html__('Edit Event', 'event_espresso'),
337
-                    'order'      => 5,
338
-                    'persistent' => false,
339
-                    'url'        => isset($this->_req_data['post'])
340
-                        ? EE_Admin_Page::add_query_args_and_nonce(
341
-                            array('post' => $this->_req_data['post'], 'action' => 'edit'),
342
-                            $this->_current_page_view_url
343
-                        )
344
-                        : $this->_admin_base_url,
345
-                ),
346
-                'metaboxes'     => array('_register_event_editor_meta_boxes'),
347
-                'help_tabs'     => array(
348
-                    'event_editor_help_tab'                            => array(
349
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
350
-                        'filename' => 'event_editor',
351
-                    ),
352
-                    'event_editor_title_richtexteditor_help_tab'       => array(
353
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
354
-                        'filename' => 'event_editor_title_richtexteditor',
355
-                    ),
356
-                    'event_editor_venue_details_help_tab'              => array(
357
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
358
-                        'filename' => 'event_editor_venue_details',
359
-                    ),
360
-                    'event_editor_event_datetimes_help_tab'            => array(
361
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
362
-                        'filename' => 'event_editor_event_datetimes',
363
-                    ),
364
-                    'event_editor_event_tickets_help_tab'              => array(
365
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
366
-                        'filename' => 'event_editor_event_tickets',
367
-                    ),
368
-                    'event_editor_event_registration_options_help_tab' => array(
369
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
370
-                        'filename' => 'event_editor_event_registration_options',
371
-                    ),
372
-                    'event_editor_tags_categories_help_tab'            => array(
373
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
374
-                        'filename' => 'event_editor_tags_categories',
375
-                    ),
376
-                    'event_editor_questions_registrants_help_tab'      => array(
377
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
378
-                        'filename' => 'event_editor_questions_registrants',
379
-                    ),
380
-                    'event_editor_save_new_event_help_tab'             => array(
381
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
382
-                        'filename' => 'event_editor_save_new_event',
383
-                    ),
384
-                    'event_editor_other_help_tab'                      => array(
385
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
386
-                        'filename' => 'event_editor_other',
387
-                    ),
388
-                ),
389
-                'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
390
-                'require_nonce' => false,
391
-            ),
392
-            'default_event_settings' => array(
393
-                'nav'           => array(
394
-                    'label' => esc_html__('Default Settings', 'event_espresso'),
395
-                    'order' => 40,
396
-                ),
397
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
398
-                'labels'        => array(
399
-                    'publishbox' => esc_html__('Update Settings', 'event_espresso'),
400
-                ),
401
-                'help_tabs'     => array(
402
-                    'default_settings_help_tab'        => array(
403
-                        'title'    => esc_html__('Default Event Settings', 'event_espresso'),
404
-                        'filename' => 'events_default_settings',
405
-                    ),
406
-                    'default_settings_status_help_tab' => array(
407
-                        'title'    => esc_html__('Default Registration Status', 'event_espresso'),
408
-                        'filename' => 'events_default_settings_status',
409
-                    ),
410
-                    'default_maximum_tickets_help_tab' => array(
411
-                        'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
412
-                        'filename' => 'events_default_settings_max_tickets',
413
-                    ),
414
-                ),
415
-                'help_tour'     => array('Event_Default_Settings_Help_Tour'),
416
-                'require_nonce' => false,
417
-            ),
418
-            // template settings
419
-            'template_settings'      => array(
420
-                'nav'           => array(
421
-                    'label' => esc_html__('Templates', 'event_espresso'),
422
-                    'order' => 30,
423
-                ),
424
-                'metaboxes'     => $this->_default_espresso_metaboxes,
425
-                'help_tabs'     => array(
426
-                    'general_settings_templates_help_tab' => array(
427
-                        'title'    => esc_html__('Templates', 'event_espresso'),
428
-                        'filename' => 'general_settings_templates',
429
-                    ),
430
-                ),
431
-                'help_tour'     => array('Templates_Help_Tour'),
432
-                'require_nonce' => false,
433
-            ),
434
-            // event category stuff
435
-            'add_category'           => array(
436
-                'nav'           => array(
437
-                    'label'      => esc_html__('Add Category', 'event_espresso'),
438
-                    'order'      => 15,
439
-                    'persistent' => false,
440
-                ),
441
-                'help_tabs'     => array(
442
-                    'add_category_help_tab' => array(
443
-                        'title'    => esc_html__('Add New Event Category', 'event_espresso'),
444
-                        'filename' => 'events_add_category',
445
-                    ),
446
-                ),
447
-                'help_tour'     => array('Event_Add_Category_Help_Tour'),
448
-                'metaboxes'     => array('_publish_post_box'),
449
-                'require_nonce' => false,
450
-            ),
451
-            'edit_category'          => array(
452
-                'nav'           => array(
453
-                    'label'      => esc_html__('Edit Category', 'event_espresso'),
454
-                    'order'      => 15,
455
-                    'persistent' => false,
456
-                    'url'        => isset($this->_req_data['EVT_CAT_ID'])
457
-                        ? add_query_arg(
458
-                            array('EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']),
459
-                            $this->_current_page_view_url
460
-                        )
461
-                        : $this->_admin_base_url,
462
-                ),
463
-                'help_tabs'     => array(
464
-                    'edit_category_help_tab' => array(
465
-                        'title'    => esc_html__('Edit Event Category', 'event_espresso'),
466
-                        'filename' => 'events_edit_category',
467
-                    ),
468
-                ),
469
-                /*'help_tour' => array('Event_Edit_Category_Help_Tour'),*/
470
-                'metaboxes'     => array('_publish_post_box'),
471
-                'require_nonce' => false,
472
-            ),
473
-            'category_list'          => array(
474
-                'nav'           => array(
475
-                    'label' => esc_html__('Categories', 'event_espresso'),
476
-                    'order' => 20,
477
-                ),
478
-                'list_table'    => 'Event_Categories_Admin_List_Table',
479
-                'help_tabs'     => array(
480
-                    'events_categories_help_tab'                       => array(
481
-                        'title'    => esc_html__('Event Categories', 'event_espresso'),
482
-                        'filename' => 'events_categories',
483
-                    ),
484
-                    'events_categories_table_column_headings_help_tab' => array(
485
-                        'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
486
-                        'filename' => 'events_categories_table_column_headings',
487
-                    ),
488
-                    'events_categories_view_help_tab'                  => array(
489
-                        'title'    => esc_html__('Event Categories Views', 'event_espresso'),
490
-                        'filename' => 'events_categories_views',
491
-                    ),
492
-                    'events_categories_other_help_tab'                 => array(
493
-                        'title'    => esc_html__('Event Categories Other', 'event_espresso'),
494
-                        'filename' => 'events_categories_other',
495
-                    ),
496
-                ),
497
-                'help_tour'     => array(
498
-                    'Event_Categories_Help_Tour',
499
-                ),
500
-                'metaboxes'     => $this->_default_espresso_metaboxes,
501
-                'require_nonce' => false,
502
-            ),
503
-        );
504
-    }
505
-
506
-
507
-    /**
508
-     * Used to register any global screen options if necessary for every route in this admin page group.
509
-     */
510
-    protected function _add_screen_options()
511
-    {
512
-    }
513
-
514
-
515
-    /**
516
-     * Implementing the screen options for the 'default' route.
517
-     */
518
-    protected function _add_screen_options_default()
519
-    {
520
-        $this->_per_page_screen_option();
521
-    }
522
-
523
-
524
-    /**
525
-     * Implementing screen options for the category list route.
526
-     */
527
-    protected function _add_screen_options_category_list()
528
-    {
529
-        $page_title = $this->_admin_page_title;
530
-        $this->_admin_page_title = esc_html__('Categories', 'event_espresso');
531
-        $this->_per_page_screen_option();
532
-        $this->_admin_page_title = $page_title;
533
-    }
534
-
535
-
536
-    /**
537
-     * Used to register any global feature pointers for the admin page group.
538
-     */
539
-    protected function _add_feature_pointers()
540
-    {
541
-    }
542
-
543
-
544
-    /**
545
-     * Registers and enqueues any global scripts and styles for the entire admin page group.
546
-     */
547
-    public function load_scripts_styles()
548
-    {
549
-        wp_register_style(
550
-            'events-admin-css',
551
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
552
-            array(),
553
-            EVENT_ESPRESSO_VERSION
554
-        );
555
-        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
556
-        wp_enqueue_style('events-admin-css');
557
-        wp_enqueue_style('ee-cat-admin');
558
-        // todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
559
-        // registers for all views
560
-        // scripts
561
-        wp_register_script(
562
-            'event_editor_js',
563
-            EVENTS_ASSETS_URL . 'event_editor.js',
564
-            array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
565
-            EVENT_ESPRESSO_VERSION,
566
-            true
567
-        );
568
-    }
569
-
570
-
571
-    /**
572
-     * Enqueuing scripts and styles specific to this view
573
-     */
574
-    public function load_scripts_styles_create_new()
575
-    {
576
-        $this->load_scripts_styles_edit();
577
-    }
578
-
579
-
580
-    /**
581
-     * Enqueuing scripts and styles specific to this view
582
-     */
583
-    public function load_scripts_styles_edit()
584
-    {
585
-        // styles
586
-        wp_enqueue_style('espresso-ui-theme');
587
-        wp_register_style(
588
-            'event-editor-css',
589
-            EVENTS_ASSETS_URL . 'event-editor.css',
590
-            array('ee-admin-css'),
591
-            EVENT_ESPRESSO_VERSION
592
-        );
593
-        wp_enqueue_style('event-editor-css');
594
-        // scripts
595
-        wp_register_script(
596
-            'event-datetime-metabox',
597
-            EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
598
-            array('event_editor_js', 'ee-datepicker'),
599
-            EVENT_ESPRESSO_VERSION
600
-        );
601
-        wp_enqueue_script('event-datetime-metabox');
602
-    }
603
-
604
-
605
-    /**
606
-     * Populating the _views property for the category list table view.
607
-     */
608
-    protected function _set_list_table_views_category_list()
609
-    {
610
-        $this->_views = array(
611
-            'all' => array(
612
-                'slug'        => 'all',
613
-                'label'       => esc_html__('All', 'event_espresso'),
614
-                'count'       => 0,
615
-                'bulk_action' => array(
616
-                    'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
617
-                ),
618
-            ),
619
-        );
620
-    }
621
-
622
-
623
-    /**
624
-     * For adding anything that fires on the admin_init hook for any route within this admin page group.
625
-     */
626
-    public function admin_init()
627
-    {
628
-        EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
629
-            'Do you really want to delete this image? Please remember to update your event to complete the removal.',
630
-            'event_espresso'
631
-        );
632
-    }
633
-
634
-
635
-    /**
636
-     * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
637
-     * group.
638
-     */
639
-    public function admin_notices()
640
-    {
641
-    }
642
-
643
-
644
-    /**
645
-     * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
646
-     * this admin page group.
647
-     */
648
-    public function admin_footer_scripts()
649
-    {
650
-    }
651
-
652
-
653
-    /**
654
-     * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
655
-     * warning (via EE_Error::add_error());
656
-     *
657
-     * @param  EE_Event $event Event object
658
-     * @param string    $req_type
659
-     * @return void
660
-     * @throws EE_Error
661
-     * @access public
662
-     */
663
-    public function verify_event_edit($event = null, $req_type = '')
664
-    {
665
-        // don't need to do this when processing
666
-        if (! empty($req_type)) {
667
-            return;
668
-        }
669
-        // no event?
670
-        if (empty($event)) {
671
-            // set event
672
-            $event = $this->_cpt_model_obj;
673
-        }
674
-        // STILL no event?
675
-        if (! $event instanceof EE_Event) {
676
-            return;
677
-        }
678
-        $orig_status = $event->status();
679
-        // first check if event is active.
680
-        if ($orig_status === EEM_Event::cancelled
681
-            || $orig_status === EEM_Event::postponed
682
-            || $event->is_expired()
683
-            || $event->is_inactive()
684
-        ) {
685
-            return;
686
-        }
687
-        // made it here so it IS active... next check that any of the tickets are sold.
688
-        if ($event->is_sold_out(true)) {
689
-            if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
690
-                EE_Error::add_attention(
691
-                    sprintf(
692
-                        esc_html__(
693
-                            'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
694
-                            'event_espresso'
695
-                        ),
696
-                        EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
697
-                    )
698
-                );
699
-            }
700
-            return;
701
-        } elseif ($orig_status === EEM_Event::sold_out) {
702
-            EE_Error::add_attention(
703
-                sprintf(
704
-                    esc_html__(
705
-                        'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
706
-                        'event_espresso'
707
-                    ),
708
-                    EEH_Template::pretty_status($event->status(), false, 'sentence')
709
-                )
710
-            );
711
-        }
712
-        // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
713
-        if (! $event->tickets_on_sale()) {
714
-            return;
715
-        }
716
-        // made it here so show warning
717
-        $this->_edit_event_warning();
718
-    }
719
-
720
-
721
-    /**
722
-     * This is the text used for when an event is being edited that is public and has tickets for sale.
723
-     * When needed, hook this into a EE_Error::add_error() notice.
724
-     *
725
-     * @access protected
726
-     * @return void
727
-     */
728
-    protected function _edit_event_warning()
729
-    {
730
-        // we don't want to add warnings during these requests
731
-        if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
732
-            return;
733
-        }
734
-        EE_Error::add_attention(
735
-            sprintf(
736
-                esc_html__(
737
-                    'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
738
-                    'event_espresso'
739
-                ),
740
-                '<a class="espresso-help-tab-lnk">',
741
-                '</a>'
742
-            )
743
-        );
744
-    }
745
-
746
-
747
-    /**
748
-     * When a user is creating a new event, notify them if they haven't set their timezone.
749
-     * Otherwise, do the normal logic
750
-     *
751
-     * @return string
752
-     * @throws \EE_Error
753
-     */
754
-    protected function _create_new_cpt_item()
755
-    {
756
-        $has_timezone_string = get_option('timezone_string');
757
-        // only nag them about setting their timezone if it's their first event, and they haven't already done it
758
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
759
-            EE_Error::add_attention(
760
-                sprintf(
761
-                    __(
762
-                        'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
763
-                        'event_espresso'
764
-                    ),
765
-                    '<br>',
766
-                    '<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
767
-                    . EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
768
-                    . '</select>',
769
-                    '<button class="button button-secondary timezone-submit">',
770
-                    '</button><span class="spinner"></span>'
771
-                ),
772
-                __FILE__,
773
-                __FUNCTION__,
774
-                __LINE__
775
-            );
776
-        }
777
-        return parent::_create_new_cpt_item();
778
-    }
779
-
780
-
781
-    /**
782
-     * Sets the _views property for the default route in this admin page group.
783
-     */
784
-    protected function _set_list_table_views_default()
785
-    {
786
-        $this->_views = array(
787
-            'all'   => array(
788
-                'slug'        => 'all',
789
-                'label'       => esc_html__('View All Events', 'event_espresso'),
790
-                'count'       => 0,
791
-                'bulk_action' => array(
792
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
793
-                ),
794
-            ),
795
-            'draft' => array(
796
-                'slug'        => 'draft',
797
-                'label'       => esc_html__('Draft', 'event_espresso'),
798
-                'count'       => 0,
799
-                'bulk_action' => array(
800
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
801
-                ),
802
-            ),
803
-        );
804
-        if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
805
-            $this->_views['trash'] = array(
806
-                'slug'        => 'trash',
807
-                'label'       => esc_html__('Trash', 'event_espresso'),
808
-                'count'       => 0,
809
-                'bulk_action' => array(
810
-                    'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
811
-                    'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
812
-                ),
813
-            );
814
-        }
815
-    }
816
-
817
-
818
-    /**
819
-     * Provides the legend item array for the default list table view.
820
-     *
821
-     * @return array
822
-     */
823
-    protected function _event_legend_items()
824
-    {
825
-        $items = array(
826
-            'view_details'   => array(
827
-                'class' => 'dashicons dashicons-search',
828
-                'desc'  => esc_html__('View Event', 'event_espresso'),
829
-            ),
830
-            'edit_event'     => array(
831
-                'class' => 'ee-icon ee-icon-calendar-edit',
832
-                'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
833
-            ),
834
-            'view_attendees' => array(
835
-                'class' => 'dashicons dashicons-groups',
836
-                'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
837
-            ),
838
-        );
839
-        $items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
840
-        $statuses = array(
841
-            'sold_out_status'  => array(
842
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
843
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
844
-            ),
845
-            'active_status'    => array(
846
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
847
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
848
-            ),
849
-            'upcoming_status'  => array(
850
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
851
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
852
-            ),
853
-            'postponed_status' => array(
854
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
855
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
856
-            ),
857
-            'cancelled_status' => array(
858
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
859
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
860
-            ),
861
-            'expired_status'   => array(
862
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
863
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
864
-            ),
865
-            'inactive_status'  => array(
866
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
867
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
868
-            ),
869
-        );
870
-        $statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
871
-        return array_merge($items, $statuses);
872
-    }
873
-
874
-
875
-    /**
876
-     * @return EEM_Event
877
-     */
878
-    private function _event_model()
879
-    {
880
-        if (! $this->_event_model instanceof EEM_Event) {
881
-            $this->_event_model = EE_Registry::instance()->load_model('Event');
882
-        }
883
-        return $this->_event_model;
884
-    }
885
-
886
-
887
-    /**
888
-     * Adds extra buttons to the WP CPT permalink field row.
889
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
890
-     *
891
-     * @param  string $return    the current html
892
-     * @param  int    $id        the post id for the page
893
-     * @param  string $new_title What the title is
894
-     * @param  string $new_slug  what the slug is
895
-     * @return string            The new html string for the permalink area
896
-     */
897
-    public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
898
-    {
899
-        // make sure this is only when editing
900
-        if (! empty($id)) {
901
-            $post = get_post($id);
902
-            $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
903
-                       . esc_html__('Shortcode', 'event_espresso')
904
-                       . '</a> ';
905
-            $return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
906
-                       . $post->ID
907
-                       . ']">';
908
-        }
909
-        return $return;
910
-    }
911
-
912
-
913
-    /**
914
-     * _events_overview_list_table
915
-     * This contains the logic for showing the events_overview list
916
-     *
917
-     * @access protected
918
-     * @return void
919
-     * @throws \EE_Error
920
-     */
921
-    protected function _events_overview_list_table()
922
-    {
923
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
924
-        $this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
925
-            ? (array) $this->_template_args['after_list_table']
926
-            : array();
927
-        $this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
928
-                . EEH_Template::get_button_or_link(
929
-                    get_post_type_archive_link('espresso_events'),
930
-                    esc_html__("View Event Archive Page", "event_espresso"),
931
-                    'button'
932
-                );
933
-        $this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
934
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
935
-            'create_new',
936
-            'add',
937
-            array(),
938
-            'add-new-h2'
939
-        );
940
-        $this->display_admin_list_table_page_with_no_sidebar();
941
-    }
942
-
943
-
944
-    /**
945
-     * this allows for extra misc actions in the default WP publish box
946
-     *
947
-     * @return void
948
-     */
949
-    public function extra_misc_actions_publish_box()
950
-    {
951
-        $this->_generate_publish_box_extra_content();
952
-    }
953
-
954
-
955
-    /**
956
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
957
-     * saved.
958
-     * Typically you would use this to save any additional data.
959
-     * Keep in mind also that "save_post" runs on EVERY post update to the database.
960
-     * ALSO very important.  When a post transitions from scheduled to published,
961
-     * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
962
-     * other meta saves. So MAKE sure that you handle this accordingly.
963
-     *
964
-     * @access protected
965
-     * @abstract
966
-     * @param  string $post_id The ID of the cpt that was saved (so you can link relationally)
967
-     * @param  object $post    The post object of the cpt that was saved.
968
-     * @return void
969
-     * @throws \EE_Error
970
-     */
971
-    protected function _insert_update_cpt_item($post_id, $post)
972
-    {
973
-        if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
974
-            // get out we're not processing an event save.
975
-            return;
976
-        }
977
-        $event_values = array(
978
-            'EVT_display_desc'                => ! empty($this->_req_data['display_desc']) ? 1 : 0,
979
-            'EVT_display_ticket_selector'     => ! empty($this->_req_data['display_ticket_selector']) ? 1 : 0,
980
-            'EVT_additional_limit'            => min(
981
-                apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
982
-                ! empty($this->_req_data['additional_limit']) ? $this->_req_data['additional_limit'] : null
983
-            ),
984
-            'EVT_default_registration_status' => ! empty($this->_req_data['EVT_default_registration_status'])
985
-                ? $this->_req_data['EVT_default_registration_status']
986
-                : EE_Registry::instance()->CFG->registration->default_STS_ID,
987
-            'EVT_member_only'                 => ! empty($this->_req_data['member_only']) ? 1 : 0,
988
-            'EVT_allow_overflow'              => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
989
-            'EVT_timezone_string'             => ! empty($this->_req_data['timezone_string'])
990
-                ? $this->_req_data['timezone_string'] : null,
991
-            'EVT_external_URL'                => ! empty($this->_req_data['externalURL'])
992
-                ? $this->_req_data['externalURL'] : null,
993
-            'EVT_phone'                       => ! empty($this->_req_data['event_phone'])
994
-                ? $this->_req_data['event_phone'] : null,
995
-        );
996
-        // update event
997
-        $success = $this->_event_model()->update_by_ID($event_values, $post_id);
998
-        // get event_object for other metaboxes... though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
999
-        $get_one_where = array(
1000
-            $this->_event_model()->primary_key_name() => $post_id,
1001
-            'OR'                                      => array(
1002
-                'status'   => $post->post_status,
1003
-                // if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1004
-                // but the returned object here has a status of "publish", so use the original post status as well
1005
-                'status*1' => $this->_req_data['original_post_status'],
1006
-            ),
1007
-        );
1008
-        $event = $this->_event_model()->get_one(array($get_one_where));
1009
-        // the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1010
-        $event_update_callbacks = apply_filters(
1011
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1012
-            array(
1013
-                array($this, '_default_venue_update'),
1014
-                array($this, '_default_tickets_update'),
1015
-            )
1016
-        );
1017
-        $att_success = true;
1018
-        foreach ($event_update_callbacks as $e_callback) {
1019
-            $_success = is_callable($e_callback)
1020
-                ? call_user_func($e_callback, $event, $this->_req_data)
1021
-                : false;
1022
-            // if ANY of these updates fail then we want the appropriate global error message
1023
-            $att_success = ! $att_success ? $att_success : $_success;
1024
-        }
1025
-        // any errors?
1026
-        if ($success && false === $att_success) {
1027
-            EE_Error::add_error(
1028
-                esc_html__(
1029
-                    'Event Details saved successfully but something went wrong with saving attachments.',
1030
-                    'event_espresso'
1031
-                ),
1032
-                __FILE__,
1033
-                __FUNCTION__,
1034
-                __LINE__
1035
-            );
1036
-        } elseif ($success === false) {
1037
-            EE_Error::add_error(
1038
-                esc_html__('Event Details did not save successfully.', 'event_espresso'),
1039
-                __FILE__,
1040
-                __FUNCTION__,
1041
-                __LINE__
1042
-            );
1043
-        }
1044
-    }
1045
-
1046
-
1047
-    /**
1048
-     * @see parent::restore_item()
1049
-     * @param int $post_id
1050
-     * @param int $revision_id
1051
-     */
1052
-    protected function _restore_cpt_item($post_id, $revision_id)
1053
-    {
1054
-        // copy existing event meta to new post
1055
-        $post_evt = $this->_event_model()->get_one_by_ID($post_id);
1056
-        if ($post_evt instanceof EE_Event) {
1057
-            // meta revision restore
1058
-            $post_evt->restore_revision($revision_id);
1059
-            // related objs restore
1060
-            $post_evt->restore_revision($revision_id, array('Venue', 'Datetime', 'Price'));
1061
-        }
1062
-    }
1063
-
1064
-
1065
-    /**
1066
-     * Attach the venue to the Event
1067
-     *
1068
-     * @param  \EE_Event $evtobj Event Object to add the venue to
1069
-     * @param  array     $data   The request data from the form
1070
-     * @return bool           Success or fail.
1071
-     */
1072
-    protected function _default_venue_update(\EE_Event $evtobj, $data)
1073
-    {
1074
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1075
-        $venue_model = EE_Registry::instance()->load_model('Venue');
1076
-        $rows_affected = null;
1077
-        $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1078
-        // very important.  If we don't have a venue name...
1079
-        // then we'll get out because not necessary to create empty venue
1080
-        if (empty($data['venue_title'])) {
1081
-            return false;
1082
-        }
1083
-        $venue_array = array(
1084
-            'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1085
-            'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1086
-            'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1087
-            'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1088
-            'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1089
-                : null,
1090
-            'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1091
-            'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1092
-            'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1093
-            'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1094
-            'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1095
-            'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1096
-            'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1097
-            'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1098
-            'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1099
-            'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1100
-            'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1101
-            'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1102
-            'status'              => 'publish',
1103
-        );
1104
-        // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1105
-        if (! empty($venue_id)) {
1106
-            $update_where = array($venue_model->primary_key_name() => $venue_id);
1107
-            $rows_affected = $venue_model->update($venue_array, array($update_where));
1108
-            // we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
1109
-            $evtobj->_add_relation_to($venue_id, 'Venue');
1110
-            return $rows_affected > 0 ? true : false;
1111
-        } else {
1112
-            // we insert the venue
1113
-            $venue_id = $venue_model->insert($venue_array);
1114
-            $evtobj->_add_relation_to($venue_id, 'Venue');
1115
-            return ! empty($venue_id) ? true : false;
1116
-        }
1117
-        // when we have the ancestor come in it's already been handled by the revision save.
1118
-    }
1119
-
1120
-
1121
-    /**
1122
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
1123
-     *
1124
-     * @param  EE_Event $evtobj The Event object we're attaching data to
1125
-     * @param  array    $data   The request data from the form
1126
-     * @return array
1127
-     */
1128
-    protected function _default_tickets_update(EE_Event $evtobj, $data)
1129
-    {
1130
-        $success = true;
1131
-        $saved_dtt = null;
1132
-        $saved_tickets = array();
1133
-        $incoming_date_formats = array('Y-m-d', 'h:i a');
1134
-        foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1135
-            // trim all values to ensure any excess whitespace is removed.
1136
-            $dtt = array_map('trim', $dtt);
1137
-            $dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1138
-                : $dtt['DTT_EVT_start'];
1139
-            $datetime_values = array(
1140
-                'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1141
-                'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1142
-                'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1143
-                'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1144
-                'DTT_order'     => $row,
1145
-            );
1146
-            // if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1147
-            if (! empty($dtt['DTT_ID'])) {
1148
-                $DTM = EE_Registry::instance()
1149
-                                  ->load_model('Datetime', array($evtobj->get_timezone()))
1150
-                                  ->get_one_by_ID($dtt['DTT_ID']);
1151
-                $DTM->set_date_format($incoming_date_formats[0]);
1152
-                $DTM->set_time_format($incoming_date_formats[1]);
1153
-                foreach ($datetime_values as $field => $value) {
1154
-                    $DTM->set($field, $value);
1155
-                }
1156
-                // make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1157
-                $saved_dtts[ $DTM->ID() ] = $DTM;
1158
-            } else {
1159
-                $DTM = EE_Registry::instance()->load_class(
1160
-                    'Datetime',
1161
-                    array($datetime_values, $evtobj->get_timezone(), $incoming_date_formats),
1162
-                    false,
1163
-                    false
1164
-                );
1165
-                foreach ($datetime_values as $field => $value) {
1166
-                    $DTM->set($field, $value);
1167
-                }
1168
-            }
1169
-            $DTM->save();
1170
-            $DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1171
-            // load DTT helper
1172
-            // before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1173
-            if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1174
-                $DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1175
-                $DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1176
-                $DTT->save();
1177
-            }
1178
-            // now we got to make sure we add the new DTT_ID to the $saved_dtts array  because it is possible there was a new one created for the autosave.
1179
-            $saved_dtt = $DTT;
1180
-            $success = ! $success ? $success : $DTT;
1181
-            // if ANY of these updates fail then we want the appropriate global error message.
1182
-            // //todo this is actually sucky we need a better error message but this is what it is for now.
1183
-        }
1184
-        // no dtts get deleted so we don't do any of that logic here.
1185
-        // update tickets next
1186
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
1187
-        foreach ($data['edit_tickets'] as $row => $tkt) {
1188
-            $incoming_date_formats = array('Y-m-d', 'h:i a');
1189
-            $update_prices = false;
1190
-            $ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1191
-                ? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1192
-            // trim inputs to ensure any excess whitespace is removed.
1193
-            $tkt = array_map('trim', $tkt);
1194
-            if (empty($tkt['TKT_start_date'])) {
1195
-                // let's use now in the set timezone.
1196
-                $now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1197
-                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1198
-            }
1199
-            if (empty($tkt['TKT_end_date'])) {
1200
-                // use the start date of the first datetime
1201
-                $dtt = $evtobj->first_datetime();
1202
-                $tkt['TKT_end_date'] = $dtt->start_date_and_time(
1203
-                    $incoming_date_formats[0],
1204
-                    $incoming_date_formats[1]
1205
-                );
1206
-            }
1207
-            $TKT_values = array(
1208
-                'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1209
-                'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1210
-                'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1211
-                'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1212
-                'TKT_start_date'  => $tkt['TKT_start_date'],
1213
-                'TKT_end_date'    => $tkt['TKT_end_date'],
1214
-                'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1215
-                'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1216
-                'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1217
-                'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1218
-                'TKT_row'         => $row,
1219
-                'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1220
-                'TKT_price'       => $ticket_price,
1221
-            );
1222
-            // if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, which means in turn that the prices will become new prices as well.
1223
-            if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1224
-                $TKT_values['TKT_ID'] = 0;
1225
-                $TKT_values['TKT_is_default'] = 0;
1226
-                $TKT_values['TKT_price'] = $ticket_price;
1227
-                $update_prices = true;
1228
-            }
1229
-            // if we have a TKT_ID then we need to get that existing TKT_obj and update it
1230
-            // we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1231
-            // keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1232
-            if (! empty($tkt['TKT_ID'])) {
1233
-                $TKT = EE_Registry::instance()
1234
-                                  ->load_model('Ticket', array($evtobj->get_timezone()))
1235
-                                  ->get_one_by_ID($tkt['TKT_ID']);
1236
-                if ($TKT instanceof EE_Ticket) {
1237
-                    $ticket_sold = $TKT->count_related(
1238
-                        'Registration',
1239
-                        array(
1240
-                            array(
1241
-                                'STS_ID' => array(
1242
-                                    'NOT IN',
1243
-                                    array(EEM_Registration::status_id_incomplete),
1244
-                                ),
1245
-                            ),
1246
-                        )
1247
-                    ) > 0 ? true : false;
1248
-                    // let's just check the total price for the existing ticket and determine if it matches the new total price.  if they are different then we create a new ticket (if tkts sold) if they aren't different then we go ahead and modify existing ticket.
1249
-                    $create_new_TKT = $ticket_sold && $ticket_price != $TKT->get('TKT_price')
1250
-                                      && ! $TKT->get('TKT_deleted');
1251
-                    $TKT->set_date_format($incoming_date_formats[0]);
1252
-                    $TKT->set_time_format($incoming_date_formats[1]);
1253
-                    // set new values
1254
-                    foreach ($TKT_values as $field => $value) {
1255
-                        if ($field == 'TKT_qty') {
1256
-                            $TKT->set_qty($value);
1257
-                        } else {
1258
-                            $TKT->set($field, $value);
1259
-                        }
1260
-                    }
1261
-                    // if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1262
-                    if ($create_new_TKT) {
1263
-                        // archive the old ticket first
1264
-                        $TKT->set('TKT_deleted', 1);
1265
-                        $TKT->save();
1266
-                        // make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1267
-                        $saved_tickets[ $TKT->ID() ] = $TKT;
1268
-                        // create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1269
-                        $TKT = clone $TKT;
1270
-                        $TKT->set('TKT_ID', 0);
1271
-                        $TKT->set('TKT_deleted', 0);
1272
-                        $TKT->set('TKT_price', $ticket_price);
1273
-                        $TKT->set('TKT_sold', 0);
1274
-                        // now we need to make sure that $new prices are created as well and attached to new ticket.
1275
-                        $update_prices = true;
1276
-                    }
1277
-                    // make sure price is set if it hasn't been already
1278
-                    $TKT->set('TKT_price', $ticket_price);
1279
-                }
1280
-            } else {
1281
-                // no TKT_id so a new TKT
1282
-                $TKT_values['TKT_price'] = $ticket_price;
1283
-                $TKT = EE_Registry::instance()->load_class('Ticket', array($TKT_values), false, false);
1284
-                if ($TKT instanceof EE_Ticket) {
1285
-                    // need to reset values to properly account for the date formats
1286
-                    $TKT->set_date_format($incoming_date_formats[0]);
1287
-                    $TKT->set_time_format($incoming_date_formats[1]);
1288
-                    $TKT->set_timezone($evtobj->get_timezone());
1289
-                    // set new values
1290
-                    foreach ($TKT_values as $field => $value) {
1291
-                        if ($field == 'TKT_qty') {
1292
-                            $TKT->set_qty($value);
1293
-                        } else {
1294
-                            $TKT->set($field, $value);
1295
-                        }
1296
-                    }
1297
-                    $update_prices = true;
1298
-                }
1299
-            }
1300
-            // cap ticket qty by datetime reg limits
1301
-            $TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1302
-            // update ticket.
1303
-            $TKT->save();
1304
-            // before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1305
-            if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1306
-                $TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1307
-                $TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1308
-                $TKT->save();
1309
-            }
1310
-            // initially let's add the ticket to the dtt
1311
-            $saved_dtt->_add_relation_to($TKT, 'Ticket');
1312
-            $saved_tickets[ $TKT->ID() ] = $TKT;
1313
-            // add prices to ticket
1314
-            $this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1315
-        }
1316
-        // however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1317
-        $old_tickets = isset($old_tickets[0]) && $old_tickets[0] == '' ? array() : $old_tickets;
1318
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1319
-        foreach ($tickets_removed as $id) {
1320
-            $id = absint($id);
1321
-            // get the ticket for this id
1322
-            $tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1323
-            // need to get all the related datetimes on this ticket and remove from every single one of them (remember this process can ONLY kick off if there are NO tkts_sold)
1324
-            $dtts = $tkt_to_remove->get_many_related('Datetime');
1325
-            foreach ($dtts as $dtt) {
1326
-                $tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1327
-            }
1328
-            // need to do the same for prices (except these prices can also be deleted because again, tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1329
-            $tkt_to_remove->delete_related_permanently('Price');
1330
-            // finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1331
-            $tkt_to_remove->delete_permanently();
1332
-        }
1333
-        return array($saved_dtt, $saved_tickets);
1334
-    }
1335
-
1336
-
1337
-    /**
1338
-     * This attaches a list of given prices to a ticket.
1339
-     * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1340
-     * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1341
-     * price info and prices are automatically "archived" via the ticket.
1342
-     *
1343
-     * @access  private
1344
-     * @param array     $prices     Array of prices from the form.
1345
-     * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1346
-     * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1347
-     * @return  void
1348
-     */
1349
-    private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1350
-    {
1351
-        foreach ($prices as $row => $prc) {
1352
-            $PRC_values = array(
1353
-                'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1354
-                'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1355
-                'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1356
-                'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1357
-                'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1358
-                'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1359
-                'PRC_order'      => $row,
1360
-            );
1361
-            if ($new_prices || empty($PRC_values['PRC_ID'])) {
1362
-                $PRC_values['PRC_ID'] = 0;
1363
-                $PRC = EE_Registry::instance()->load_class('Price', array($PRC_values), false, false);
1364
-            } else {
1365
-                $PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1366
-                // update this price with new values
1367
-                foreach ($PRC_values as $field => $newprc) {
1368
-                    $PRC->set($field, $newprc);
1369
-                }
1370
-                $PRC->save();
1371
-            }
1372
-            $ticket->_add_relation_to($PRC, 'Price');
1373
-        }
1374
-    }
1375
-
1376
-
1377
-    /**
1378
-     * Add in our autosave ajax handlers
1379
-     *
1380
-     */
1381
-    protected function _ee_autosave_create_new()
1382
-    {
1383
-    }
1384
-
1385
-
1386
-    /**
1387
-     * More autosave handlers.
1388
-     */
1389
-    protected function _ee_autosave_edit()
1390
-    {
1391
-        return; // TEMPORARILY EXITING CAUSE THIS IS A TODO
1392
-    }
1393
-
1394
-
1395
-    /**
1396
-     *    _generate_publish_box_extra_content
1397
-     */
1398
-    private function _generate_publish_box_extra_content()
1399
-    {
1400
-        // load formatter helper
1401
-        // args for getting related registrations
1402
-        $approved_query_args = array(
1403
-            array(
1404
-                'REG_deleted' => 0,
1405
-                'STS_ID'      => EEM_Registration::status_id_approved,
1406
-            ),
1407
-        );
1408
-        $not_approved_query_args = array(
1409
-            array(
1410
-                'REG_deleted' => 0,
1411
-                'STS_ID'      => EEM_Registration::status_id_not_approved,
1412
-            ),
1413
-        );
1414
-        $pending_payment_query_args = array(
1415
-            array(
1416
-                'REG_deleted' => 0,
1417
-                'STS_ID'      => EEM_Registration::status_id_pending_payment,
1418
-            ),
1419
-        );
1420
-        // publish box
1421
-        $publish_box_extra_args = array(
1422
-            'view_approved_reg_url'        => add_query_arg(
1423
-                array(
1424
-                    'action'      => 'default',
1425
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1426
-                    '_reg_status' => EEM_Registration::status_id_approved,
1427
-                ),
1428
-                REG_ADMIN_URL
1429
-            ),
1430
-            'view_not_approved_reg_url'    => add_query_arg(
1431
-                array(
1432
-                    'action'      => 'default',
1433
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1434
-                    '_reg_status' => EEM_Registration::status_id_not_approved,
1435
-                ),
1436
-                REG_ADMIN_URL
1437
-            ),
1438
-            'view_pending_payment_reg_url' => add_query_arg(
1439
-                array(
1440
-                    'action'      => 'default',
1441
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1442
-                    '_reg_status' => EEM_Registration::status_id_pending_payment,
1443
-                ),
1444
-                REG_ADMIN_URL
1445
-            ),
1446
-            'approved_regs'                => $this->_cpt_model_obj->count_related(
1447
-                'Registration',
1448
-                $approved_query_args
1449
-            ),
1450
-            'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1451
-                'Registration',
1452
-                $not_approved_query_args
1453
-            ),
1454
-            'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1455
-                'Registration',
1456
-                $pending_payment_query_args
1457
-            ),
1458
-            'misc_pub_section_class'       => apply_filters(
1459
-                'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1460
-                'misc-pub-section'
1461
-            ),
1462
-        );
1463
-        ob_start();
1464
-        do_action(
1465
-            'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1466
-            $this->_cpt_model_obj
1467
-        );
1468
-        $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1469
-        // load template
1470
-        EEH_Template::display_template(
1471
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1472
-            $publish_box_extra_args
1473
-        );
1474
-    }
1475
-
1476
-
1477
-    /**
1478
-     * @return EE_Event
1479
-     */
1480
-    public function get_event_object()
1481
-    {
1482
-        return $this->_cpt_model_obj;
1483
-    }
1484
-
1485
-
1486
-
1487
-
1488
-    /** METABOXES * */
1489
-    /**
1490
-     * _register_event_editor_meta_boxes
1491
-     * add all metaboxes related to the event_editor
1492
-     *
1493
-     * @return void
1494
-     */
1495
-    protected function _register_event_editor_meta_boxes()
1496
-    {
1497
-        $this->verify_cpt_object();
1498
-        add_meta_box(
1499
-            'espresso_event_editor_tickets',
1500
-            esc_html__('Event Datetime & Ticket', 'event_espresso'),
1501
-            array($this, 'ticket_metabox'),
1502
-            $this->page_slug,
1503
-            'normal',
1504
-            'high'
1505
-        );
1506
-        add_meta_box(
1507
-            'espresso_event_editor_event_options',
1508
-            esc_html__('Event Registration Options', 'event_espresso'),
1509
-            array($this, 'registration_options_meta_box'),
1510
-            $this->page_slug,
1511
-            'side',
1512
-            'default'
1513
-        );
1514
-        // NOTE: if you're looking for other metaboxes in here,
1515
-        // where a metabox has a related management page in the admin
1516
-        // you will find it setup in the related management page's "_Hooks" file.
1517
-        // i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1518
-    }
1519
-
1520
-
1521
-    /**
1522
-     * @throws DomainException
1523
-     * @throws EE_Error
1524
-     */
1525
-    public function ticket_metabox()
1526
-    {
1527
-        $existing_datetime_ids = $existing_ticket_ids = array();
1528
-        // defaults for template args
1529
-        $template_args = array(
1530
-            'existing_datetime_ids'    => '',
1531
-            'event_datetime_help_link' => '',
1532
-            'ticket_options_help_link' => '',
1533
-            'time'                     => null,
1534
-            'ticket_rows'              => '',
1535
-            'existing_ticket_ids'      => '',
1536
-            'total_ticket_rows'        => 1,
1537
-            'ticket_js_structure'      => '',
1538
-            'trash_icon'               => 'ee-lock-icon',
1539
-            'disabled'                 => '',
1540
-        );
1541
-        $event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1542
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1543
-        /**
1544
-         * 1. Start with retrieving Datetimes
1545
-         * 2. Fore each datetime get related tickets
1546
-         * 3. For each ticket get related prices
1547
-         */
1548
-        $times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1549
-        /** @type EE_Datetime $first_datetime */
1550
-        $first_datetime = reset($times);
1551
-        // do we get related tickets?
1552
-        if ($first_datetime instanceof EE_Datetime
1553
-            && $first_datetime->ID() !== 0
1554
-        ) {
1555
-            $existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1556
-            $template_args['time'] = $first_datetime;
1557
-            $related_tickets = $first_datetime->tickets(
1558
-                array(
1559
-                    array('OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0)),
1560
-                    'default_where_conditions' => 'none',
1561
-                )
1562
-            );
1563
-            if (! empty($related_tickets)) {
1564
-                $template_args['total_ticket_rows'] = count($related_tickets);
1565
-                $row = 0;
1566
-                foreach ($related_tickets as $ticket) {
1567
-                    $existing_ticket_ids[] = $ticket->get('TKT_ID');
1568
-                    $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1569
-                    $row++;
1570
-                }
1571
-            } else {
1572
-                $template_args['total_ticket_rows'] = 1;
1573
-                /** @type EE_Ticket $ticket */
1574
-                $ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1575
-                $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1576
-            }
1577
-        } else {
1578
-            $template_args['time'] = $times[0];
1579
-            /** @type EE_Ticket $ticket */
1580
-            $ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1581
-            $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1582
-            // NOTE: we're just sending the first default row
1583
-            // (decaf can't manage default tickets so this should be sufficient);
1584
-        }
1585
-        $template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1586
-            'event_editor_event_datetimes_help_tab'
1587
-        );
1588
-        $template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1589
-        $template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1590
-        $template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1591
-        $template_args['ticket_js_structure'] = $this->_get_ticket_row(
1592
-            EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1593
-            true
1594
-        );
1595
-        $template = apply_filters(
1596
-            'FHEE__Events_Admin_Page__ticket_metabox__template',
1597
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1598
-        );
1599
-        EEH_Template::display_template($template, $template_args);
1600
-    }
1601
-
1602
-
1603
-    /**
1604
-     * Setup an individual ticket form for the decaf event editor page
1605
-     *
1606
-     * @access private
1607
-     * @param  EE_Ticket $ticket   the ticket object
1608
-     * @param  boolean   $skeleton whether we're generating a skeleton for js manipulation
1609
-     * @param int        $row
1610
-     * @return string generated html for the ticket row.
1611
-     */
1612
-    private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1613
-    {
1614
-        $template_args = array(
1615
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1616
-            'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1617
-                : '',
1618
-            'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1619
-            'TKT_ID'              => $ticket->get('TKT_ID'),
1620
-            'TKT_name'            => $ticket->get('TKT_name'),
1621
-            'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1622
-            'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1623
-            'TKT_is_default'      => $ticket->get('TKT_is_default'),
1624
-            'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1625
-            'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1626
-            'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1627
-            'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1628
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1629
-                ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1630
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1631
-                : ' disabled=disabled',
1632
-        );
1633
-        $price = $ticket->ID() !== 0
1634
-            ? $ticket->get_first_related('Price', array('default_where_conditions' => 'none'))
1635
-            : EE_Registry::instance()->load_model('Price')->create_default_object();
1636
-        $price_args = array(
1637
-            'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1638
-            'PRC_amount'            => $price->get('PRC_amount'),
1639
-            'PRT_ID'                => $price->get('PRT_ID'),
1640
-            'PRC_ID'                => $price->get('PRC_ID'),
1641
-            'PRC_is_default'        => $price->get('PRC_is_default'),
1642
-        );
1643
-        // make sure we have default start and end dates if skeleton
1644
-        // handle rows that should NOT be empty
1645
-        if (empty($template_args['TKT_start_date'])) {
1646
-            // if empty then the start date will be now.
1647
-            $template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1648
-        }
1649
-        if (empty($template_args['TKT_end_date'])) {
1650
-            // get the earliest datetime (if present);
1651
-            $earliest_dtt = $this->_cpt_model_obj->ID() > 0
1652
-                ? $this->_cpt_model_obj->get_first_related(
1653
-                    'Datetime',
1654
-                    array('order_by' => array('DTT_EVT_start' => 'ASC'))
1655
-                )
1656
-                : null;
1657
-            if (! empty($earliest_dtt)) {
1658
-                $template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1659
-            } else {
1660
-                $template_args['TKT_end_date'] = date(
1661
-                    'Y-m-d h:i a',
1662
-                    mktime(0, 0, 0, date("m"), date("d") + 7, date("Y"))
1663
-                );
1664
-            }
1665
-        }
1666
-        $template_args = array_merge($template_args, $price_args);
1667
-        $template = apply_filters(
1668
-            'FHEE__Events_Admin_Page__get_ticket_row__template',
1669
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1670
-            $ticket
1671
-        );
1672
-        return EEH_Template::display_template($template, $template_args, true);
1673
-    }
1674
-
1675
-
1676
-    /**
1677
-     * @throws DomainException
1678
-     */
1679
-    public function registration_options_meta_box()
1680
-    {
1681
-        $yes_no_values = array(
1682
-            array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
1683
-            array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
1684
-        );
1685
-        $default_reg_status_values = EEM_Registration::reg_status_array(
1686
-            array(
1687
-                EEM_Registration::status_id_cancelled,
1688
-                EEM_Registration::status_id_declined,
1689
-                EEM_Registration::status_id_incomplete,
1690
-            ),
1691
-            true
1692
-        );
1693
-        // $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1694
-        $template_args['_event'] = $this->_cpt_model_obj;
1695
-        $template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1696
-        $template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1697
-        $template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1698
-            'default_reg_status',
1699
-            $default_reg_status_values,
1700
-            $this->_cpt_model_obj->default_registration_status()
1701
-        );
1702
-        $template_args['display_description'] = EEH_Form_Fields::select_input(
1703
-            'display_desc',
1704
-            $yes_no_values,
1705
-            $this->_cpt_model_obj->display_description()
1706
-        );
1707
-        $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1708
-            'display_ticket_selector',
1709
-            $yes_no_values,
1710
-            $this->_cpt_model_obj->display_ticket_selector(),
1711
-            '',
1712
-            '',
1713
-            false
1714
-        );
1715
-        $template_args['additional_registration_options'] = apply_filters(
1716
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1717
-            '',
1718
-            $template_args,
1719
-            $yes_no_values,
1720
-            $default_reg_status_values
1721
-        );
1722
-        EEH_Template::display_template(
1723
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1724
-            $template_args
1725
-        );
1726
-    }
1727
-
1728
-
1729
-    /**
1730
-     * _get_events()
1731
-     * This method simply returns all the events (for the given _view and paging)
1732
-     *
1733
-     * @access public
1734
-     * @param int  $per_page     count of items per page (20 default);
1735
-     * @param int  $current_page what is the current page being viewed.
1736
-     * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1737
-     *                           If FALSE then we return an array of event objects
1738
-     *                           that match the given _view and paging parameters.
1739
-     * @return array an array of event objects.
1740
-     */
1741
-    public function get_events($per_page = 10, $current_page = 1, $count = false)
1742
-    {
1743
-        $EEME = $this->_event_model();
1744
-        $offset = ($current_page - 1) * $per_page;
1745
-        $limit = $count ? null : $offset . ',' . $per_page;
1746
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1747
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC";
1748
-        if (isset($this->_req_data['month_range'])) {
1749
-            $pieces = explode(' ', $this->_req_data['month_range'], 3);
1750
-            // simulate the FIRST day of the month, that fixes issues for months like February
1751
-            // where PHP doesn't know what to assume for date.
1752
-            // @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1753
-            $month_r = ! empty($pieces[0]) ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1754
-            $year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1755
-        }
1756
-        $where = array();
1757
-        $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1758
-        // determine what post_status our condition will have for the query.
1759
-        switch ($status) {
1760
-            case 'month':
1761
-            case 'today':
1762
-            case null:
1763
-            case 'all':
1764
-                break;
1765
-            case 'draft':
1766
-                $where['status'] = array('IN', array('draft', 'auto-draft'));
1767
-                break;
1768
-            default:
1769
-                $where['status'] = $status;
1770
-        }
1771
-        // categories?
1772
-        $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1773
-            ? $this->_req_data['EVT_CAT'] : null;
1774
-        if (! empty($category)) {
1775
-            $where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1776
-            $where['Term_Taxonomy.term_id'] = $category;
1777
-        }
1778
-        // date where conditions
1779
-        $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1780
-        if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') {
1781
-            $DateTime = new DateTime(
1782
-                $year_r . '-' . $month_r . '-01 00:00:00',
1783
-                new DateTimeZone('UTC')
1784
-            );
1785
-            $start = $DateTime->getTimestamp();
1786
-            // set the datetime to be the end of the month
1787
-            $DateTime->setDate(
1788
-                $year_r,
1789
-                $month_r,
1790
-                $DateTime->format('t')
1791
-            )->setTime(23, 59, 59);
1792
-            $end = $DateTime->getTimestamp();
1793
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1794
-        } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] == 'today') {
1795
-            $DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1796
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1797
-            $end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1798
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1799
-        } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] == 'month') {
1800
-            $now = date('Y-m-01');
1801
-            $DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1802
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1803
-            $end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1804
-                            ->setTime(23, 59, 59)
1805
-                            ->format(implode(' ', $start_formats));
1806
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1807
-        }
1808
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1809
-            $where['EVT_wp_user'] = get_current_user_id();
1810
-        } else {
1811
-            if (! isset($where['status'])) {
1812
-                if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1813
-                    $where['OR'] = array(
1814
-                        'status*restrict_private' => array('!=', 'private'),
1815
-                        'AND'                     => array(
1816
-                            'status*inclusive' => array('=', 'private'),
1817
-                            'EVT_wp_user'      => get_current_user_id(),
1818
-                        ),
1819
-                    );
1820
-                }
1821
-            }
1822
-        }
1823
-        if (isset($this->_req_data['EVT_wp_user'])) {
1824
-            if ($this->_req_data['EVT_wp_user'] != get_current_user_id()
1825
-                && EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1826
-            ) {
1827
-                $where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1828
-            }
1829
-        }
1830
-        // search query handling
1831
-        if (isset($this->_req_data['s'])) {
1832
-            $search_string = '%' . $this->_req_data['s'] . '%';
1833
-            $where['OR'] = array(
1834
-                'EVT_name'       => array('LIKE', $search_string),
1835
-                'EVT_desc'       => array('LIKE', $search_string),
1836
-                'EVT_short_desc' => array('LIKE', $search_string),
1837
-            );
1838
-        }
1839
-        // filter events by venue.
1840
-        if (isset($this->_req_data['venue']) && ! empty($this->_req_data['venue'])) {
1841
-            $where['Venue.VNU_ID'] = absint($this->_req_data['venue']);
1842
-        }
1843
-        $where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
1844
-        $query_params = apply_filters(
1845
-            'FHEE__Events_Admin_Page__get_events__query_params',
1846
-            array(
1847
-                $where,
1848
-                'limit'    => $limit,
1849
-                'order_by' => $orderby,
1850
-                'order'    => $order,
1851
-                'group_by' => 'EVT_ID',
1852
-            ),
1853
-            $this->_req_data
1854
-        );
1855
-
1856
-        // let's first check if we have special requests coming in.
1857
-        if (isset($this->_req_data['active_status'])) {
1858
-            switch ($this->_req_data['active_status']) {
1859
-                case 'upcoming':
1860
-                    return $EEME->get_upcoming_events($query_params, $count);
1861
-                    break;
1862
-                case 'expired':
1863
-                    return $EEME->get_expired_events($query_params, $count);
1864
-                    break;
1865
-                case 'active':
1866
-                    return $EEME->get_active_events($query_params, $count);
1867
-                    break;
1868
-                case 'inactive':
1869
-                    return $EEME->get_inactive_events($query_params, $count);
1870
-                    break;
1871
-            }
1872
-        }
1873
-
1874
-        $events = $count ? $EEME->count(array($where), 'EVT_ID', true) : $EEME->get_all($query_params);
1875
-        return $events;
1876
-    }
1877
-
1878
-
1879
-    /**
1880
-     * handling for WordPress CPT actions (trash, restore, delete)
1881
-     *
1882
-     * @param string $post_id
1883
-     */
1884
-    public function trash_cpt_item($post_id)
1885
-    {
1886
-        $this->_req_data['EVT_ID'] = $post_id;
1887
-        $this->_trash_or_restore_event('trash', false);
1888
-    }
1889
-
1890
-
1891
-    /**
1892
-     * @param string $post_id
1893
-     */
1894
-    public function restore_cpt_item($post_id)
1895
-    {
1896
-        $this->_req_data['EVT_ID'] = $post_id;
1897
-        $this->_trash_or_restore_event('draft', false);
1898
-    }
1899
-
1900
-
1901
-    /**
1902
-     * @param string $post_id
1903
-     */
1904
-    public function delete_cpt_item($post_id)
1905
-    {
1906
-        $this->_req_data['EVT_ID'] = $post_id;
1907
-        $this->_delete_event(false);
1908
-    }
1909
-
1910
-
1911
-    /**
1912
-     * _trash_or_restore_event
1913
-     *
1914
-     * @access protected
1915
-     * @param  string $event_status
1916
-     * @param bool    $redirect_after
1917
-     */
1918
-    protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
1919
-    {
1920
-        // determine the event id and set to array.
1921
-        $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
1922
-        // loop thru events
1923
-        if ($EVT_ID) {
1924
-            // clean status
1925
-            $event_status = sanitize_key($event_status);
1926
-            // grab status
1927
-            if (! empty($event_status)) {
1928
-                $success = $this->_change_event_status($EVT_ID, $event_status);
1929
-            } else {
1930
-                $success = false;
1931
-                $msg = esc_html__(
1932
-                    'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
1933
-                    'event_espresso'
1934
-                );
1935
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1936
-            }
1937
-        } else {
1938
-            $success = false;
1939
-            $msg = esc_html__(
1940
-                'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
1941
-                'event_espresso'
1942
-            );
1943
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1944
-        }
1945
-        $action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1946
-        if ($redirect_after) {
1947
-            $this->_redirect_after_action($success, 'Event', $action, array('action' => 'default'));
1948
-        }
1949
-    }
1950
-
1951
-
1952
-    /**
1953
-     * _trash_or_restore_events
1954
-     *
1955
-     * @access protected
1956
-     * @param  string $event_status
1957
-     * @return void
1958
-     */
1959
-    protected function _trash_or_restore_events($event_status = 'trash')
1960
-    {
1961
-        // clean status
1962
-        $event_status = sanitize_key($event_status);
1963
-        // grab status
1964
-        if (! empty($event_status)) {
1965
-            $success = true;
1966
-            // determine the event id and set to array.
1967
-            $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
1968
-            // loop thru events
1969
-            foreach ($EVT_IDs as $EVT_ID) {
1970
-                if ($EVT_ID = absint($EVT_ID)) {
1971
-                    $results = $this->_change_event_status($EVT_ID, $event_status);
1972
-                    $success = $results !== false ? $success : false;
1973
-                } else {
1974
-                    $msg = sprintf(
1975
-                        esc_html__(
1976
-                            'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
1977
-                            'event_espresso'
1978
-                        ),
1979
-                        $EVT_ID
1980
-                    );
1981
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1982
-                    $success = false;
1983
-                }
1984
-            }
1985
-        } else {
1986
-            $success = false;
1987
-            $msg = esc_html__(
1988
-                'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
1989
-                'event_espresso'
1990
-            );
1991
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1992
-        }
1993
-        // in order to force a pluralized result message we need to send back a success status greater than 1
1994
-        $success = $success ? 2 : false;
1995
-        $action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1996
-        $this->_redirect_after_action($success, 'Events', $action, array('action' => 'default'));
1997
-    }
1998
-
1999
-
2000
-    /**
2001
-     * _trash_or_restore_events
2002
-     *
2003
-     * @access  private
2004
-     * @param  int    $EVT_ID
2005
-     * @param  string $event_status
2006
-     * @return bool
2007
-     */
2008
-    private function _change_event_status($EVT_ID = 0, $event_status = '')
2009
-    {
2010
-        // grab event id
2011
-        if (! $EVT_ID) {
2012
-            $msg = esc_html__(
2013
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2014
-                'event_espresso'
2015
-            );
2016
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2017
-            return false;
2018
-        }
2019
-        $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2020
-        // clean status
2021
-        $event_status = sanitize_key($event_status);
2022
-        // grab status
2023
-        if (empty($event_status)) {
2024
-            $msg = esc_html__(
2025
-                'An error occurred. No Event Status or an invalid Event Status was received.',
2026
-                'event_espresso'
2027
-            );
2028
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2029
-            return false;
2030
-        }
2031
-        // was event trashed or restored ?
2032
-        switch ($event_status) {
2033
-            case 'draft':
2034
-                $action = 'restored from the trash';
2035
-                $hook = 'AHEE_event_restored_from_trash';
2036
-                break;
2037
-            case 'trash':
2038
-                $action = 'moved to the trash';
2039
-                $hook = 'AHEE_event_moved_to_trash';
2040
-                break;
2041
-            default:
2042
-                $action = 'updated';
2043
-                $hook = false;
2044
-        }
2045
-        // use class to change status
2046
-        $this->_cpt_model_obj->set_status($event_status);
2047
-        $success = $this->_cpt_model_obj->save();
2048
-        if ($success === false) {
2049
-            $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2050
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2051
-            return false;
2052
-        }
2053
-        if ($hook) {
2054
-            do_action($hook);
2055
-        }
2056
-        return true;
2057
-    }
2058
-
2059
-
2060
-    /**
2061
-     * _delete_event
2062
-     *
2063
-     * @access protected
2064
-     * @param bool $redirect_after
2065
-     */
2066
-    protected function _delete_event($redirect_after = true)
2067
-    {
2068
-        // determine the event id and set to array.
2069
-        $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : null;
2070
-        $EVT_ID = isset($this->_req_data['post']) ? absint($this->_req_data['post']) : $EVT_ID;
2071
-        // loop thru events
2072
-        if ($EVT_ID) {
2073
-            $success = $this->_permanently_delete_event($EVT_ID);
2074
-            // get list of events with no prices
2075
-            $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2076
-            // remove this event from the list of events with no prices
2077
-            if (isset($espresso_no_ticket_prices[ $EVT_ID ])) {
2078
-                unset($espresso_no_ticket_prices[ $EVT_ID ]);
2079
-            }
2080
-            update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2081
-        } else {
2082
-            $success = false;
2083
-            $msg = esc_html__(
2084
-                'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2085
-                'event_espresso'
2086
-            );
2087
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2088
-        }
2089
-        if ($redirect_after) {
2090
-            $this->_redirect_after_action(
2091
-                $success,
2092
-                'Event',
2093
-                'deleted',
2094
-                array('action' => 'default', 'status' => 'trash')
2095
-            );
2096
-        }
2097
-    }
2098
-
2099
-
2100
-    /**
2101
-     * _delete_events
2102
-     *
2103
-     * @access protected
2104
-     * @return void
2105
-     */
2106
-    protected function _delete_events()
2107
-    {
2108
-        $success = true;
2109
-        // get list of events with no prices
2110
-        $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2111
-        // determine the event id and set to array.
2112
-        $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
2113
-        // loop thru events
2114
-        foreach ($EVT_IDs as $EVT_ID) {
2115
-            $EVT_ID = absint($EVT_ID);
2116
-            if ($EVT_ID) {
2117
-                $results = $this->_permanently_delete_event($EVT_ID);
2118
-                $success = $results !== false ? $success : false;
2119
-                // remove this event from the list of events with no prices
2120
-                unset($espresso_no_ticket_prices[ $EVT_ID ]);
2121
-            } else {
2122
-                $success = false;
2123
-                $msg = esc_html__(
2124
-                    'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2125
-                    'event_espresso'
2126
-                );
2127
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2128
-            }
2129
-        }
2130
-        update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2131
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2132
-        $success = $success ? 2 : false;
2133
-        $this->_redirect_after_action($success, 'Events', 'deleted', array('action' => 'default'));
2134
-    }
2135
-
2136
-
2137
-    /**
2138
-     * _permanently_delete_event
2139
-     *
2140
-     * @access  private
2141
-     * @param  int $EVT_ID
2142
-     * @return bool
2143
-     */
2144
-    private function _permanently_delete_event($EVT_ID = 0)
2145
-    {
2146
-        // grab event id
2147
-        if (! $EVT_ID) {
2148
-            $msg = esc_html__(
2149
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2150
-                'event_espresso'
2151
-            );
2152
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2153
-            return false;
2154
-        }
2155
-        if (! $this->_cpt_model_obj instanceof EE_Event
2156
-            || $this->_cpt_model_obj->ID() !== $EVT_ID
2157
-        ) {
2158
-            $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2159
-        }
2160
-        if (! $this->_cpt_model_obj instanceof EE_Event) {
2161
-            return false;
2162
-        }
2163
-        // need to delete related tickets and prices first.
2164
-        $datetimes = $this->_cpt_model_obj->get_many_related('Datetime');
2165
-        foreach ($datetimes as $datetime) {
2166
-            $this->_cpt_model_obj->_remove_relation_to($datetime, 'Datetime');
2167
-            $tickets = $datetime->get_many_related('Ticket');
2168
-            foreach ($tickets as $ticket) {
2169
-                $ticket->_remove_relation_to($datetime, 'Datetime');
2170
-                $ticket->delete_related_permanently('Price');
2171
-                $ticket->delete_permanently();
2172
-            }
2173
-            $datetime->delete();
2174
-        }
2175
-        // what about related venues or terms?
2176
-        $venues = $this->_cpt_model_obj->get_many_related('Venue');
2177
-        foreach ($venues as $venue) {
2178
-            $this->_cpt_model_obj->_remove_relation_to($venue, 'Venue');
2179
-        }
2180
-        // any attached question groups?
2181
-        $question_groups = $this->_cpt_model_obj->get_many_related('Question_Group');
2182
-        if (! empty($question_groups)) {
2183
-            foreach ($question_groups as $question_group) {
2184
-                $this->_cpt_model_obj->_remove_relation_to($question_group, 'Question_Group');
2185
-            }
2186
-        }
2187
-        // Message Template Groups
2188
-        $this->_cpt_model_obj->_remove_relations('Message_Template_Group');
2189
-        /** @type EE_Term_Taxonomy[] $term_taxonomies */
2190
-        $term_taxonomies = $this->_cpt_model_obj->term_taxonomies();
2191
-        foreach ($term_taxonomies as $term_taxonomy) {
2192
-            $this->_cpt_model_obj->remove_relation_to_term_taxonomy($term_taxonomy);
2193
-        }
2194
-        $success = $this->_cpt_model_obj->delete_permanently();
2195
-        // did it all go as planned ?
2196
-        if ($success) {
2197
-            $msg = sprintf(esc_html__('Event ID # %d has been deleted.', 'event_espresso'), $EVT_ID);
2198
-            EE_Error::add_success($msg);
2199
-        } else {
2200
-            $msg = sprintf(
2201
-                esc_html__('An error occurred. Event ID # %d could not be deleted.', 'event_espresso'),
2202
-                $EVT_ID
2203
-            );
2204
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2205
-            return false;
2206
-        }
2207
-        do_action('AHEE__Events_Admin_Page___permanently_delete_event__after_event_deleted', $EVT_ID);
2208
-        return true;
2209
-    }
2210
-
2211
-
2212
-    /**
2213
-     * get total number of events
2214
-     *
2215
-     * @access public
2216
-     * @return int
2217
-     */
2218
-    public function total_events()
2219
-    {
2220
-        $count = EEM_Event::instance()->count(array('caps' => 'read_admin'), 'EVT_ID', true);
2221
-        return $count;
2222
-    }
2223
-
2224
-
2225
-    /**
2226
-     * get total number of draft events
2227
-     *
2228
-     * @access public
2229
-     * @return int
2230
-     */
2231
-    public function total_events_draft()
2232
-    {
2233
-        $where = array(
2234
-            'status' => array('IN', array('draft', 'auto-draft')),
2235
-        );
2236
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2237
-        return $count;
2238
-    }
2239
-
2240
-
2241
-    /**
2242
-     * get total number of trashed events
2243
-     *
2244
-     * @access public
2245
-     * @return int
2246
-     */
2247
-    public function total_trashed_events()
2248
-    {
2249
-        $where = array(
2250
-            'status' => 'trash',
2251
-        );
2252
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2253
-        return $count;
2254
-    }
2255
-
2256
-
2257
-    /**
2258
-     *    _default_event_settings
2259
-     *    This generates the Default Settings Tab
2260
-     *
2261
-     * @return void
2262
-     * @throws EE_Error
2263
-     */
2264
-    protected function _default_event_settings()
2265
-    {
2266
-        $this->_set_add_edit_form_tags('update_default_event_settings');
2267
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
2268
-        $this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2269
-        $this->display_admin_page_with_sidebar();
2270
-    }
2271
-
2272
-
2273
-    /**
2274
-     * Return the form for event settings.
2275
-     *
2276
-     * @return EE_Form_Section_Proper
2277
-     * @throws EE_Error
2278
-     */
2279
-    protected function _default_event_settings_form()
2280
-    {
2281
-        $registration_config = EE_Registry::instance()->CFG->registration;
2282
-        $registration_stati_for_selection = EEM_Registration::reg_status_array(
2283
-            // exclude
2284
-            array(
2285
-                EEM_Registration::status_id_cancelled,
2286
-                EEM_Registration::status_id_declined,
2287
-                EEM_Registration::status_id_incomplete,
2288
-                EEM_Registration::status_id_wait_list,
2289
-            ),
2290
-            true
2291
-        );
2292
-        return new EE_Form_Section_Proper(
2293
-            array(
2294
-                'name'            => 'update_default_event_settings',
2295
-                'html_id'         => 'update_default_event_settings',
2296
-                'html_class'      => 'form-table',
2297
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2298
-                'subsections'     => apply_filters(
2299
-                    'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2300
-                    array(
2301
-                        'default_reg_status'  => new EE_Select_Input(
2302
-                            $registration_stati_for_selection,
2303
-                            array(
2304
-                                'default'         => isset($registration_config->default_STS_ID)
2305
-                                                     && array_key_exists(
2306
-                                                         $registration_config->default_STS_ID,
2307
-                                                         $registration_stati_for_selection
2308
-                                                     )
2309
-                                    ? sanitize_text_field($registration_config->default_STS_ID)
2310
-                                    : EEM_Registration::status_id_pending_payment,
2311
-                                'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2312
-                                                     . EEH_Template::get_help_tab_link(
2313
-                                                         'default_settings_status_help_tab'
2314
-                                                     ),
2315
-                                'html_help_text'  => esc_html__(
2316
-                                    'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2317
-                                    'event_espresso'
2318
-                                ),
2319
-                            )
2320
-                        ),
2321
-                        'default_max_tickets' => new EE_Integer_Input(
2322
-                            array(
2323
-                                'default'         => isset($registration_config->default_maximum_number_of_tickets)
2324
-                                    ? $registration_config->default_maximum_number_of_tickets
2325
-                                    : EEM_Event::get_default_additional_limit(),
2326
-                                'html_label_text' => esc_html__(
2327
-                                    'Default Maximum Tickets Allowed Per Order:',
2328
-                                    'event_espresso'
2329
-                                )
2330
-                                                     . EEH_Template::get_help_tab_link(
2331
-                                                         'default_maximum_tickets_help_tab"'
2332
-                                                     ),
2333
-                                'html_help_text'  => esc_html__(
2334
-                                    'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2335
-                                    'event_espresso'
2336
-                                ),
2337
-                            )
2338
-                        ),
2339
-                    )
2340
-                ),
2341
-            )
2342
-        );
2343
-    }
2344
-
2345
-
2346
-    /**
2347
-     * _update_default_event_settings
2348
-     *
2349
-     * @access protected
2350
-     * @return void
2351
-     * @throws EE_Error
2352
-     */
2353
-    protected function _update_default_event_settings()
2354
-    {
2355
-        $registration_config = EE_Registry::instance()->CFG->registration;
2356
-        $form = $this->_default_event_settings_form();
2357
-        if ($form->was_submitted()) {
2358
-            $form->receive_form_submission();
2359
-            if ($form->is_valid()) {
2360
-                $valid_data = $form->valid_data();
2361
-                if (isset($valid_data['default_reg_status'])) {
2362
-                    $registration_config->default_STS_ID = $valid_data['default_reg_status'];
2363
-                }
2364
-                if (isset($valid_data['default_max_tickets'])) {
2365
-                    $registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2366
-                }
2367
-                // update because data was valid!
2368
-                EE_Registry::instance()->CFG->update_espresso_config();
2369
-                EE_Error::overwrite_success();
2370
-                EE_Error::add_success(
2371
-                    __('Default Event Settings were updated', 'event_espresso')
2372
-                );
2373
-            }
2374
-        }
2375
-        $this->_redirect_after_action(0, '', '', array('action' => 'default_event_settings'), true);
2376
-    }
2377
-
2378
-
2379
-    /*************        Templates        *************/
2380
-    protected function _template_settings()
2381
-    {
2382
-        $this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2383
-        $this->_template_args['preview_img'] = '<img src="'
2384
-                                               . EVENTS_ASSETS_URL
2385
-                                               . '/images/'
2386
-                                               . 'caffeinated_template_features.jpg" alt="'
2387
-                                               . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2388
-                                               . '" />';
2389
-        $this->_template_args['preview_text'] = '<strong>'
2390
-                                                . esc_html__(
2391
-                                                    'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2392
-                                                    'event_espresso'
2393
-                                                ) . '</strong>';
2394
-        $this->display_admin_caf_preview_page('template_settings_tab');
2395
-    }
2396
-
2397
-
2398
-    /** Event Category Stuff **/
2399
-    /**
2400
-     * set the _category property with the category object for the loaded page.
2401
-     *
2402
-     * @access private
2403
-     * @return void
2404
-     */
2405
-    private function _set_category_object()
2406
-    {
2407
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
2408
-            return;
2409
-        } //already have the category object so get out.
2410
-        // set default category object
2411
-        $this->_set_empty_category_object();
2412
-        // only set if we've got an id
2413
-        if (! isset($this->_req_data['EVT_CAT_ID'])) {
2414
-            return;
2415
-        }
2416
-        $category_id = absint($this->_req_data['EVT_CAT_ID']);
2417
-        $term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2418
-        if (! empty($term)) {
2419
-            $this->_category->category_name = $term->name;
2420
-            $this->_category->category_identifier = $term->slug;
2421
-            $this->_category->category_desc = $term->description;
2422
-            $this->_category->id = $term->term_id;
2423
-            $this->_category->parent = $term->parent;
2424
-        }
2425
-    }
2426
-
2427
-
2428
-    /**
2429
-     * Clears out category properties.
2430
-     */
2431
-    private function _set_empty_category_object()
2432
-    {
2433
-        $this->_category = new stdClass();
2434
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2435
-        $this->_category->id = $this->_category->parent = 0;
2436
-    }
2437
-
2438
-
2439
-    /**
2440
-     * @throws EE_Error
2441
-     */
2442
-    protected function _category_list_table()
2443
-    {
2444
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2445
-        $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2446
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2447
-            'add_category',
2448
-            'add_category',
2449
-            array(),
2450
-            'add-new-h2'
2451
-        );
2452
-        $this->display_admin_list_table_page_with_sidebar();
2453
-    }
2454
-
2455
-
2456
-    /**
2457
-     * Output category details view.
2458
-     */
2459
-    protected function _category_details($view)
2460
-    {
2461
-        // load formatter helper
2462
-        // load field generator helper
2463
-        $route = $view == 'edit' ? 'update_category' : 'insert_category';
2464
-        $this->_set_add_edit_form_tags($route);
2465
-        $this->_set_category_object();
2466
-        $id = ! empty($this->_category->id) ? $this->_category->id : '';
2467
-        $delete_action = 'delete_category';
2468
-        // custom redirect
2469
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(
2470
-            array('action' => 'category_list'),
2471
-            $this->_admin_base_url
2472
-        );
2473
-        $this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2474
-        // take care of contents
2475
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
2476
-        $this->display_admin_page_with_sidebar();
2477
-    }
2478
-
2479
-
2480
-    /**
2481
-     * Output category details content.
2482
-     */
2483
-    protected function _category_details_content()
2484
-    {
2485
-        $editor_args['category_desc'] = array(
2486
-            'type'          => 'wp_editor',
2487
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2488
-            'class'         => 'my_editor_custom',
2489
-            'wpeditor_args' => array('media_buttons' => false),
2490
-        );
2491
-        $_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2492
-        $all_terms = get_terms(
2493
-            array(EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY),
2494
-            array('hide_empty' => 0, 'exclude' => array($this->_category->id))
2495
-        );
2496
-        // setup category select for term parents.
2497
-        $category_select_values[] = array(
2498
-            'text' => esc_html__('No Parent', 'event_espresso'),
2499
-            'id'   => 0,
2500
-        );
2501
-        foreach ($all_terms as $term) {
2502
-            $category_select_values[] = array(
2503
-                'text' => $term->name,
2504
-                'id'   => $term->term_id,
2505
-            );
2506
-        }
2507
-        $category_select = EEH_Form_Fields::select_input(
2508
-            'category_parent',
2509
-            $category_select_values,
2510
-            $this->_category->parent
2511
-        );
2512
-        $template_args = array(
2513
-            'category'                 => $this->_category,
2514
-            'category_select'          => $category_select,
2515
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2516
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2517
-            'disable'                  => '',
2518
-            'disabled_message'         => false,
2519
-        );
2520
-        $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2521
-        return EEH_Template::display_template($template, $template_args, true);
2522
-    }
2523
-
2524
-
2525
-    /**
2526
-     * Handles deleting categories.
2527
-     */
2528
-    protected function _delete_categories()
2529
-    {
2530
-        $cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array) $this->_req_data['EVT_CAT_ID']
2531
-            : (array) $this->_req_data['category_id'];
2532
-        foreach ($cat_ids as $cat_id) {
2533
-            $this->_delete_category($cat_id);
2534
-        }
2535
-        // doesn't matter what page we're coming from... we're going to the same place after delete.
2536
-        $query_args = array(
2537
-            'action' => 'category_list',
2538
-        );
2539
-        $this->_redirect_after_action(0, '', '', $query_args);
2540
-    }
2541
-
2542
-
2543
-    /**
2544
-     * Handles deleting specific category.
2545
-     *
2546
-     * @param int $cat_id
2547
-     */
2548
-    protected function _delete_category($cat_id)
2549
-    {
2550
-        $cat_id = absint($cat_id);
2551
-        wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2552
-    }
2553
-
2554
-
2555
-    /**
2556
-     * Handles triggering the update or insertion of a new category.
2557
-     *
2558
-     * @param bool $new_category true means we're triggering the insert of a new category.
2559
-     */
2560
-    protected function _insert_or_update_category($new_category)
2561
-    {
2562
-        $cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2563
-        $success = 0; // we already have a success message so lets not send another.
2564
-        if ($cat_id) {
2565
-            $query_args = array(
2566
-                'action'     => 'edit_category',
2567
-                'EVT_CAT_ID' => $cat_id,
2568
-            );
2569
-        } else {
2570
-            $query_args = array('action' => 'add_category');
2571
-        }
2572
-        $this->_redirect_after_action($success, '', '', $query_args, true);
2573
-    }
2574
-
2575
-
2576
-    /**
2577
-     * Inserts or updates category
2578
-     *
2579
-     * @param bool $update (true indicates we're updating a category).
2580
-     * @return bool|mixed|string
2581
-     */
2582
-    private function _insert_category($update = false)
2583
-    {
2584
-        $cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2585
-        $category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2586
-        $category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2587
-        $category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2588
-        if (empty($category_name)) {
2589
-            $msg = esc_html__('You must add a name for the category.', 'event_espresso');
2590
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2591
-            return false;
2592
-        }
2593
-        $term_args = array(
2594
-            'name'        => $category_name,
2595
-            'description' => $category_desc,
2596
-            'parent'      => $category_parent,
2597
-        );
2598
-        // was the category_identifier input disabled?
2599
-        if (isset($this->_req_data['category_identifier'])) {
2600
-            $term_args['slug'] = $this->_req_data['category_identifier'];
2601
-        }
2602
-        $insert_ids = $update
2603
-            ? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2604
-            : wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2605
-        if (! is_array($insert_ids)) {
2606
-            $msg = esc_html__(
2607
-                'An error occurred and the category has not been saved to the database.',
2608
-                'event_espresso'
2609
-            );
2610
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2611
-        } else {
2612
-            $cat_id = $insert_ids['term_id'];
2613
-            $msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2614
-            EE_Error::add_success($msg);
2615
-        }
2616
-        return $cat_id;
2617
-    }
2618
-
2619
-
2620
-    /**
2621
-     * Gets categories or count of categories matching the arguments in the request.
2622
-     *
2623
-     * @param int  $per_page
2624
-     * @param int  $current_page
2625
-     * @param bool $count
2626
-     * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2627
-     */
2628
-    public function get_categories($per_page = 10, $current_page = 1, $count = false)
2629
-    {
2630
-        // testing term stuff
2631
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2632
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2633
-        $limit = ($current_page - 1) * $per_page;
2634
-        $where = array('taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2635
-        if (isset($this->_req_data['s'])) {
2636
-            $sstr = '%' . $this->_req_data['s'] . '%';
2637
-            $where['OR'] = array(
2638
-                'Term.name'   => array('LIKE', $sstr),
2639
-                'description' => array('LIKE', $sstr),
2640
-            );
2641
-        }
2642
-        $query_params = array(
2643
-            $where,
2644
-            'order_by'   => array($orderby => $order),
2645
-            'limit'      => $limit . ',' . $per_page,
2646
-            'force_join' => array('Term'),
2647
-        );
2648
-        $categories = $count
2649
-            ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2650
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
2651
-        return $categories;
2652
-    }
2653
-
2654
-    /* end category stuff */
2655
-    /**************/
2656
-
2657
-
2658
-    /**
2659
-     * Callback for the `ee_save_timezone_setting` ajax action.
2660
-     *
2661
-     * @throws EE_Error
2662
-     */
2663
-    public function save_timezonestring_setting()
2664
-    {
2665
-        $timezone_string = isset($this->_req_data['timezone_selected'])
2666
-            ? $this->_req_data['timezone_selected']
2667
-            : '';
2668
-        if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2669
-            EE_Error::add_error(
2670
-                esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2671
-                __FILE__,
2672
-                __FUNCTION__,
2673
-                __LINE__
2674
-            );
2675
-            $this->_template_args['error'] = true;
2676
-            $this->_return_json();
2677
-        }
2678
-
2679
-        update_option('timezone_string', $timezone_string);
2680
-        EE_Error::add_success(
2681
-            esc_html__('Your timezone string was updated.', 'event_espresso')
2682
-        );
2683
-        $this->_template_args['success'] = true;
2684
-        $this->_return_json(true, array('action' => 'create_new'));
2685
-    }
15
+	/**
16
+	 * This will hold the event object for event_details screen.
17
+	 *
18
+	 * @access protected
19
+	 * @var EE_Event $_event
20
+	 */
21
+	protected $_event;
22
+
23
+
24
+	/**
25
+	 * This will hold the category object for category_details screen.
26
+	 *
27
+	 * @var stdClass $_category
28
+	 */
29
+	protected $_category;
30
+
31
+
32
+	/**
33
+	 * This will hold the event model instance
34
+	 *
35
+	 * @var EEM_Event $_event_model
36
+	 */
37
+	protected $_event_model;
38
+
39
+
40
+	/**
41
+	 * @var EE_Event
42
+	 */
43
+	protected $_cpt_model_obj = false;
44
+
45
+
46
+	/**
47
+	 * Initialize page props for this admin page group.
48
+	 */
49
+	protected function _init_page_props()
50
+	{
51
+		$this->page_slug = EVENTS_PG_SLUG;
52
+		$this->page_label = EVENTS_LABEL;
53
+		$this->_admin_base_url = EVENTS_ADMIN_URL;
54
+		$this->_admin_base_path = EVENTS_ADMIN;
55
+		$this->_cpt_model_names = array(
56
+			'create_new' => 'EEM_Event',
57
+			'edit'       => 'EEM_Event',
58
+		);
59
+		$this->_cpt_edit_routes = array(
60
+			'espresso_events' => 'edit',
61
+		);
62
+		add_action(
63
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
64
+			array($this, 'verify_event_edit'),
65
+			10,
66
+			2
67
+		);
68
+	}
69
+
70
+
71
+	/**
72
+	 * Sets the ajax hooks used for this admin page group.
73
+	 */
74
+	protected function _ajax_hooks()
75
+	{
76
+		add_action('wp_ajax_ee_save_timezone_setting', array($this, 'save_timezonestring_setting'));
77
+	}
78
+
79
+
80
+	/**
81
+	 * Sets the page properties for this admin page group.
82
+	 */
83
+	protected function _define_page_props()
84
+	{
85
+		$this->_admin_page_title = EVENTS_LABEL;
86
+		$this->_labels = array(
87
+			'buttons'      => array(
88
+				'add'             => esc_html__('Add New Event', 'event_espresso'),
89
+				'edit'            => esc_html__('Edit Event', 'event_espresso'),
90
+				'delete'          => esc_html__('Delete Event', 'event_espresso'),
91
+				'add_category'    => esc_html__('Add New Category', 'event_espresso'),
92
+				'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
93
+				'delete_category' => esc_html__('Delete Category', 'event_espresso'),
94
+			),
95
+			'editor_title' => array(
96
+				'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
97
+			),
98
+			'publishbox'   => array(
99
+				'create_new'        => esc_html__('Save New Event', 'event_espresso'),
100
+				'edit'              => esc_html__('Update Event', 'event_espresso'),
101
+				'add_category'      => esc_html__('Save New Category', 'event_espresso'),
102
+				'edit_category'     => esc_html__('Update Category', 'event_espresso'),
103
+				'template_settings' => esc_html__('Update Settings', 'event_espresso'),
104
+			),
105
+		);
106
+	}
107
+
108
+
109
+	/**
110
+	 * Sets the page routes property for this admin page group.
111
+	 */
112
+	protected function _set_page_routes()
113
+	{
114
+		// load formatter helper
115
+		// load field generator helper
116
+		// is there a evt_id in the request?
117
+		$evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
118
+			? $this->_req_data['EVT_ID']
119
+			: 0;
120
+		$evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
121
+		$this->_page_routes = array(
122
+			'default'                       => array(
123
+				'func'       => '_events_overview_list_table',
124
+				'capability' => 'ee_read_events',
125
+			),
126
+			'create_new'                    => array(
127
+				'func'       => '_create_new_cpt_item',
128
+				'capability' => 'ee_edit_events',
129
+			),
130
+			'edit'                          => array(
131
+				'func'       => '_edit_cpt_item',
132
+				'capability' => 'ee_edit_event',
133
+				'obj_id'     => $evt_id,
134
+			),
135
+			'copy_event'                    => array(
136
+				'func'       => '_copy_events',
137
+				'capability' => 'ee_edit_event',
138
+				'obj_id'     => $evt_id,
139
+				'noheader'   => true,
140
+			),
141
+			'trash_event'                   => array(
142
+				'func'       => '_trash_or_restore_event',
143
+				'args'       => array('event_status' => 'trash'),
144
+				'capability' => 'ee_delete_event',
145
+				'obj_id'     => $evt_id,
146
+				'noheader'   => true,
147
+			),
148
+			'trash_events'                  => array(
149
+				'func'       => '_trash_or_restore_events',
150
+				'args'       => array('event_status' => 'trash'),
151
+				'capability' => 'ee_delete_events',
152
+				'noheader'   => true,
153
+			),
154
+			'restore_event'                 => array(
155
+				'func'       => '_trash_or_restore_event',
156
+				'args'       => array('event_status' => 'draft'),
157
+				'capability' => 'ee_delete_event',
158
+				'obj_id'     => $evt_id,
159
+				'noheader'   => true,
160
+			),
161
+			'restore_events'                => array(
162
+				'func'       => '_trash_or_restore_events',
163
+				'args'       => array('event_status' => 'draft'),
164
+				'capability' => 'ee_delete_events',
165
+				'noheader'   => true,
166
+			),
167
+			'delete_event'                  => array(
168
+				'func'       => '_delete_event',
169
+				'capability' => 'ee_delete_event',
170
+				'obj_id'     => $evt_id,
171
+				'noheader'   => true,
172
+			),
173
+			'delete_events'                 => array(
174
+				'func'       => '_delete_events',
175
+				'capability' => 'ee_delete_events',
176
+				'noheader'   => true,
177
+			),
178
+			'view_report'                   => array(
179
+				'func'      => '_view_report',
180
+				'capablity' => 'ee_edit_events',
181
+			),
182
+			'default_event_settings'        => array(
183
+				'func'       => '_default_event_settings',
184
+				'capability' => 'manage_options',
185
+			),
186
+			'update_default_event_settings' => array(
187
+				'func'       => '_update_default_event_settings',
188
+				'capability' => 'manage_options',
189
+				'noheader'   => true,
190
+			),
191
+			'template_settings'             => array(
192
+				'func'       => '_template_settings',
193
+				'capability' => 'manage_options',
194
+			),
195
+			// event category tab related
196
+			'add_category'                  => array(
197
+				'func'       => '_category_details',
198
+				'capability' => 'ee_edit_event_category',
199
+				'args'       => array('add'),
200
+			),
201
+			'edit_category'                 => array(
202
+				'func'       => '_category_details',
203
+				'capability' => 'ee_edit_event_category',
204
+				'args'       => array('edit'),
205
+			),
206
+			'delete_categories'             => array(
207
+				'func'       => '_delete_categories',
208
+				'capability' => 'ee_delete_event_category',
209
+				'noheader'   => true,
210
+			),
211
+			'delete_category'               => array(
212
+				'func'       => '_delete_categories',
213
+				'capability' => 'ee_delete_event_category',
214
+				'noheader'   => true,
215
+			),
216
+			'insert_category'               => array(
217
+				'func'       => '_insert_or_update_category',
218
+				'args'       => array('new_category' => true),
219
+				'capability' => 'ee_edit_event_category',
220
+				'noheader'   => true,
221
+			),
222
+			'update_category'               => array(
223
+				'func'       => '_insert_or_update_category',
224
+				'args'       => array('new_category' => false),
225
+				'capability' => 'ee_edit_event_category',
226
+				'noheader'   => true,
227
+			),
228
+			'category_list'                 => array(
229
+				'func'       => '_category_list_table',
230
+				'capability' => 'ee_manage_event_categories',
231
+			),
232
+		);
233
+	}
234
+
235
+
236
+	/**
237
+	 * Set the _page_config property for this admin page group.
238
+	 */
239
+	protected function _set_page_config()
240
+	{
241
+		$this->_page_config = array(
242
+			'default'                => array(
243
+				'nav'           => array(
244
+					'label' => esc_html__('Overview', 'event_espresso'),
245
+					'order' => 10,
246
+				),
247
+				'list_table'    => 'Events_Admin_List_Table',
248
+				'help_tabs'     => array(
249
+					'events_overview_help_tab'                       => array(
250
+						'title'    => esc_html__('Events Overview', 'event_espresso'),
251
+						'filename' => 'events_overview',
252
+					),
253
+					'events_overview_table_column_headings_help_tab' => array(
254
+						'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
255
+						'filename' => 'events_overview_table_column_headings',
256
+					),
257
+					'events_overview_filters_help_tab'               => array(
258
+						'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
259
+						'filename' => 'events_overview_filters',
260
+					),
261
+					'events_overview_view_help_tab'                  => array(
262
+						'title'    => esc_html__('Events Overview Views', 'event_espresso'),
263
+						'filename' => 'events_overview_views',
264
+					),
265
+					'events_overview_other_help_tab'                 => array(
266
+						'title'    => esc_html__('Events Overview Other', 'event_espresso'),
267
+						'filename' => 'events_overview_other',
268
+					),
269
+				),
270
+				'help_tour'     => array(
271
+					'Event_Overview_Help_Tour',
272
+					// 'New_Features_Test_Help_Tour' for testing multiple help tour
273
+				),
274
+				'qtips'         => array(
275
+					'EE_Event_List_Table_Tips',
276
+				),
277
+				'require_nonce' => false,
278
+			),
279
+			'create_new'             => array(
280
+				'nav'           => array(
281
+					'label'      => esc_html__('Add Event', 'event_espresso'),
282
+					'order'      => 5,
283
+					'persistent' => false,
284
+				),
285
+				'metaboxes'     => array('_register_event_editor_meta_boxes'),
286
+				'help_tabs'     => array(
287
+					'event_editor_help_tab'                            => array(
288
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
289
+						'filename' => 'event_editor',
290
+					),
291
+					'event_editor_title_richtexteditor_help_tab'       => array(
292
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
293
+						'filename' => 'event_editor_title_richtexteditor',
294
+					),
295
+					'event_editor_venue_details_help_tab'              => array(
296
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
297
+						'filename' => 'event_editor_venue_details',
298
+					),
299
+					'event_editor_event_datetimes_help_tab'            => array(
300
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
301
+						'filename' => 'event_editor_event_datetimes',
302
+					),
303
+					'event_editor_event_tickets_help_tab'              => array(
304
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
305
+						'filename' => 'event_editor_event_tickets',
306
+					),
307
+					'event_editor_event_registration_options_help_tab' => array(
308
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
309
+						'filename' => 'event_editor_event_registration_options',
310
+					),
311
+					'event_editor_tags_categories_help_tab'            => array(
312
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
313
+						'filename' => 'event_editor_tags_categories',
314
+					),
315
+					'event_editor_questions_registrants_help_tab'      => array(
316
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
317
+						'filename' => 'event_editor_questions_registrants',
318
+					),
319
+					'event_editor_save_new_event_help_tab'             => array(
320
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
321
+						'filename' => 'event_editor_save_new_event',
322
+					),
323
+					'event_editor_other_help_tab'                      => array(
324
+						'title'    => esc_html__('Event Other', 'event_espresso'),
325
+						'filename' => 'event_editor_other',
326
+					),
327
+				),
328
+				'help_tour'     => array(
329
+					'Event_Editor_Help_Tour',
330
+				),
331
+				'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
332
+				'require_nonce' => false,
333
+			),
334
+			'edit'                   => array(
335
+				'nav'           => array(
336
+					'label'      => esc_html__('Edit Event', 'event_espresso'),
337
+					'order'      => 5,
338
+					'persistent' => false,
339
+					'url'        => isset($this->_req_data['post'])
340
+						? EE_Admin_Page::add_query_args_and_nonce(
341
+							array('post' => $this->_req_data['post'], 'action' => 'edit'),
342
+							$this->_current_page_view_url
343
+						)
344
+						: $this->_admin_base_url,
345
+				),
346
+				'metaboxes'     => array('_register_event_editor_meta_boxes'),
347
+				'help_tabs'     => array(
348
+					'event_editor_help_tab'                            => array(
349
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
350
+						'filename' => 'event_editor',
351
+					),
352
+					'event_editor_title_richtexteditor_help_tab'       => array(
353
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
354
+						'filename' => 'event_editor_title_richtexteditor',
355
+					),
356
+					'event_editor_venue_details_help_tab'              => array(
357
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
358
+						'filename' => 'event_editor_venue_details',
359
+					),
360
+					'event_editor_event_datetimes_help_tab'            => array(
361
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
362
+						'filename' => 'event_editor_event_datetimes',
363
+					),
364
+					'event_editor_event_tickets_help_tab'              => array(
365
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
366
+						'filename' => 'event_editor_event_tickets',
367
+					),
368
+					'event_editor_event_registration_options_help_tab' => array(
369
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
370
+						'filename' => 'event_editor_event_registration_options',
371
+					),
372
+					'event_editor_tags_categories_help_tab'            => array(
373
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
374
+						'filename' => 'event_editor_tags_categories',
375
+					),
376
+					'event_editor_questions_registrants_help_tab'      => array(
377
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
378
+						'filename' => 'event_editor_questions_registrants',
379
+					),
380
+					'event_editor_save_new_event_help_tab'             => array(
381
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
382
+						'filename' => 'event_editor_save_new_event',
383
+					),
384
+					'event_editor_other_help_tab'                      => array(
385
+						'title'    => esc_html__('Event Other', 'event_espresso'),
386
+						'filename' => 'event_editor_other',
387
+					),
388
+				),
389
+				'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
390
+				'require_nonce' => false,
391
+			),
392
+			'default_event_settings' => array(
393
+				'nav'           => array(
394
+					'label' => esc_html__('Default Settings', 'event_espresso'),
395
+					'order' => 40,
396
+				),
397
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
398
+				'labels'        => array(
399
+					'publishbox' => esc_html__('Update Settings', 'event_espresso'),
400
+				),
401
+				'help_tabs'     => array(
402
+					'default_settings_help_tab'        => array(
403
+						'title'    => esc_html__('Default Event Settings', 'event_espresso'),
404
+						'filename' => 'events_default_settings',
405
+					),
406
+					'default_settings_status_help_tab' => array(
407
+						'title'    => esc_html__('Default Registration Status', 'event_espresso'),
408
+						'filename' => 'events_default_settings_status',
409
+					),
410
+					'default_maximum_tickets_help_tab' => array(
411
+						'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
412
+						'filename' => 'events_default_settings_max_tickets',
413
+					),
414
+				),
415
+				'help_tour'     => array('Event_Default_Settings_Help_Tour'),
416
+				'require_nonce' => false,
417
+			),
418
+			// template settings
419
+			'template_settings'      => array(
420
+				'nav'           => array(
421
+					'label' => esc_html__('Templates', 'event_espresso'),
422
+					'order' => 30,
423
+				),
424
+				'metaboxes'     => $this->_default_espresso_metaboxes,
425
+				'help_tabs'     => array(
426
+					'general_settings_templates_help_tab' => array(
427
+						'title'    => esc_html__('Templates', 'event_espresso'),
428
+						'filename' => 'general_settings_templates',
429
+					),
430
+				),
431
+				'help_tour'     => array('Templates_Help_Tour'),
432
+				'require_nonce' => false,
433
+			),
434
+			// event category stuff
435
+			'add_category'           => array(
436
+				'nav'           => array(
437
+					'label'      => esc_html__('Add Category', 'event_espresso'),
438
+					'order'      => 15,
439
+					'persistent' => false,
440
+				),
441
+				'help_tabs'     => array(
442
+					'add_category_help_tab' => array(
443
+						'title'    => esc_html__('Add New Event Category', 'event_espresso'),
444
+						'filename' => 'events_add_category',
445
+					),
446
+				),
447
+				'help_tour'     => array('Event_Add_Category_Help_Tour'),
448
+				'metaboxes'     => array('_publish_post_box'),
449
+				'require_nonce' => false,
450
+			),
451
+			'edit_category'          => array(
452
+				'nav'           => array(
453
+					'label'      => esc_html__('Edit Category', 'event_espresso'),
454
+					'order'      => 15,
455
+					'persistent' => false,
456
+					'url'        => isset($this->_req_data['EVT_CAT_ID'])
457
+						? add_query_arg(
458
+							array('EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']),
459
+							$this->_current_page_view_url
460
+						)
461
+						: $this->_admin_base_url,
462
+				),
463
+				'help_tabs'     => array(
464
+					'edit_category_help_tab' => array(
465
+						'title'    => esc_html__('Edit Event Category', 'event_espresso'),
466
+						'filename' => 'events_edit_category',
467
+					),
468
+				),
469
+				/*'help_tour' => array('Event_Edit_Category_Help_Tour'),*/
470
+				'metaboxes'     => array('_publish_post_box'),
471
+				'require_nonce' => false,
472
+			),
473
+			'category_list'          => array(
474
+				'nav'           => array(
475
+					'label' => esc_html__('Categories', 'event_espresso'),
476
+					'order' => 20,
477
+				),
478
+				'list_table'    => 'Event_Categories_Admin_List_Table',
479
+				'help_tabs'     => array(
480
+					'events_categories_help_tab'                       => array(
481
+						'title'    => esc_html__('Event Categories', 'event_espresso'),
482
+						'filename' => 'events_categories',
483
+					),
484
+					'events_categories_table_column_headings_help_tab' => array(
485
+						'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
486
+						'filename' => 'events_categories_table_column_headings',
487
+					),
488
+					'events_categories_view_help_tab'                  => array(
489
+						'title'    => esc_html__('Event Categories Views', 'event_espresso'),
490
+						'filename' => 'events_categories_views',
491
+					),
492
+					'events_categories_other_help_tab'                 => array(
493
+						'title'    => esc_html__('Event Categories Other', 'event_espresso'),
494
+						'filename' => 'events_categories_other',
495
+					),
496
+				),
497
+				'help_tour'     => array(
498
+					'Event_Categories_Help_Tour',
499
+				),
500
+				'metaboxes'     => $this->_default_espresso_metaboxes,
501
+				'require_nonce' => false,
502
+			),
503
+		);
504
+	}
505
+
506
+
507
+	/**
508
+	 * Used to register any global screen options if necessary for every route in this admin page group.
509
+	 */
510
+	protected function _add_screen_options()
511
+	{
512
+	}
513
+
514
+
515
+	/**
516
+	 * Implementing the screen options for the 'default' route.
517
+	 */
518
+	protected function _add_screen_options_default()
519
+	{
520
+		$this->_per_page_screen_option();
521
+	}
522
+
523
+
524
+	/**
525
+	 * Implementing screen options for the category list route.
526
+	 */
527
+	protected function _add_screen_options_category_list()
528
+	{
529
+		$page_title = $this->_admin_page_title;
530
+		$this->_admin_page_title = esc_html__('Categories', 'event_espresso');
531
+		$this->_per_page_screen_option();
532
+		$this->_admin_page_title = $page_title;
533
+	}
534
+
535
+
536
+	/**
537
+	 * Used to register any global feature pointers for the admin page group.
538
+	 */
539
+	protected function _add_feature_pointers()
540
+	{
541
+	}
542
+
543
+
544
+	/**
545
+	 * Registers and enqueues any global scripts and styles for the entire admin page group.
546
+	 */
547
+	public function load_scripts_styles()
548
+	{
549
+		wp_register_style(
550
+			'events-admin-css',
551
+			EVENTS_ASSETS_URL . 'events-admin-page.css',
552
+			array(),
553
+			EVENT_ESPRESSO_VERSION
554
+		);
555
+		wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
556
+		wp_enqueue_style('events-admin-css');
557
+		wp_enqueue_style('ee-cat-admin');
558
+		// todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
559
+		// registers for all views
560
+		// scripts
561
+		wp_register_script(
562
+			'event_editor_js',
563
+			EVENTS_ASSETS_URL . 'event_editor.js',
564
+			array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
565
+			EVENT_ESPRESSO_VERSION,
566
+			true
567
+		);
568
+	}
569
+
570
+
571
+	/**
572
+	 * Enqueuing scripts and styles specific to this view
573
+	 */
574
+	public function load_scripts_styles_create_new()
575
+	{
576
+		$this->load_scripts_styles_edit();
577
+	}
578
+
579
+
580
+	/**
581
+	 * Enqueuing scripts and styles specific to this view
582
+	 */
583
+	public function load_scripts_styles_edit()
584
+	{
585
+		// styles
586
+		wp_enqueue_style('espresso-ui-theme');
587
+		wp_register_style(
588
+			'event-editor-css',
589
+			EVENTS_ASSETS_URL . 'event-editor.css',
590
+			array('ee-admin-css'),
591
+			EVENT_ESPRESSO_VERSION
592
+		);
593
+		wp_enqueue_style('event-editor-css');
594
+		// scripts
595
+		wp_register_script(
596
+			'event-datetime-metabox',
597
+			EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
598
+			array('event_editor_js', 'ee-datepicker'),
599
+			EVENT_ESPRESSO_VERSION
600
+		);
601
+		wp_enqueue_script('event-datetime-metabox');
602
+	}
603
+
604
+
605
+	/**
606
+	 * Populating the _views property for the category list table view.
607
+	 */
608
+	protected function _set_list_table_views_category_list()
609
+	{
610
+		$this->_views = array(
611
+			'all' => array(
612
+				'slug'        => 'all',
613
+				'label'       => esc_html__('All', 'event_espresso'),
614
+				'count'       => 0,
615
+				'bulk_action' => array(
616
+					'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
617
+				),
618
+			),
619
+		);
620
+	}
621
+
622
+
623
+	/**
624
+	 * For adding anything that fires on the admin_init hook for any route within this admin page group.
625
+	 */
626
+	public function admin_init()
627
+	{
628
+		EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
629
+			'Do you really want to delete this image? Please remember to update your event to complete the removal.',
630
+			'event_espresso'
631
+		);
632
+	}
633
+
634
+
635
+	/**
636
+	 * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
637
+	 * group.
638
+	 */
639
+	public function admin_notices()
640
+	{
641
+	}
642
+
643
+
644
+	/**
645
+	 * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
646
+	 * this admin page group.
647
+	 */
648
+	public function admin_footer_scripts()
649
+	{
650
+	}
651
+
652
+
653
+	/**
654
+	 * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
655
+	 * warning (via EE_Error::add_error());
656
+	 *
657
+	 * @param  EE_Event $event Event object
658
+	 * @param string    $req_type
659
+	 * @return void
660
+	 * @throws EE_Error
661
+	 * @access public
662
+	 */
663
+	public function verify_event_edit($event = null, $req_type = '')
664
+	{
665
+		// don't need to do this when processing
666
+		if (! empty($req_type)) {
667
+			return;
668
+		}
669
+		// no event?
670
+		if (empty($event)) {
671
+			// set event
672
+			$event = $this->_cpt_model_obj;
673
+		}
674
+		// STILL no event?
675
+		if (! $event instanceof EE_Event) {
676
+			return;
677
+		}
678
+		$orig_status = $event->status();
679
+		// first check if event is active.
680
+		if ($orig_status === EEM_Event::cancelled
681
+			|| $orig_status === EEM_Event::postponed
682
+			|| $event->is_expired()
683
+			|| $event->is_inactive()
684
+		) {
685
+			return;
686
+		}
687
+		// made it here so it IS active... next check that any of the tickets are sold.
688
+		if ($event->is_sold_out(true)) {
689
+			if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
690
+				EE_Error::add_attention(
691
+					sprintf(
692
+						esc_html__(
693
+							'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
694
+							'event_espresso'
695
+						),
696
+						EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
697
+					)
698
+				);
699
+			}
700
+			return;
701
+		} elseif ($orig_status === EEM_Event::sold_out) {
702
+			EE_Error::add_attention(
703
+				sprintf(
704
+					esc_html__(
705
+						'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
706
+						'event_espresso'
707
+					),
708
+					EEH_Template::pretty_status($event->status(), false, 'sentence')
709
+				)
710
+			);
711
+		}
712
+		// now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
713
+		if (! $event->tickets_on_sale()) {
714
+			return;
715
+		}
716
+		// made it here so show warning
717
+		$this->_edit_event_warning();
718
+	}
719
+
720
+
721
+	/**
722
+	 * This is the text used for when an event is being edited that is public and has tickets for sale.
723
+	 * When needed, hook this into a EE_Error::add_error() notice.
724
+	 *
725
+	 * @access protected
726
+	 * @return void
727
+	 */
728
+	protected function _edit_event_warning()
729
+	{
730
+		// we don't want to add warnings during these requests
731
+		if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
732
+			return;
733
+		}
734
+		EE_Error::add_attention(
735
+			sprintf(
736
+				esc_html__(
737
+					'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
738
+					'event_espresso'
739
+				),
740
+				'<a class="espresso-help-tab-lnk">',
741
+				'</a>'
742
+			)
743
+		);
744
+	}
745
+
746
+
747
+	/**
748
+	 * When a user is creating a new event, notify them if they haven't set their timezone.
749
+	 * Otherwise, do the normal logic
750
+	 *
751
+	 * @return string
752
+	 * @throws \EE_Error
753
+	 */
754
+	protected function _create_new_cpt_item()
755
+	{
756
+		$has_timezone_string = get_option('timezone_string');
757
+		// only nag them about setting their timezone if it's their first event, and they haven't already done it
758
+		if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
759
+			EE_Error::add_attention(
760
+				sprintf(
761
+					__(
762
+						'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
763
+						'event_espresso'
764
+					),
765
+					'<br>',
766
+					'<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
767
+					. EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
768
+					. '</select>',
769
+					'<button class="button button-secondary timezone-submit">',
770
+					'</button><span class="spinner"></span>'
771
+				),
772
+				__FILE__,
773
+				__FUNCTION__,
774
+				__LINE__
775
+			);
776
+		}
777
+		return parent::_create_new_cpt_item();
778
+	}
779
+
780
+
781
+	/**
782
+	 * Sets the _views property for the default route in this admin page group.
783
+	 */
784
+	protected function _set_list_table_views_default()
785
+	{
786
+		$this->_views = array(
787
+			'all'   => array(
788
+				'slug'        => 'all',
789
+				'label'       => esc_html__('View All Events', 'event_espresso'),
790
+				'count'       => 0,
791
+				'bulk_action' => array(
792
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
793
+				),
794
+			),
795
+			'draft' => array(
796
+				'slug'        => 'draft',
797
+				'label'       => esc_html__('Draft', 'event_espresso'),
798
+				'count'       => 0,
799
+				'bulk_action' => array(
800
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
801
+				),
802
+			),
803
+		);
804
+		if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
805
+			$this->_views['trash'] = array(
806
+				'slug'        => 'trash',
807
+				'label'       => esc_html__('Trash', 'event_espresso'),
808
+				'count'       => 0,
809
+				'bulk_action' => array(
810
+					'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
811
+					'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
812
+				),
813
+			);
814
+		}
815
+	}
816
+
817
+
818
+	/**
819
+	 * Provides the legend item array for the default list table view.
820
+	 *
821
+	 * @return array
822
+	 */
823
+	protected function _event_legend_items()
824
+	{
825
+		$items = array(
826
+			'view_details'   => array(
827
+				'class' => 'dashicons dashicons-search',
828
+				'desc'  => esc_html__('View Event', 'event_espresso'),
829
+			),
830
+			'edit_event'     => array(
831
+				'class' => 'ee-icon ee-icon-calendar-edit',
832
+				'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
833
+			),
834
+			'view_attendees' => array(
835
+				'class' => 'dashicons dashicons-groups',
836
+				'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
837
+			),
838
+		);
839
+		$items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
840
+		$statuses = array(
841
+			'sold_out_status'  => array(
842
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
843
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
844
+			),
845
+			'active_status'    => array(
846
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
847
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
848
+			),
849
+			'upcoming_status'  => array(
850
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
851
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
852
+			),
853
+			'postponed_status' => array(
854
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
855
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
856
+			),
857
+			'cancelled_status' => array(
858
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
859
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
860
+			),
861
+			'expired_status'   => array(
862
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
863
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
864
+			),
865
+			'inactive_status'  => array(
866
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
867
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
868
+			),
869
+		);
870
+		$statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
871
+		return array_merge($items, $statuses);
872
+	}
873
+
874
+
875
+	/**
876
+	 * @return EEM_Event
877
+	 */
878
+	private function _event_model()
879
+	{
880
+		if (! $this->_event_model instanceof EEM_Event) {
881
+			$this->_event_model = EE_Registry::instance()->load_model('Event');
882
+		}
883
+		return $this->_event_model;
884
+	}
885
+
886
+
887
+	/**
888
+	 * Adds extra buttons to the WP CPT permalink field row.
889
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
890
+	 *
891
+	 * @param  string $return    the current html
892
+	 * @param  int    $id        the post id for the page
893
+	 * @param  string $new_title What the title is
894
+	 * @param  string $new_slug  what the slug is
895
+	 * @return string            The new html string for the permalink area
896
+	 */
897
+	public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
898
+	{
899
+		// make sure this is only when editing
900
+		if (! empty($id)) {
901
+			$post = get_post($id);
902
+			$return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
903
+					   . esc_html__('Shortcode', 'event_espresso')
904
+					   . '</a> ';
905
+			$return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
906
+					   . $post->ID
907
+					   . ']">';
908
+		}
909
+		return $return;
910
+	}
911
+
912
+
913
+	/**
914
+	 * _events_overview_list_table
915
+	 * This contains the logic for showing the events_overview list
916
+	 *
917
+	 * @access protected
918
+	 * @return void
919
+	 * @throws \EE_Error
920
+	 */
921
+	protected function _events_overview_list_table()
922
+	{
923
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
924
+		$this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
925
+			? (array) $this->_template_args['after_list_table']
926
+			: array();
927
+		$this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
928
+				. EEH_Template::get_button_or_link(
929
+					get_post_type_archive_link('espresso_events'),
930
+					esc_html__("View Event Archive Page", "event_espresso"),
931
+					'button'
932
+				);
933
+		$this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
934
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
935
+			'create_new',
936
+			'add',
937
+			array(),
938
+			'add-new-h2'
939
+		);
940
+		$this->display_admin_list_table_page_with_no_sidebar();
941
+	}
942
+
943
+
944
+	/**
945
+	 * this allows for extra misc actions in the default WP publish box
946
+	 *
947
+	 * @return void
948
+	 */
949
+	public function extra_misc_actions_publish_box()
950
+	{
951
+		$this->_generate_publish_box_extra_content();
952
+	}
953
+
954
+
955
+	/**
956
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
957
+	 * saved.
958
+	 * Typically you would use this to save any additional data.
959
+	 * Keep in mind also that "save_post" runs on EVERY post update to the database.
960
+	 * ALSO very important.  When a post transitions from scheduled to published,
961
+	 * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
962
+	 * other meta saves. So MAKE sure that you handle this accordingly.
963
+	 *
964
+	 * @access protected
965
+	 * @abstract
966
+	 * @param  string $post_id The ID of the cpt that was saved (so you can link relationally)
967
+	 * @param  object $post    The post object of the cpt that was saved.
968
+	 * @return void
969
+	 * @throws \EE_Error
970
+	 */
971
+	protected function _insert_update_cpt_item($post_id, $post)
972
+	{
973
+		if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
974
+			// get out we're not processing an event save.
975
+			return;
976
+		}
977
+		$event_values = array(
978
+			'EVT_display_desc'                => ! empty($this->_req_data['display_desc']) ? 1 : 0,
979
+			'EVT_display_ticket_selector'     => ! empty($this->_req_data['display_ticket_selector']) ? 1 : 0,
980
+			'EVT_additional_limit'            => min(
981
+				apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
982
+				! empty($this->_req_data['additional_limit']) ? $this->_req_data['additional_limit'] : null
983
+			),
984
+			'EVT_default_registration_status' => ! empty($this->_req_data['EVT_default_registration_status'])
985
+				? $this->_req_data['EVT_default_registration_status']
986
+				: EE_Registry::instance()->CFG->registration->default_STS_ID,
987
+			'EVT_member_only'                 => ! empty($this->_req_data['member_only']) ? 1 : 0,
988
+			'EVT_allow_overflow'              => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
989
+			'EVT_timezone_string'             => ! empty($this->_req_data['timezone_string'])
990
+				? $this->_req_data['timezone_string'] : null,
991
+			'EVT_external_URL'                => ! empty($this->_req_data['externalURL'])
992
+				? $this->_req_data['externalURL'] : null,
993
+			'EVT_phone'                       => ! empty($this->_req_data['event_phone'])
994
+				? $this->_req_data['event_phone'] : null,
995
+		);
996
+		// update event
997
+		$success = $this->_event_model()->update_by_ID($event_values, $post_id);
998
+		// get event_object for other metaboxes... though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
999
+		$get_one_where = array(
1000
+			$this->_event_model()->primary_key_name() => $post_id,
1001
+			'OR'                                      => array(
1002
+				'status'   => $post->post_status,
1003
+				// if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1004
+				// but the returned object here has a status of "publish", so use the original post status as well
1005
+				'status*1' => $this->_req_data['original_post_status'],
1006
+			),
1007
+		);
1008
+		$event = $this->_event_model()->get_one(array($get_one_where));
1009
+		// the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1010
+		$event_update_callbacks = apply_filters(
1011
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1012
+			array(
1013
+				array($this, '_default_venue_update'),
1014
+				array($this, '_default_tickets_update'),
1015
+			)
1016
+		);
1017
+		$att_success = true;
1018
+		foreach ($event_update_callbacks as $e_callback) {
1019
+			$_success = is_callable($e_callback)
1020
+				? call_user_func($e_callback, $event, $this->_req_data)
1021
+				: false;
1022
+			// if ANY of these updates fail then we want the appropriate global error message
1023
+			$att_success = ! $att_success ? $att_success : $_success;
1024
+		}
1025
+		// any errors?
1026
+		if ($success && false === $att_success) {
1027
+			EE_Error::add_error(
1028
+				esc_html__(
1029
+					'Event Details saved successfully but something went wrong with saving attachments.',
1030
+					'event_espresso'
1031
+				),
1032
+				__FILE__,
1033
+				__FUNCTION__,
1034
+				__LINE__
1035
+			);
1036
+		} elseif ($success === false) {
1037
+			EE_Error::add_error(
1038
+				esc_html__('Event Details did not save successfully.', 'event_espresso'),
1039
+				__FILE__,
1040
+				__FUNCTION__,
1041
+				__LINE__
1042
+			);
1043
+		}
1044
+	}
1045
+
1046
+
1047
+	/**
1048
+	 * @see parent::restore_item()
1049
+	 * @param int $post_id
1050
+	 * @param int $revision_id
1051
+	 */
1052
+	protected function _restore_cpt_item($post_id, $revision_id)
1053
+	{
1054
+		// copy existing event meta to new post
1055
+		$post_evt = $this->_event_model()->get_one_by_ID($post_id);
1056
+		if ($post_evt instanceof EE_Event) {
1057
+			// meta revision restore
1058
+			$post_evt->restore_revision($revision_id);
1059
+			// related objs restore
1060
+			$post_evt->restore_revision($revision_id, array('Venue', 'Datetime', 'Price'));
1061
+		}
1062
+	}
1063
+
1064
+
1065
+	/**
1066
+	 * Attach the venue to the Event
1067
+	 *
1068
+	 * @param  \EE_Event $evtobj Event Object to add the venue to
1069
+	 * @param  array     $data   The request data from the form
1070
+	 * @return bool           Success or fail.
1071
+	 */
1072
+	protected function _default_venue_update(\EE_Event $evtobj, $data)
1073
+	{
1074
+		require_once(EE_MODELS . 'EEM_Venue.model.php');
1075
+		$venue_model = EE_Registry::instance()->load_model('Venue');
1076
+		$rows_affected = null;
1077
+		$venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1078
+		// very important.  If we don't have a venue name...
1079
+		// then we'll get out because not necessary to create empty venue
1080
+		if (empty($data['venue_title'])) {
1081
+			return false;
1082
+		}
1083
+		$venue_array = array(
1084
+			'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1085
+			'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1086
+			'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1087
+			'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1088
+			'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1089
+				: null,
1090
+			'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1091
+			'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1092
+			'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1093
+			'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1094
+			'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1095
+			'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1096
+			'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1097
+			'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1098
+			'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1099
+			'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1100
+			'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1101
+			'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1102
+			'status'              => 'publish',
1103
+		);
1104
+		// if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1105
+		if (! empty($venue_id)) {
1106
+			$update_where = array($venue_model->primary_key_name() => $venue_id);
1107
+			$rows_affected = $venue_model->update($venue_array, array($update_where));
1108
+			// we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
1109
+			$evtobj->_add_relation_to($venue_id, 'Venue');
1110
+			return $rows_affected > 0 ? true : false;
1111
+		} else {
1112
+			// we insert the venue
1113
+			$venue_id = $venue_model->insert($venue_array);
1114
+			$evtobj->_add_relation_to($venue_id, 'Venue');
1115
+			return ! empty($venue_id) ? true : false;
1116
+		}
1117
+		// when we have the ancestor come in it's already been handled by the revision save.
1118
+	}
1119
+
1120
+
1121
+	/**
1122
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
1123
+	 *
1124
+	 * @param  EE_Event $evtobj The Event object we're attaching data to
1125
+	 * @param  array    $data   The request data from the form
1126
+	 * @return array
1127
+	 */
1128
+	protected function _default_tickets_update(EE_Event $evtobj, $data)
1129
+	{
1130
+		$success = true;
1131
+		$saved_dtt = null;
1132
+		$saved_tickets = array();
1133
+		$incoming_date_formats = array('Y-m-d', 'h:i a');
1134
+		foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1135
+			// trim all values to ensure any excess whitespace is removed.
1136
+			$dtt = array_map('trim', $dtt);
1137
+			$dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1138
+				: $dtt['DTT_EVT_start'];
1139
+			$datetime_values = array(
1140
+				'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1141
+				'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1142
+				'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1143
+				'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1144
+				'DTT_order'     => $row,
1145
+			);
1146
+			// if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1147
+			if (! empty($dtt['DTT_ID'])) {
1148
+				$DTM = EE_Registry::instance()
1149
+								  ->load_model('Datetime', array($evtobj->get_timezone()))
1150
+								  ->get_one_by_ID($dtt['DTT_ID']);
1151
+				$DTM->set_date_format($incoming_date_formats[0]);
1152
+				$DTM->set_time_format($incoming_date_formats[1]);
1153
+				foreach ($datetime_values as $field => $value) {
1154
+					$DTM->set($field, $value);
1155
+				}
1156
+				// make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1157
+				$saved_dtts[ $DTM->ID() ] = $DTM;
1158
+			} else {
1159
+				$DTM = EE_Registry::instance()->load_class(
1160
+					'Datetime',
1161
+					array($datetime_values, $evtobj->get_timezone(), $incoming_date_formats),
1162
+					false,
1163
+					false
1164
+				);
1165
+				foreach ($datetime_values as $field => $value) {
1166
+					$DTM->set($field, $value);
1167
+				}
1168
+			}
1169
+			$DTM->save();
1170
+			$DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1171
+			// load DTT helper
1172
+			// before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1173
+			if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1174
+				$DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1175
+				$DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1176
+				$DTT->save();
1177
+			}
1178
+			// now we got to make sure we add the new DTT_ID to the $saved_dtts array  because it is possible there was a new one created for the autosave.
1179
+			$saved_dtt = $DTT;
1180
+			$success = ! $success ? $success : $DTT;
1181
+			// if ANY of these updates fail then we want the appropriate global error message.
1182
+			// //todo this is actually sucky we need a better error message but this is what it is for now.
1183
+		}
1184
+		// no dtts get deleted so we don't do any of that logic here.
1185
+		// update tickets next
1186
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
1187
+		foreach ($data['edit_tickets'] as $row => $tkt) {
1188
+			$incoming_date_formats = array('Y-m-d', 'h:i a');
1189
+			$update_prices = false;
1190
+			$ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1191
+				? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1192
+			// trim inputs to ensure any excess whitespace is removed.
1193
+			$tkt = array_map('trim', $tkt);
1194
+			if (empty($tkt['TKT_start_date'])) {
1195
+				// let's use now in the set timezone.
1196
+				$now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1197
+				$tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1198
+			}
1199
+			if (empty($tkt['TKT_end_date'])) {
1200
+				// use the start date of the first datetime
1201
+				$dtt = $evtobj->first_datetime();
1202
+				$tkt['TKT_end_date'] = $dtt->start_date_and_time(
1203
+					$incoming_date_formats[0],
1204
+					$incoming_date_formats[1]
1205
+				);
1206
+			}
1207
+			$TKT_values = array(
1208
+				'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1209
+				'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1210
+				'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1211
+				'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1212
+				'TKT_start_date'  => $tkt['TKT_start_date'],
1213
+				'TKT_end_date'    => $tkt['TKT_end_date'],
1214
+				'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1215
+				'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1216
+				'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1217
+				'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1218
+				'TKT_row'         => $row,
1219
+				'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1220
+				'TKT_price'       => $ticket_price,
1221
+			);
1222
+			// if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, which means in turn that the prices will become new prices as well.
1223
+			if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1224
+				$TKT_values['TKT_ID'] = 0;
1225
+				$TKT_values['TKT_is_default'] = 0;
1226
+				$TKT_values['TKT_price'] = $ticket_price;
1227
+				$update_prices = true;
1228
+			}
1229
+			// if we have a TKT_ID then we need to get that existing TKT_obj and update it
1230
+			// we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1231
+			// keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1232
+			if (! empty($tkt['TKT_ID'])) {
1233
+				$TKT = EE_Registry::instance()
1234
+								  ->load_model('Ticket', array($evtobj->get_timezone()))
1235
+								  ->get_one_by_ID($tkt['TKT_ID']);
1236
+				if ($TKT instanceof EE_Ticket) {
1237
+					$ticket_sold = $TKT->count_related(
1238
+						'Registration',
1239
+						array(
1240
+							array(
1241
+								'STS_ID' => array(
1242
+									'NOT IN',
1243
+									array(EEM_Registration::status_id_incomplete),
1244
+								),
1245
+							),
1246
+						)
1247
+					) > 0 ? true : false;
1248
+					// let's just check the total price for the existing ticket and determine if it matches the new total price.  if they are different then we create a new ticket (if tkts sold) if they aren't different then we go ahead and modify existing ticket.
1249
+					$create_new_TKT = $ticket_sold && $ticket_price != $TKT->get('TKT_price')
1250
+									  && ! $TKT->get('TKT_deleted');
1251
+					$TKT->set_date_format($incoming_date_formats[0]);
1252
+					$TKT->set_time_format($incoming_date_formats[1]);
1253
+					// set new values
1254
+					foreach ($TKT_values as $field => $value) {
1255
+						if ($field == 'TKT_qty') {
1256
+							$TKT->set_qty($value);
1257
+						} else {
1258
+							$TKT->set($field, $value);
1259
+						}
1260
+					}
1261
+					// if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1262
+					if ($create_new_TKT) {
1263
+						// archive the old ticket first
1264
+						$TKT->set('TKT_deleted', 1);
1265
+						$TKT->save();
1266
+						// make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1267
+						$saved_tickets[ $TKT->ID() ] = $TKT;
1268
+						// create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1269
+						$TKT = clone $TKT;
1270
+						$TKT->set('TKT_ID', 0);
1271
+						$TKT->set('TKT_deleted', 0);
1272
+						$TKT->set('TKT_price', $ticket_price);
1273
+						$TKT->set('TKT_sold', 0);
1274
+						// now we need to make sure that $new prices are created as well and attached to new ticket.
1275
+						$update_prices = true;
1276
+					}
1277
+					// make sure price is set if it hasn't been already
1278
+					$TKT->set('TKT_price', $ticket_price);
1279
+				}
1280
+			} else {
1281
+				// no TKT_id so a new TKT
1282
+				$TKT_values['TKT_price'] = $ticket_price;
1283
+				$TKT = EE_Registry::instance()->load_class('Ticket', array($TKT_values), false, false);
1284
+				if ($TKT instanceof EE_Ticket) {
1285
+					// need to reset values to properly account for the date formats
1286
+					$TKT->set_date_format($incoming_date_formats[0]);
1287
+					$TKT->set_time_format($incoming_date_formats[1]);
1288
+					$TKT->set_timezone($evtobj->get_timezone());
1289
+					// set new values
1290
+					foreach ($TKT_values as $field => $value) {
1291
+						if ($field == 'TKT_qty') {
1292
+							$TKT->set_qty($value);
1293
+						} else {
1294
+							$TKT->set($field, $value);
1295
+						}
1296
+					}
1297
+					$update_prices = true;
1298
+				}
1299
+			}
1300
+			// cap ticket qty by datetime reg limits
1301
+			$TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1302
+			// update ticket.
1303
+			$TKT->save();
1304
+			// before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1305
+			if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1306
+				$TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1307
+				$TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1308
+				$TKT->save();
1309
+			}
1310
+			// initially let's add the ticket to the dtt
1311
+			$saved_dtt->_add_relation_to($TKT, 'Ticket');
1312
+			$saved_tickets[ $TKT->ID() ] = $TKT;
1313
+			// add prices to ticket
1314
+			$this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1315
+		}
1316
+		// however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1317
+		$old_tickets = isset($old_tickets[0]) && $old_tickets[0] == '' ? array() : $old_tickets;
1318
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1319
+		foreach ($tickets_removed as $id) {
1320
+			$id = absint($id);
1321
+			// get the ticket for this id
1322
+			$tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1323
+			// need to get all the related datetimes on this ticket and remove from every single one of them (remember this process can ONLY kick off if there are NO tkts_sold)
1324
+			$dtts = $tkt_to_remove->get_many_related('Datetime');
1325
+			foreach ($dtts as $dtt) {
1326
+				$tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1327
+			}
1328
+			// need to do the same for prices (except these prices can also be deleted because again, tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1329
+			$tkt_to_remove->delete_related_permanently('Price');
1330
+			// finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1331
+			$tkt_to_remove->delete_permanently();
1332
+		}
1333
+		return array($saved_dtt, $saved_tickets);
1334
+	}
1335
+
1336
+
1337
+	/**
1338
+	 * This attaches a list of given prices to a ticket.
1339
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1340
+	 * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1341
+	 * price info and prices are automatically "archived" via the ticket.
1342
+	 *
1343
+	 * @access  private
1344
+	 * @param array     $prices     Array of prices from the form.
1345
+	 * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1346
+	 * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1347
+	 * @return  void
1348
+	 */
1349
+	private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1350
+	{
1351
+		foreach ($prices as $row => $prc) {
1352
+			$PRC_values = array(
1353
+				'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1354
+				'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1355
+				'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1356
+				'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1357
+				'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1358
+				'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1359
+				'PRC_order'      => $row,
1360
+			);
1361
+			if ($new_prices || empty($PRC_values['PRC_ID'])) {
1362
+				$PRC_values['PRC_ID'] = 0;
1363
+				$PRC = EE_Registry::instance()->load_class('Price', array($PRC_values), false, false);
1364
+			} else {
1365
+				$PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1366
+				// update this price with new values
1367
+				foreach ($PRC_values as $field => $newprc) {
1368
+					$PRC->set($field, $newprc);
1369
+				}
1370
+				$PRC->save();
1371
+			}
1372
+			$ticket->_add_relation_to($PRC, 'Price');
1373
+		}
1374
+	}
1375
+
1376
+
1377
+	/**
1378
+	 * Add in our autosave ajax handlers
1379
+	 *
1380
+	 */
1381
+	protected function _ee_autosave_create_new()
1382
+	{
1383
+	}
1384
+
1385
+
1386
+	/**
1387
+	 * More autosave handlers.
1388
+	 */
1389
+	protected function _ee_autosave_edit()
1390
+	{
1391
+		return; // TEMPORARILY EXITING CAUSE THIS IS A TODO
1392
+	}
1393
+
1394
+
1395
+	/**
1396
+	 *    _generate_publish_box_extra_content
1397
+	 */
1398
+	private function _generate_publish_box_extra_content()
1399
+	{
1400
+		// load formatter helper
1401
+		// args for getting related registrations
1402
+		$approved_query_args = array(
1403
+			array(
1404
+				'REG_deleted' => 0,
1405
+				'STS_ID'      => EEM_Registration::status_id_approved,
1406
+			),
1407
+		);
1408
+		$not_approved_query_args = array(
1409
+			array(
1410
+				'REG_deleted' => 0,
1411
+				'STS_ID'      => EEM_Registration::status_id_not_approved,
1412
+			),
1413
+		);
1414
+		$pending_payment_query_args = array(
1415
+			array(
1416
+				'REG_deleted' => 0,
1417
+				'STS_ID'      => EEM_Registration::status_id_pending_payment,
1418
+			),
1419
+		);
1420
+		// publish box
1421
+		$publish_box_extra_args = array(
1422
+			'view_approved_reg_url'        => add_query_arg(
1423
+				array(
1424
+					'action'      => 'default',
1425
+					'event_id'    => $this->_cpt_model_obj->ID(),
1426
+					'_reg_status' => EEM_Registration::status_id_approved,
1427
+				),
1428
+				REG_ADMIN_URL
1429
+			),
1430
+			'view_not_approved_reg_url'    => add_query_arg(
1431
+				array(
1432
+					'action'      => 'default',
1433
+					'event_id'    => $this->_cpt_model_obj->ID(),
1434
+					'_reg_status' => EEM_Registration::status_id_not_approved,
1435
+				),
1436
+				REG_ADMIN_URL
1437
+			),
1438
+			'view_pending_payment_reg_url' => add_query_arg(
1439
+				array(
1440
+					'action'      => 'default',
1441
+					'event_id'    => $this->_cpt_model_obj->ID(),
1442
+					'_reg_status' => EEM_Registration::status_id_pending_payment,
1443
+				),
1444
+				REG_ADMIN_URL
1445
+			),
1446
+			'approved_regs'                => $this->_cpt_model_obj->count_related(
1447
+				'Registration',
1448
+				$approved_query_args
1449
+			),
1450
+			'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1451
+				'Registration',
1452
+				$not_approved_query_args
1453
+			),
1454
+			'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1455
+				'Registration',
1456
+				$pending_payment_query_args
1457
+			),
1458
+			'misc_pub_section_class'       => apply_filters(
1459
+				'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1460
+				'misc-pub-section'
1461
+			),
1462
+		);
1463
+		ob_start();
1464
+		do_action(
1465
+			'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1466
+			$this->_cpt_model_obj
1467
+		);
1468
+		$publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1469
+		// load template
1470
+		EEH_Template::display_template(
1471
+			EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1472
+			$publish_box_extra_args
1473
+		);
1474
+	}
1475
+
1476
+
1477
+	/**
1478
+	 * @return EE_Event
1479
+	 */
1480
+	public function get_event_object()
1481
+	{
1482
+		return $this->_cpt_model_obj;
1483
+	}
1484
+
1485
+
1486
+
1487
+
1488
+	/** METABOXES * */
1489
+	/**
1490
+	 * _register_event_editor_meta_boxes
1491
+	 * add all metaboxes related to the event_editor
1492
+	 *
1493
+	 * @return void
1494
+	 */
1495
+	protected function _register_event_editor_meta_boxes()
1496
+	{
1497
+		$this->verify_cpt_object();
1498
+		add_meta_box(
1499
+			'espresso_event_editor_tickets',
1500
+			esc_html__('Event Datetime & Ticket', 'event_espresso'),
1501
+			array($this, 'ticket_metabox'),
1502
+			$this->page_slug,
1503
+			'normal',
1504
+			'high'
1505
+		);
1506
+		add_meta_box(
1507
+			'espresso_event_editor_event_options',
1508
+			esc_html__('Event Registration Options', 'event_espresso'),
1509
+			array($this, 'registration_options_meta_box'),
1510
+			$this->page_slug,
1511
+			'side',
1512
+			'default'
1513
+		);
1514
+		// NOTE: if you're looking for other metaboxes in here,
1515
+		// where a metabox has a related management page in the admin
1516
+		// you will find it setup in the related management page's "_Hooks" file.
1517
+		// i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1518
+	}
1519
+
1520
+
1521
+	/**
1522
+	 * @throws DomainException
1523
+	 * @throws EE_Error
1524
+	 */
1525
+	public function ticket_metabox()
1526
+	{
1527
+		$existing_datetime_ids = $existing_ticket_ids = array();
1528
+		// defaults for template args
1529
+		$template_args = array(
1530
+			'existing_datetime_ids'    => '',
1531
+			'event_datetime_help_link' => '',
1532
+			'ticket_options_help_link' => '',
1533
+			'time'                     => null,
1534
+			'ticket_rows'              => '',
1535
+			'existing_ticket_ids'      => '',
1536
+			'total_ticket_rows'        => 1,
1537
+			'ticket_js_structure'      => '',
1538
+			'trash_icon'               => 'ee-lock-icon',
1539
+			'disabled'                 => '',
1540
+		);
1541
+		$event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1542
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1543
+		/**
1544
+		 * 1. Start with retrieving Datetimes
1545
+		 * 2. Fore each datetime get related tickets
1546
+		 * 3. For each ticket get related prices
1547
+		 */
1548
+		$times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1549
+		/** @type EE_Datetime $first_datetime */
1550
+		$first_datetime = reset($times);
1551
+		// do we get related tickets?
1552
+		if ($first_datetime instanceof EE_Datetime
1553
+			&& $first_datetime->ID() !== 0
1554
+		) {
1555
+			$existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1556
+			$template_args['time'] = $first_datetime;
1557
+			$related_tickets = $first_datetime->tickets(
1558
+				array(
1559
+					array('OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0)),
1560
+					'default_where_conditions' => 'none',
1561
+				)
1562
+			);
1563
+			if (! empty($related_tickets)) {
1564
+				$template_args['total_ticket_rows'] = count($related_tickets);
1565
+				$row = 0;
1566
+				foreach ($related_tickets as $ticket) {
1567
+					$existing_ticket_ids[] = $ticket->get('TKT_ID');
1568
+					$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1569
+					$row++;
1570
+				}
1571
+			} else {
1572
+				$template_args['total_ticket_rows'] = 1;
1573
+				/** @type EE_Ticket $ticket */
1574
+				$ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1575
+				$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1576
+			}
1577
+		} else {
1578
+			$template_args['time'] = $times[0];
1579
+			/** @type EE_Ticket $ticket */
1580
+			$ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1581
+			$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1582
+			// NOTE: we're just sending the first default row
1583
+			// (decaf can't manage default tickets so this should be sufficient);
1584
+		}
1585
+		$template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1586
+			'event_editor_event_datetimes_help_tab'
1587
+		);
1588
+		$template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1589
+		$template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1590
+		$template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1591
+		$template_args['ticket_js_structure'] = $this->_get_ticket_row(
1592
+			EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1593
+			true
1594
+		);
1595
+		$template = apply_filters(
1596
+			'FHEE__Events_Admin_Page__ticket_metabox__template',
1597
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1598
+		);
1599
+		EEH_Template::display_template($template, $template_args);
1600
+	}
1601
+
1602
+
1603
+	/**
1604
+	 * Setup an individual ticket form for the decaf event editor page
1605
+	 *
1606
+	 * @access private
1607
+	 * @param  EE_Ticket $ticket   the ticket object
1608
+	 * @param  boolean   $skeleton whether we're generating a skeleton for js manipulation
1609
+	 * @param int        $row
1610
+	 * @return string generated html for the ticket row.
1611
+	 */
1612
+	private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1613
+	{
1614
+		$template_args = array(
1615
+			'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1616
+			'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1617
+				: '',
1618
+			'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1619
+			'TKT_ID'              => $ticket->get('TKT_ID'),
1620
+			'TKT_name'            => $ticket->get('TKT_name'),
1621
+			'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1622
+			'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1623
+			'TKT_is_default'      => $ticket->get('TKT_is_default'),
1624
+			'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1625
+			'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1626
+			'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1627
+			'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1628
+									 && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1629
+				? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1630
+			'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1631
+				: ' disabled=disabled',
1632
+		);
1633
+		$price = $ticket->ID() !== 0
1634
+			? $ticket->get_first_related('Price', array('default_where_conditions' => 'none'))
1635
+			: EE_Registry::instance()->load_model('Price')->create_default_object();
1636
+		$price_args = array(
1637
+			'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1638
+			'PRC_amount'            => $price->get('PRC_amount'),
1639
+			'PRT_ID'                => $price->get('PRT_ID'),
1640
+			'PRC_ID'                => $price->get('PRC_ID'),
1641
+			'PRC_is_default'        => $price->get('PRC_is_default'),
1642
+		);
1643
+		// make sure we have default start and end dates if skeleton
1644
+		// handle rows that should NOT be empty
1645
+		if (empty($template_args['TKT_start_date'])) {
1646
+			// if empty then the start date will be now.
1647
+			$template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1648
+		}
1649
+		if (empty($template_args['TKT_end_date'])) {
1650
+			// get the earliest datetime (if present);
1651
+			$earliest_dtt = $this->_cpt_model_obj->ID() > 0
1652
+				? $this->_cpt_model_obj->get_first_related(
1653
+					'Datetime',
1654
+					array('order_by' => array('DTT_EVT_start' => 'ASC'))
1655
+				)
1656
+				: null;
1657
+			if (! empty($earliest_dtt)) {
1658
+				$template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1659
+			} else {
1660
+				$template_args['TKT_end_date'] = date(
1661
+					'Y-m-d h:i a',
1662
+					mktime(0, 0, 0, date("m"), date("d") + 7, date("Y"))
1663
+				);
1664
+			}
1665
+		}
1666
+		$template_args = array_merge($template_args, $price_args);
1667
+		$template = apply_filters(
1668
+			'FHEE__Events_Admin_Page__get_ticket_row__template',
1669
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1670
+			$ticket
1671
+		);
1672
+		return EEH_Template::display_template($template, $template_args, true);
1673
+	}
1674
+
1675
+
1676
+	/**
1677
+	 * @throws DomainException
1678
+	 */
1679
+	public function registration_options_meta_box()
1680
+	{
1681
+		$yes_no_values = array(
1682
+			array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
1683
+			array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
1684
+		);
1685
+		$default_reg_status_values = EEM_Registration::reg_status_array(
1686
+			array(
1687
+				EEM_Registration::status_id_cancelled,
1688
+				EEM_Registration::status_id_declined,
1689
+				EEM_Registration::status_id_incomplete,
1690
+			),
1691
+			true
1692
+		);
1693
+		// $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1694
+		$template_args['_event'] = $this->_cpt_model_obj;
1695
+		$template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1696
+		$template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1697
+		$template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1698
+			'default_reg_status',
1699
+			$default_reg_status_values,
1700
+			$this->_cpt_model_obj->default_registration_status()
1701
+		);
1702
+		$template_args['display_description'] = EEH_Form_Fields::select_input(
1703
+			'display_desc',
1704
+			$yes_no_values,
1705
+			$this->_cpt_model_obj->display_description()
1706
+		);
1707
+		$template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1708
+			'display_ticket_selector',
1709
+			$yes_no_values,
1710
+			$this->_cpt_model_obj->display_ticket_selector(),
1711
+			'',
1712
+			'',
1713
+			false
1714
+		);
1715
+		$template_args['additional_registration_options'] = apply_filters(
1716
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1717
+			'',
1718
+			$template_args,
1719
+			$yes_no_values,
1720
+			$default_reg_status_values
1721
+		);
1722
+		EEH_Template::display_template(
1723
+			EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1724
+			$template_args
1725
+		);
1726
+	}
1727
+
1728
+
1729
+	/**
1730
+	 * _get_events()
1731
+	 * This method simply returns all the events (for the given _view and paging)
1732
+	 *
1733
+	 * @access public
1734
+	 * @param int  $per_page     count of items per page (20 default);
1735
+	 * @param int  $current_page what is the current page being viewed.
1736
+	 * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1737
+	 *                           If FALSE then we return an array of event objects
1738
+	 *                           that match the given _view and paging parameters.
1739
+	 * @return array an array of event objects.
1740
+	 */
1741
+	public function get_events($per_page = 10, $current_page = 1, $count = false)
1742
+	{
1743
+		$EEME = $this->_event_model();
1744
+		$offset = ($current_page - 1) * $per_page;
1745
+		$limit = $count ? null : $offset . ',' . $per_page;
1746
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1747
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC";
1748
+		if (isset($this->_req_data['month_range'])) {
1749
+			$pieces = explode(' ', $this->_req_data['month_range'], 3);
1750
+			// simulate the FIRST day of the month, that fixes issues for months like February
1751
+			// where PHP doesn't know what to assume for date.
1752
+			// @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1753
+			$month_r = ! empty($pieces[0]) ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1754
+			$year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1755
+		}
1756
+		$where = array();
1757
+		$status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1758
+		// determine what post_status our condition will have for the query.
1759
+		switch ($status) {
1760
+			case 'month':
1761
+			case 'today':
1762
+			case null:
1763
+			case 'all':
1764
+				break;
1765
+			case 'draft':
1766
+				$where['status'] = array('IN', array('draft', 'auto-draft'));
1767
+				break;
1768
+			default:
1769
+				$where['status'] = $status;
1770
+		}
1771
+		// categories?
1772
+		$category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1773
+			? $this->_req_data['EVT_CAT'] : null;
1774
+		if (! empty($category)) {
1775
+			$where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1776
+			$where['Term_Taxonomy.term_id'] = $category;
1777
+		}
1778
+		// date where conditions
1779
+		$start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1780
+		if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') {
1781
+			$DateTime = new DateTime(
1782
+				$year_r . '-' . $month_r . '-01 00:00:00',
1783
+				new DateTimeZone('UTC')
1784
+			);
1785
+			$start = $DateTime->getTimestamp();
1786
+			// set the datetime to be the end of the month
1787
+			$DateTime->setDate(
1788
+				$year_r,
1789
+				$month_r,
1790
+				$DateTime->format('t')
1791
+			)->setTime(23, 59, 59);
1792
+			$end = $DateTime->getTimestamp();
1793
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1794
+		} elseif (isset($this->_req_data['status']) && $this->_req_data['status'] == 'today') {
1795
+			$DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1796
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1797
+			$end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1798
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1799
+		} elseif (isset($this->_req_data['status']) && $this->_req_data['status'] == 'month') {
1800
+			$now = date('Y-m-01');
1801
+			$DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1802
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1803
+			$end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1804
+							->setTime(23, 59, 59)
1805
+							->format(implode(' ', $start_formats));
1806
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1807
+		}
1808
+		if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1809
+			$where['EVT_wp_user'] = get_current_user_id();
1810
+		} else {
1811
+			if (! isset($where['status'])) {
1812
+				if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1813
+					$where['OR'] = array(
1814
+						'status*restrict_private' => array('!=', 'private'),
1815
+						'AND'                     => array(
1816
+							'status*inclusive' => array('=', 'private'),
1817
+							'EVT_wp_user'      => get_current_user_id(),
1818
+						),
1819
+					);
1820
+				}
1821
+			}
1822
+		}
1823
+		if (isset($this->_req_data['EVT_wp_user'])) {
1824
+			if ($this->_req_data['EVT_wp_user'] != get_current_user_id()
1825
+				&& EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1826
+			) {
1827
+				$where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1828
+			}
1829
+		}
1830
+		// search query handling
1831
+		if (isset($this->_req_data['s'])) {
1832
+			$search_string = '%' . $this->_req_data['s'] . '%';
1833
+			$where['OR'] = array(
1834
+				'EVT_name'       => array('LIKE', $search_string),
1835
+				'EVT_desc'       => array('LIKE', $search_string),
1836
+				'EVT_short_desc' => array('LIKE', $search_string),
1837
+			);
1838
+		}
1839
+		// filter events by venue.
1840
+		if (isset($this->_req_data['venue']) && ! empty($this->_req_data['venue'])) {
1841
+			$where['Venue.VNU_ID'] = absint($this->_req_data['venue']);
1842
+		}
1843
+		$where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
1844
+		$query_params = apply_filters(
1845
+			'FHEE__Events_Admin_Page__get_events__query_params',
1846
+			array(
1847
+				$where,
1848
+				'limit'    => $limit,
1849
+				'order_by' => $orderby,
1850
+				'order'    => $order,
1851
+				'group_by' => 'EVT_ID',
1852
+			),
1853
+			$this->_req_data
1854
+		);
1855
+
1856
+		// let's first check if we have special requests coming in.
1857
+		if (isset($this->_req_data['active_status'])) {
1858
+			switch ($this->_req_data['active_status']) {
1859
+				case 'upcoming':
1860
+					return $EEME->get_upcoming_events($query_params, $count);
1861
+					break;
1862
+				case 'expired':
1863
+					return $EEME->get_expired_events($query_params, $count);
1864
+					break;
1865
+				case 'active':
1866
+					return $EEME->get_active_events($query_params, $count);
1867
+					break;
1868
+				case 'inactive':
1869
+					return $EEME->get_inactive_events($query_params, $count);
1870
+					break;
1871
+			}
1872
+		}
1873
+
1874
+		$events = $count ? $EEME->count(array($where), 'EVT_ID', true) : $EEME->get_all($query_params);
1875
+		return $events;
1876
+	}
1877
+
1878
+
1879
+	/**
1880
+	 * handling for WordPress CPT actions (trash, restore, delete)
1881
+	 *
1882
+	 * @param string $post_id
1883
+	 */
1884
+	public function trash_cpt_item($post_id)
1885
+	{
1886
+		$this->_req_data['EVT_ID'] = $post_id;
1887
+		$this->_trash_or_restore_event('trash', false);
1888
+	}
1889
+
1890
+
1891
+	/**
1892
+	 * @param string $post_id
1893
+	 */
1894
+	public function restore_cpt_item($post_id)
1895
+	{
1896
+		$this->_req_data['EVT_ID'] = $post_id;
1897
+		$this->_trash_or_restore_event('draft', false);
1898
+	}
1899
+
1900
+
1901
+	/**
1902
+	 * @param string $post_id
1903
+	 */
1904
+	public function delete_cpt_item($post_id)
1905
+	{
1906
+		$this->_req_data['EVT_ID'] = $post_id;
1907
+		$this->_delete_event(false);
1908
+	}
1909
+
1910
+
1911
+	/**
1912
+	 * _trash_or_restore_event
1913
+	 *
1914
+	 * @access protected
1915
+	 * @param  string $event_status
1916
+	 * @param bool    $redirect_after
1917
+	 */
1918
+	protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
1919
+	{
1920
+		// determine the event id and set to array.
1921
+		$EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
1922
+		// loop thru events
1923
+		if ($EVT_ID) {
1924
+			// clean status
1925
+			$event_status = sanitize_key($event_status);
1926
+			// grab status
1927
+			if (! empty($event_status)) {
1928
+				$success = $this->_change_event_status($EVT_ID, $event_status);
1929
+			} else {
1930
+				$success = false;
1931
+				$msg = esc_html__(
1932
+					'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
1933
+					'event_espresso'
1934
+				);
1935
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1936
+			}
1937
+		} else {
1938
+			$success = false;
1939
+			$msg = esc_html__(
1940
+				'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
1941
+				'event_espresso'
1942
+			);
1943
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1944
+		}
1945
+		$action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1946
+		if ($redirect_after) {
1947
+			$this->_redirect_after_action($success, 'Event', $action, array('action' => 'default'));
1948
+		}
1949
+	}
1950
+
1951
+
1952
+	/**
1953
+	 * _trash_or_restore_events
1954
+	 *
1955
+	 * @access protected
1956
+	 * @param  string $event_status
1957
+	 * @return void
1958
+	 */
1959
+	protected function _trash_or_restore_events($event_status = 'trash')
1960
+	{
1961
+		// clean status
1962
+		$event_status = sanitize_key($event_status);
1963
+		// grab status
1964
+		if (! empty($event_status)) {
1965
+			$success = true;
1966
+			// determine the event id and set to array.
1967
+			$EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
1968
+			// loop thru events
1969
+			foreach ($EVT_IDs as $EVT_ID) {
1970
+				if ($EVT_ID = absint($EVT_ID)) {
1971
+					$results = $this->_change_event_status($EVT_ID, $event_status);
1972
+					$success = $results !== false ? $success : false;
1973
+				} else {
1974
+					$msg = sprintf(
1975
+						esc_html__(
1976
+							'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
1977
+							'event_espresso'
1978
+						),
1979
+						$EVT_ID
1980
+					);
1981
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1982
+					$success = false;
1983
+				}
1984
+			}
1985
+		} else {
1986
+			$success = false;
1987
+			$msg = esc_html__(
1988
+				'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
1989
+				'event_espresso'
1990
+			);
1991
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1992
+		}
1993
+		// in order to force a pluralized result message we need to send back a success status greater than 1
1994
+		$success = $success ? 2 : false;
1995
+		$action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1996
+		$this->_redirect_after_action($success, 'Events', $action, array('action' => 'default'));
1997
+	}
1998
+
1999
+
2000
+	/**
2001
+	 * _trash_or_restore_events
2002
+	 *
2003
+	 * @access  private
2004
+	 * @param  int    $EVT_ID
2005
+	 * @param  string $event_status
2006
+	 * @return bool
2007
+	 */
2008
+	private function _change_event_status($EVT_ID = 0, $event_status = '')
2009
+	{
2010
+		// grab event id
2011
+		if (! $EVT_ID) {
2012
+			$msg = esc_html__(
2013
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2014
+				'event_espresso'
2015
+			);
2016
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2017
+			return false;
2018
+		}
2019
+		$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2020
+		// clean status
2021
+		$event_status = sanitize_key($event_status);
2022
+		// grab status
2023
+		if (empty($event_status)) {
2024
+			$msg = esc_html__(
2025
+				'An error occurred. No Event Status or an invalid Event Status was received.',
2026
+				'event_espresso'
2027
+			);
2028
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2029
+			return false;
2030
+		}
2031
+		// was event trashed or restored ?
2032
+		switch ($event_status) {
2033
+			case 'draft':
2034
+				$action = 'restored from the trash';
2035
+				$hook = 'AHEE_event_restored_from_trash';
2036
+				break;
2037
+			case 'trash':
2038
+				$action = 'moved to the trash';
2039
+				$hook = 'AHEE_event_moved_to_trash';
2040
+				break;
2041
+			default:
2042
+				$action = 'updated';
2043
+				$hook = false;
2044
+		}
2045
+		// use class to change status
2046
+		$this->_cpt_model_obj->set_status($event_status);
2047
+		$success = $this->_cpt_model_obj->save();
2048
+		if ($success === false) {
2049
+			$msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2050
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2051
+			return false;
2052
+		}
2053
+		if ($hook) {
2054
+			do_action($hook);
2055
+		}
2056
+		return true;
2057
+	}
2058
+
2059
+
2060
+	/**
2061
+	 * _delete_event
2062
+	 *
2063
+	 * @access protected
2064
+	 * @param bool $redirect_after
2065
+	 */
2066
+	protected function _delete_event($redirect_after = true)
2067
+	{
2068
+		// determine the event id and set to array.
2069
+		$EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : null;
2070
+		$EVT_ID = isset($this->_req_data['post']) ? absint($this->_req_data['post']) : $EVT_ID;
2071
+		// loop thru events
2072
+		if ($EVT_ID) {
2073
+			$success = $this->_permanently_delete_event($EVT_ID);
2074
+			// get list of events with no prices
2075
+			$espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2076
+			// remove this event from the list of events with no prices
2077
+			if (isset($espresso_no_ticket_prices[ $EVT_ID ])) {
2078
+				unset($espresso_no_ticket_prices[ $EVT_ID ]);
2079
+			}
2080
+			update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2081
+		} else {
2082
+			$success = false;
2083
+			$msg = esc_html__(
2084
+				'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2085
+				'event_espresso'
2086
+			);
2087
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2088
+		}
2089
+		if ($redirect_after) {
2090
+			$this->_redirect_after_action(
2091
+				$success,
2092
+				'Event',
2093
+				'deleted',
2094
+				array('action' => 'default', 'status' => 'trash')
2095
+			);
2096
+		}
2097
+	}
2098
+
2099
+
2100
+	/**
2101
+	 * _delete_events
2102
+	 *
2103
+	 * @access protected
2104
+	 * @return void
2105
+	 */
2106
+	protected function _delete_events()
2107
+	{
2108
+		$success = true;
2109
+		// get list of events with no prices
2110
+		$espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2111
+		// determine the event id and set to array.
2112
+		$EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
2113
+		// loop thru events
2114
+		foreach ($EVT_IDs as $EVT_ID) {
2115
+			$EVT_ID = absint($EVT_ID);
2116
+			if ($EVT_ID) {
2117
+				$results = $this->_permanently_delete_event($EVT_ID);
2118
+				$success = $results !== false ? $success : false;
2119
+				// remove this event from the list of events with no prices
2120
+				unset($espresso_no_ticket_prices[ $EVT_ID ]);
2121
+			} else {
2122
+				$success = false;
2123
+				$msg = esc_html__(
2124
+					'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2125
+					'event_espresso'
2126
+				);
2127
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2128
+			}
2129
+		}
2130
+		update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2131
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2132
+		$success = $success ? 2 : false;
2133
+		$this->_redirect_after_action($success, 'Events', 'deleted', array('action' => 'default'));
2134
+	}
2135
+
2136
+
2137
+	/**
2138
+	 * _permanently_delete_event
2139
+	 *
2140
+	 * @access  private
2141
+	 * @param  int $EVT_ID
2142
+	 * @return bool
2143
+	 */
2144
+	private function _permanently_delete_event($EVT_ID = 0)
2145
+	{
2146
+		// grab event id
2147
+		if (! $EVT_ID) {
2148
+			$msg = esc_html__(
2149
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2150
+				'event_espresso'
2151
+			);
2152
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2153
+			return false;
2154
+		}
2155
+		if (! $this->_cpt_model_obj instanceof EE_Event
2156
+			|| $this->_cpt_model_obj->ID() !== $EVT_ID
2157
+		) {
2158
+			$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2159
+		}
2160
+		if (! $this->_cpt_model_obj instanceof EE_Event) {
2161
+			return false;
2162
+		}
2163
+		// need to delete related tickets and prices first.
2164
+		$datetimes = $this->_cpt_model_obj->get_many_related('Datetime');
2165
+		foreach ($datetimes as $datetime) {
2166
+			$this->_cpt_model_obj->_remove_relation_to($datetime, 'Datetime');
2167
+			$tickets = $datetime->get_many_related('Ticket');
2168
+			foreach ($tickets as $ticket) {
2169
+				$ticket->_remove_relation_to($datetime, 'Datetime');
2170
+				$ticket->delete_related_permanently('Price');
2171
+				$ticket->delete_permanently();
2172
+			}
2173
+			$datetime->delete();
2174
+		}
2175
+		// what about related venues or terms?
2176
+		$venues = $this->_cpt_model_obj->get_many_related('Venue');
2177
+		foreach ($venues as $venue) {
2178
+			$this->_cpt_model_obj->_remove_relation_to($venue, 'Venue');
2179
+		}
2180
+		// any attached question groups?
2181
+		$question_groups = $this->_cpt_model_obj->get_many_related('Question_Group');
2182
+		if (! empty($question_groups)) {
2183
+			foreach ($question_groups as $question_group) {
2184
+				$this->_cpt_model_obj->_remove_relation_to($question_group, 'Question_Group');
2185
+			}
2186
+		}
2187
+		// Message Template Groups
2188
+		$this->_cpt_model_obj->_remove_relations('Message_Template_Group');
2189
+		/** @type EE_Term_Taxonomy[] $term_taxonomies */
2190
+		$term_taxonomies = $this->_cpt_model_obj->term_taxonomies();
2191
+		foreach ($term_taxonomies as $term_taxonomy) {
2192
+			$this->_cpt_model_obj->remove_relation_to_term_taxonomy($term_taxonomy);
2193
+		}
2194
+		$success = $this->_cpt_model_obj->delete_permanently();
2195
+		// did it all go as planned ?
2196
+		if ($success) {
2197
+			$msg = sprintf(esc_html__('Event ID # %d has been deleted.', 'event_espresso'), $EVT_ID);
2198
+			EE_Error::add_success($msg);
2199
+		} else {
2200
+			$msg = sprintf(
2201
+				esc_html__('An error occurred. Event ID # %d could not be deleted.', 'event_espresso'),
2202
+				$EVT_ID
2203
+			);
2204
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2205
+			return false;
2206
+		}
2207
+		do_action('AHEE__Events_Admin_Page___permanently_delete_event__after_event_deleted', $EVT_ID);
2208
+		return true;
2209
+	}
2210
+
2211
+
2212
+	/**
2213
+	 * get total number of events
2214
+	 *
2215
+	 * @access public
2216
+	 * @return int
2217
+	 */
2218
+	public function total_events()
2219
+	{
2220
+		$count = EEM_Event::instance()->count(array('caps' => 'read_admin'), 'EVT_ID', true);
2221
+		return $count;
2222
+	}
2223
+
2224
+
2225
+	/**
2226
+	 * get total number of draft events
2227
+	 *
2228
+	 * @access public
2229
+	 * @return int
2230
+	 */
2231
+	public function total_events_draft()
2232
+	{
2233
+		$where = array(
2234
+			'status' => array('IN', array('draft', 'auto-draft')),
2235
+		);
2236
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2237
+		return $count;
2238
+	}
2239
+
2240
+
2241
+	/**
2242
+	 * get total number of trashed events
2243
+	 *
2244
+	 * @access public
2245
+	 * @return int
2246
+	 */
2247
+	public function total_trashed_events()
2248
+	{
2249
+		$where = array(
2250
+			'status' => 'trash',
2251
+		);
2252
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2253
+		return $count;
2254
+	}
2255
+
2256
+
2257
+	/**
2258
+	 *    _default_event_settings
2259
+	 *    This generates the Default Settings Tab
2260
+	 *
2261
+	 * @return void
2262
+	 * @throws EE_Error
2263
+	 */
2264
+	protected function _default_event_settings()
2265
+	{
2266
+		$this->_set_add_edit_form_tags('update_default_event_settings');
2267
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
2268
+		$this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2269
+		$this->display_admin_page_with_sidebar();
2270
+	}
2271
+
2272
+
2273
+	/**
2274
+	 * Return the form for event settings.
2275
+	 *
2276
+	 * @return EE_Form_Section_Proper
2277
+	 * @throws EE_Error
2278
+	 */
2279
+	protected function _default_event_settings_form()
2280
+	{
2281
+		$registration_config = EE_Registry::instance()->CFG->registration;
2282
+		$registration_stati_for_selection = EEM_Registration::reg_status_array(
2283
+			// exclude
2284
+			array(
2285
+				EEM_Registration::status_id_cancelled,
2286
+				EEM_Registration::status_id_declined,
2287
+				EEM_Registration::status_id_incomplete,
2288
+				EEM_Registration::status_id_wait_list,
2289
+			),
2290
+			true
2291
+		);
2292
+		return new EE_Form_Section_Proper(
2293
+			array(
2294
+				'name'            => 'update_default_event_settings',
2295
+				'html_id'         => 'update_default_event_settings',
2296
+				'html_class'      => 'form-table',
2297
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2298
+				'subsections'     => apply_filters(
2299
+					'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2300
+					array(
2301
+						'default_reg_status'  => new EE_Select_Input(
2302
+							$registration_stati_for_selection,
2303
+							array(
2304
+								'default'         => isset($registration_config->default_STS_ID)
2305
+													 && array_key_exists(
2306
+														 $registration_config->default_STS_ID,
2307
+														 $registration_stati_for_selection
2308
+													 )
2309
+									? sanitize_text_field($registration_config->default_STS_ID)
2310
+									: EEM_Registration::status_id_pending_payment,
2311
+								'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2312
+													 . EEH_Template::get_help_tab_link(
2313
+														 'default_settings_status_help_tab'
2314
+													 ),
2315
+								'html_help_text'  => esc_html__(
2316
+									'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2317
+									'event_espresso'
2318
+								),
2319
+							)
2320
+						),
2321
+						'default_max_tickets' => new EE_Integer_Input(
2322
+							array(
2323
+								'default'         => isset($registration_config->default_maximum_number_of_tickets)
2324
+									? $registration_config->default_maximum_number_of_tickets
2325
+									: EEM_Event::get_default_additional_limit(),
2326
+								'html_label_text' => esc_html__(
2327
+									'Default Maximum Tickets Allowed Per Order:',
2328
+									'event_espresso'
2329
+								)
2330
+													 . EEH_Template::get_help_tab_link(
2331
+														 'default_maximum_tickets_help_tab"'
2332
+													 ),
2333
+								'html_help_text'  => esc_html__(
2334
+									'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2335
+									'event_espresso'
2336
+								),
2337
+							)
2338
+						),
2339
+					)
2340
+				),
2341
+			)
2342
+		);
2343
+	}
2344
+
2345
+
2346
+	/**
2347
+	 * _update_default_event_settings
2348
+	 *
2349
+	 * @access protected
2350
+	 * @return void
2351
+	 * @throws EE_Error
2352
+	 */
2353
+	protected function _update_default_event_settings()
2354
+	{
2355
+		$registration_config = EE_Registry::instance()->CFG->registration;
2356
+		$form = $this->_default_event_settings_form();
2357
+		if ($form->was_submitted()) {
2358
+			$form->receive_form_submission();
2359
+			if ($form->is_valid()) {
2360
+				$valid_data = $form->valid_data();
2361
+				if (isset($valid_data['default_reg_status'])) {
2362
+					$registration_config->default_STS_ID = $valid_data['default_reg_status'];
2363
+				}
2364
+				if (isset($valid_data['default_max_tickets'])) {
2365
+					$registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2366
+				}
2367
+				// update because data was valid!
2368
+				EE_Registry::instance()->CFG->update_espresso_config();
2369
+				EE_Error::overwrite_success();
2370
+				EE_Error::add_success(
2371
+					__('Default Event Settings were updated', 'event_espresso')
2372
+				);
2373
+			}
2374
+		}
2375
+		$this->_redirect_after_action(0, '', '', array('action' => 'default_event_settings'), true);
2376
+	}
2377
+
2378
+
2379
+	/*************        Templates        *************/
2380
+	protected function _template_settings()
2381
+	{
2382
+		$this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2383
+		$this->_template_args['preview_img'] = '<img src="'
2384
+											   . EVENTS_ASSETS_URL
2385
+											   . '/images/'
2386
+											   . 'caffeinated_template_features.jpg" alt="'
2387
+											   . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2388
+											   . '" />';
2389
+		$this->_template_args['preview_text'] = '<strong>'
2390
+												. esc_html__(
2391
+													'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2392
+													'event_espresso'
2393
+												) . '</strong>';
2394
+		$this->display_admin_caf_preview_page('template_settings_tab');
2395
+	}
2396
+
2397
+
2398
+	/** Event Category Stuff **/
2399
+	/**
2400
+	 * set the _category property with the category object for the loaded page.
2401
+	 *
2402
+	 * @access private
2403
+	 * @return void
2404
+	 */
2405
+	private function _set_category_object()
2406
+	{
2407
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
2408
+			return;
2409
+		} //already have the category object so get out.
2410
+		// set default category object
2411
+		$this->_set_empty_category_object();
2412
+		// only set if we've got an id
2413
+		if (! isset($this->_req_data['EVT_CAT_ID'])) {
2414
+			return;
2415
+		}
2416
+		$category_id = absint($this->_req_data['EVT_CAT_ID']);
2417
+		$term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2418
+		if (! empty($term)) {
2419
+			$this->_category->category_name = $term->name;
2420
+			$this->_category->category_identifier = $term->slug;
2421
+			$this->_category->category_desc = $term->description;
2422
+			$this->_category->id = $term->term_id;
2423
+			$this->_category->parent = $term->parent;
2424
+		}
2425
+	}
2426
+
2427
+
2428
+	/**
2429
+	 * Clears out category properties.
2430
+	 */
2431
+	private function _set_empty_category_object()
2432
+	{
2433
+		$this->_category = new stdClass();
2434
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2435
+		$this->_category->id = $this->_category->parent = 0;
2436
+	}
2437
+
2438
+
2439
+	/**
2440
+	 * @throws EE_Error
2441
+	 */
2442
+	protected function _category_list_table()
2443
+	{
2444
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2445
+		$this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2446
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2447
+			'add_category',
2448
+			'add_category',
2449
+			array(),
2450
+			'add-new-h2'
2451
+		);
2452
+		$this->display_admin_list_table_page_with_sidebar();
2453
+	}
2454
+
2455
+
2456
+	/**
2457
+	 * Output category details view.
2458
+	 */
2459
+	protected function _category_details($view)
2460
+	{
2461
+		// load formatter helper
2462
+		// load field generator helper
2463
+		$route = $view == 'edit' ? 'update_category' : 'insert_category';
2464
+		$this->_set_add_edit_form_tags($route);
2465
+		$this->_set_category_object();
2466
+		$id = ! empty($this->_category->id) ? $this->_category->id : '';
2467
+		$delete_action = 'delete_category';
2468
+		// custom redirect
2469
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(
2470
+			array('action' => 'category_list'),
2471
+			$this->_admin_base_url
2472
+		);
2473
+		$this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2474
+		// take care of contents
2475
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
2476
+		$this->display_admin_page_with_sidebar();
2477
+	}
2478
+
2479
+
2480
+	/**
2481
+	 * Output category details content.
2482
+	 */
2483
+	protected function _category_details_content()
2484
+	{
2485
+		$editor_args['category_desc'] = array(
2486
+			'type'          => 'wp_editor',
2487
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2488
+			'class'         => 'my_editor_custom',
2489
+			'wpeditor_args' => array('media_buttons' => false),
2490
+		);
2491
+		$_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2492
+		$all_terms = get_terms(
2493
+			array(EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY),
2494
+			array('hide_empty' => 0, 'exclude' => array($this->_category->id))
2495
+		);
2496
+		// setup category select for term parents.
2497
+		$category_select_values[] = array(
2498
+			'text' => esc_html__('No Parent', 'event_espresso'),
2499
+			'id'   => 0,
2500
+		);
2501
+		foreach ($all_terms as $term) {
2502
+			$category_select_values[] = array(
2503
+				'text' => $term->name,
2504
+				'id'   => $term->term_id,
2505
+			);
2506
+		}
2507
+		$category_select = EEH_Form_Fields::select_input(
2508
+			'category_parent',
2509
+			$category_select_values,
2510
+			$this->_category->parent
2511
+		);
2512
+		$template_args = array(
2513
+			'category'                 => $this->_category,
2514
+			'category_select'          => $category_select,
2515
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2516
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2517
+			'disable'                  => '',
2518
+			'disabled_message'         => false,
2519
+		);
2520
+		$template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2521
+		return EEH_Template::display_template($template, $template_args, true);
2522
+	}
2523
+
2524
+
2525
+	/**
2526
+	 * Handles deleting categories.
2527
+	 */
2528
+	protected function _delete_categories()
2529
+	{
2530
+		$cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array) $this->_req_data['EVT_CAT_ID']
2531
+			: (array) $this->_req_data['category_id'];
2532
+		foreach ($cat_ids as $cat_id) {
2533
+			$this->_delete_category($cat_id);
2534
+		}
2535
+		// doesn't matter what page we're coming from... we're going to the same place after delete.
2536
+		$query_args = array(
2537
+			'action' => 'category_list',
2538
+		);
2539
+		$this->_redirect_after_action(0, '', '', $query_args);
2540
+	}
2541
+
2542
+
2543
+	/**
2544
+	 * Handles deleting specific category.
2545
+	 *
2546
+	 * @param int $cat_id
2547
+	 */
2548
+	protected function _delete_category($cat_id)
2549
+	{
2550
+		$cat_id = absint($cat_id);
2551
+		wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2552
+	}
2553
+
2554
+
2555
+	/**
2556
+	 * Handles triggering the update or insertion of a new category.
2557
+	 *
2558
+	 * @param bool $new_category true means we're triggering the insert of a new category.
2559
+	 */
2560
+	protected function _insert_or_update_category($new_category)
2561
+	{
2562
+		$cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2563
+		$success = 0; // we already have a success message so lets not send another.
2564
+		if ($cat_id) {
2565
+			$query_args = array(
2566
+				'action'     => 'edit_category',
2567
+				'EVT_CAT_ID' => $cat_id,
2568
+			);
2569
+		} else {
2570
+			$query_args = array('action' => 'add_category');
2571
+		}
2572
+		$this->_redirect_after_action($success, '', '', $query_args, true);
2573
+	}
2574
+
2575
+
2576
+	/**
2577
+	 * Inserts or updates category
2578
+	 *
2579
+	 * @param bool $update (true indicates we're updating a category).
2580
+	 * @return bool|mixed|string
2581
+	 */
2582
+	private function _insert_category($update = false)
2583
+	{
2584
+		$cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2585
+		$category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2586
+		$category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2587
+		$category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2588
+		if (empty($category_name)) {
2589
+			$msg = esc_html__('You must add a name for the category.', 'event_espresso');
2590
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2591
+			return false;
2592
+		}
2593
+		$term_args = array(
2594
+			'name'        => $category_name,
2595
+			'description' => $category_desc,
2596
+			'parent'      => $category_parent,
2597
+		);
2598
+		// was the category_identifier input disabled?
2599
+		if (isset($this->_req_data['category_identifier'])) {
2600
+			$term_args['slug'] = $this->_req_data['category_identifier'];
2601
+		}
2602
+		$insert_ids = $update
2603
+			? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2604
+			: wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2605
+		if (! is_array($insert_ids)) {
2606
+			$msg = esc_html__(
2607
+				'An error occurred and the category has not been saved to the database.',
2608
+				'event_espresso'
2609
+			);
2610
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2611
+		} else {
2612
+			$cat_id = $insert_ids['term_id'];
2613
+			$msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2614
+			EE_Error::add_success($msg);
2615
+		}
2616
+		return $cat_id;
2617
+	}
2618
+
2619
+
2620
+	/**
2621
+	 * Gets categories or count of categories matching the arguments in the request.
2622
+	 *
2623
+	 * @param int  $per_page
2624
+	 * @param int  $current_page
2625
+	 * @param bool $count
2626
+	 * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2627
+	 */
2628
+	public function get_categories($per_page = 10, $current_page = 1, $count = false)
2629
+	{
2630
+		// testing term stuff
2631
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2632
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2633
+		$limit = ($current_page - 1) * $per_page;
2634
+		$where = array('taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2635
+		if (isset($this->_req_data['s'])) {
2636
+			$sstr = '%' . $this->_req_data['s'] . '%';
2637
+			$where['OR'] = array(
2638
+				'Term.name'   => array('LIKE', $sstr),
2639
+				'description' => array('LIKE', $sstr),
2640
+			);
2641
+		}
2642
+		$query_params = array(
2643
+			$where,
2644
+			'order_by'   => array($orderby => $order),
2645
+			'limit'      => $limit . ',' . $per_page,
2646
+			'force_join' => array('Term'),
2647
+		);
2648
+		$categories = $count
2649
+			? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2650
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
2651
+		return $categories;
2652
+	}
2653
+
2654
+	/* end category stuff */
2655
+	/**************/
2656
+
2657
+
2658
+	/**
2659
+	 * Callback for the `ee_save_timezone_setting` ajax action.
2660
+	 *
2661
+	 * @throws EE_Error
2662
+	 */
2663
+	public function save_timezonestring_setting()
2664
+	{
2665
+		$timezone_string = isset($this->_req_data['timezone_selected'])
2666
+			? $this->_req_data['timezone_selected']
2667
+			: '';
2668
+		if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2669
+			EE_Error::add_error(
2670
+				esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2671
+				__FILE__,
2672
+				__FUNCTION__,
2673
+				__LINE__
2674
+			);
2675
+			$this->_template_args['error'] = true;
2676
+			$this->_return_json();
2677
+		}
2678
+
2679
+		update_option('timezone_string', $timezone_string);
2680
+		EE_Error::add_success(
2681
+			esc_html__('Your timezone string was updated.', 'event_espresso')
2682
+		);
2683
+		$this->_template_args['success'] = true;
2684
+		$this->_return_json(true, array('action' => 'create_new'));
2685
+	}
2686 2686
 }
Please login to merge, or discard this patch.
admin_pages/messages/Messages_Admin_Page.core.php 1 patch
Indentation   +4537 added lines, -4537 removed lines patch added patch discarded remove patch
@@ -19,2638 +19,2638 @@  discard block
 block discarded – undo
19 19
 class Messages_Admin_Page extends EE_Admin_Page
20 20
 {
21 21
 
22
-    /**
23
-     * @type EE_Message_Resource_Manager $_message_resource_manager
24
-     */
25
-    protected $_message_resource_manager;
26
-
27
-    /**
28
-     * @type string $_active_message_type_name
29
-     */
30
-    protected $_active_message_type_name = '';
31
-
32
-    /**
33
-     * @type EE_messenger $_active_messenger
34
-     */
35
-    protected $_active_messenger;
36
-    protected $_activate_state;
37
-    protected $_activate_meta_box_type;
38
-    protected $_current_message_meta_box;
39
-    protected $_current_message_meta_box_object;
40
-    protected $_context_switcher;
41
-    protected $_shortcodes = array();
42
-    protected $_active_messengers = array();
43
-    protected $_active_message_types = array();
44
-
45
-    /**
46
-     * @var EE_Message_Template_Group $_message_template_group
47
-     */
48
-    protected $_message_template_group;
49
-    protected $_m_mt_settings = array();
50
-
51
-
52
-    /**
53
-     * This is set via the _set_message_template_group method and holds whatever the template pack for the group is.
54
-     * IF there is no group then it gets automatically set to the Default template pack.
55
-     *
56
-     * @since 4.5.0
57
-     *
58
-     * @var EE_Messages_Template_Pack
59
-     */
60
-    protected $_template_pack;
61
-
62
-
63
-    /**
64
-     * This is set via the _set_message_template_group method and holds whatever the template pack variation for the
65
-     * group is.  If there is no group then it automatically gets set to default.
66
-     *
67
-     * @since 4.5.0
68
-     *
69
-     * @var string
70
-     */
71
-    protected $_variation;
72
-
73
-
74
-    /**
75
-     * @param bool $routing
76
-     * @throws EE_Error
77
-     */
78
-    public function __construct($routing = true)
79
-    {
80
-        // make sure messages autoloader is running
81
-        EED_Messages::set_autoloaders();
82
-        parent::__construct($routing);
83
-    }
84
-
85
-
86
-    protected function _init_page_props()
87
-    {
88
-        $this->page_slug = EE_MSG_PG_SLUG;
89
-        $this->page_label = esc_html__('Messages Settings', 'event_espresso');
90
-        $this->_admin_base_url = EE_MSG_ADMIN_URL;
91
-        $this->_admin_base_path = EE_MSG_ADMIN;
92
-
93
-        $this->_activate_state = isset($this->_req_data['activate_state']) ? (array) $this->_req_data['activate_state']
94
-            : array();
95
-
96
-        $this->_active_messenger = isset($this->_req_data['messenger']) ? $this->_req_data['messenger'] : null;
97
-        $this->_load_message_resource_manager();
98
-    }
99
-
100
-
101
-    /**
102
-     * loads messenger objects into the $_active_messengers property (so we can access the needed methods)
103
-     *
104
-     * @throws EE_Error
105
-     * @throws InvalidDataTypeException
106
-     * @throws InvalidInterfaceException
107
-     * @throws InvalidArgumentException
108
-     * @throws ReflectionException
109
-     */
110
-    protected function _load_message_resource_manager()
111
-    {
112
-        $this->_message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
113
-    }
114
-
115
-
116
-    /**
117
-     * @deprecated 4.9.9.rc.014
118
-     * @return array
119
-     * @throws EE_Error
120
-     * @throws InvalidArgumentException
121
-     * @throws InvalidDataTypeException
122
-     * @throws InvalidInterfaceException
123
-     */
124
-    public function get_messengers_for_list_table()
125
-    {
126
-        EE_Error::doing_it_wrong(
127
-            __METHOD__,
128
-            sprintf(
129
-                esc_html__(
130
-                    'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a messenger filter dropdown which is now generated differently via %s',
131
-                    'event_espresso'
132
-                ),
133
-                'Messages_Admin_Page::get_messengers_select_input()'
134
-            ),
135
-            '4.9.9.rc.014'
136
-        );
137
-
138
-        $m_values = array();
139
-        $active_messengers = EEM_Message::instance()->get_all(array('group_by' => 'MSG_messenger'));
140
-        // setup messengers for selects
141
-        $i = 1;
142
-        foreach ($active_messengers as $active_messenger) {
143
-            if ($active_messenger instanceof EE_Message) {
144
-                $m_values[ $i ]['id'] = $active_messenger->messenger();
145
-                $m_values[ $i ]['text'] = ucwords($active_messenger->messenger_label());
146
-                $i++;
147
-            }
148
-        }
149
-
150
-        return $m_values;
151
-    }
152
-
153
-
154
-    /**
155
-     * @deprecated 4.9.9.rc.014
156
-     * @return array
157
-     * @throws EE_Error
158
-     * @throws InvalidArgumentException
159
-     * @throws InvalidDataTypeException
160
-     * @throws InvalidInterfaceException
161
-     */
162
-    public function get_message_types_for_list_table()
163
-    {
164
-        EE_Error::doing_it_wrong(
165
-            __METHOD__,
166
-            sprintf(
167
-                esc_html__(
168
-                    'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a message type filter dropdown which is now generated differently via %s',
169
-                    'event_espresso'
170
-                ),
171
-                'Messages_Admin_Page::get_message_types_select_input()'
172
-            ),
173
-            '4.9.9.rc.014'
174
-        );
175
-
176
-        $mt_values = array();
177
-        $active_messages = EEM_Message::instance()->get_all(array('group_by' => 'MSG_message_type'));
178
-        $i = 1;
179
-        foreach ($active_messages as $active_message) {
180
-            if ($active_message instanceof EE_Message) {
181
-                $mt_values[ $i ]['id'] = $active_message->message_type();
182
-                $mt_values[ $i ]['text'] = ucwords($active_message->message_type_label());
183
-                $i++;
184
-            }
185
-        }
186
-
187
-        return $mt_values;
188
-    }
189
-
190
-
191
-    /**
192
-     * @deprecated 4.9.9.rc.014
193
-     * @return array
194
-     * @throws EE_Error
195
-     * @throws InvalidArgumentException
196
-     * @throws InvalidDataTypeException
197
-     * @throws InvalidInterfaceException
198
-     */
199
-    public function get_contexts_for_message_types_for_list_table()
200
-    {
201
-        EE_Error::doing_it_wrong(
202
-            __METHOD__,
203
-            sprintf(
204
-                esc_html__(
205
-                    'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a message type context filter dropdown which is now generated differently via %s',
206
-                    'event_espresso'
207
-                ),
208
-                'Messages_Admin_Page::get_contexts_for_message_types_select_input()'
209
-            ),
210
-            '4.9.9.rc.014'
211
-        );
212
-
213
-        $contexts = array();
214
-        $active_message_contexts = EEM_Message::instance()->get_all(array('group_by' => 'MSG_context'));
215
-        foreach ($active_message_contexts as $active_message) {
216
-            if ($active_message instanceof EE_Message) {
217
-                $message_type = $active_message->message_type_object();
218
-                if ($message_type instanceof EE_message_type) {
219
-                    $message_type_contexts = $message_type->get_contexts();
220
-                    foreach ($message_type_contexts as $context => $context_details) {
221
-                        $contexts[ $context ] = $context_details['label'];
222
-                    }
223
-                }
224
-            }
225
-        }
226
-
227
-        return $contexts;
228
-    }
229
-
230
-
231
-    /**
232
-     * Generate select input with provided messenger options array.
233
-     *
234
-     * @param array $messenger_options Array of messengers indexed by messenger slug and values are the messenger
235
-     *                                 labels.
236
-     * @return string
237
-     * @throws EE_Error
238
-     */
239
-    public function get_messengers_select_input($messenger_options)
240
-    {
241
-        // if empty or just one value then just return an empty string
242
-        if (empty($messenger_options)
243
-            || ! is_array($messenger_options)
244
-            || count($messenger_options) === 1
245
-        ) {
246
-            return '';
247
-        }
248
-        // merge in default
249
-        $messenger_options = array_merge(
250
-            array('none_selected' => esc_html__('Show All Messengers', 'event_espresso')),
251
-            $messenger_options
252
-        );
253
-        $input = new EE_Select_Input(
254
-            $messenger_options,
255
-            array(
256
-                'html_name'  => 'ee_messenger_filter_by',
257
-                'html_id'    => 'ee_messenger_filter_by',
258
-                'html_class' => 'wide',
259
-                'default'    => isset($this->_req_data['ee_messenger_filter_by'])
260
-                    ? sanitize_title($this->_req_data['ee_messenger_filter_by'])
261
-                    : 'none_selected',
262
-            )
263
-        );
264
-
265
-        return $input->get_html_for_input();
266
-    }
267
-
268
-
269
-    /**
270
-     * Generate select input with provided message type options array.
271
-     *
272
-     * @param array $message_type_options Array of message types indexed by message type slug, and values are the
273
-     *                                    message type labels
274
-     * @return string
275
-     * @throws EE_Error
276
-     */
277
-    public function get_message_types_select_input($message_type_options)
278
-    {
279
-        // if empty or count of options is 1 then just return an empty string
280
-        if (empty($message_type_options)
281
-            || ! is_array($message_type_options)
282
-            || count($message_type_options) === 1
283
-        ) {
284
-            return '';
285
-        }
286
-        // merge in default
287
-        $message_type_options = array_merge(
288
-            array('none_selected' => esc_html__('Show All Message Types', 'event_espresso')),
289
-            $message_type_options
290
-        );
291
-        $input = new EE_Select_Input(
292
-            $message_type_options,
293
-            array(
294
-                'html_name'  => 'ee_message_type_filter_by',
295
-                'html_id'    => 'ee_message_type_filter_by',
296
-                'html_class' => 'wide',
297
-                'default'    => isset($this->_req_data['ee_message_type_filter_by'])
298
-                    ? sanitize_title($this->_req_data['ee_message_type_filter_by'])
299
-                    : 'none_selected',
300
-            )
301
-        );
302
-
303
-        return $input->get_html_for_input();
304
-    }
305
-
306
-
307
-    /**
308
-     * Generate select input with provide message type contexts array.
309
-     *
310
-     * @param array $context_options Array of message type contexts indexed by context slug, and values are the
311
-     *                               context label.
312
-     * @return string
313
-     * @throws EE_Error
314
-     */
315
-    public function get_contexts_for_message_types_select_input($context_options)
316
-    {
317
-        // if empty or count of options is one then just return empty string
318
-        if (empty($context_options)
319
-            || ! is_array($context_options)
320
-            || count($context_options) === 1
321
-        ) {
322
-            return '';
323
-        }
324
-        // merge in default
325
-        $context_options = array_merge(
326
-            array('none_selected' => esc_html__('Show all Contexts', 'event_espresso')),
327
-            $context_options
328
-        );
329
-        $input = new EE_Select_Input(
330
-            $context_options,
331
-            array(
332
-                'html_name'  => 'ee_context_filter_by',
333
-                'html_id'    => 'ee_context_filter_by',
334
-                'html_class' => 'wide',
335
-                'default'    => isset($this->_req_data['ee_context_filter_by'])
336
-                    ? sanitize_title($this->_req_data['ee_context_filter_by'])
337
-                    : 'none_selected',
338
-            )
339
-        );
340
-
341
-        return $input->get_html_for_input();
342
-    }
343
-
344
-
345
-    protected function _ajax_hooks()
346
-    {
347
-        add_action('wp_ajax_activate_messenger', array($this, 'activate_messenger_toggle'));
348
-        add_action('wp_ajax_activate_mt', array($this, 'activate_mt_toggle'));
349
-        add_action('wp_ajax_ee_msgs_save_settings', array($this, 'save_settings'));
350
-        add_action('wp_ajax_ee_msgs_update_mt_form', array($this, 'update_mt_form'));
351
-        add_action('wp_ajax_switch_template_pack', array($this, 'switch_template_pack'));
352
-        add_action('wp_ajax_toggle_context_template', array($this, 'toggle_context_template'));
353
-    }
354
-
355
-
356
-    protected function _define_page_props()
357
-    {
358
-        $this->_admin_page_title = $this->page_label;
359
-        $this->_labels = array(
360
-            'buttons'    => array(
361
-                'add'    => esc_html__('Add New Message Template', 'event_espresso'),
362
-                'edit'   => esc_html__('Edit Message Template', 'event_espresso'),
363
-                'delete' => esc_html__('Delete Message Template', 'event_espresso'),
364
-            ),
365
-            'publishbox' => esc_html__('Update Actions', 'event_espresso'),
366
-        );
367
-    }
368
-
369
-
370
-    /**
371
-     *        an array for storing key => value pairs of request actions and their corresponding methods
372
-     *
373
-     * @access protected
374
-     * @return void
375
-     */
376
-    protected function _set_page_routes()
377
-    {
378
-        $grp_id = ! empty($this->_req_data['GRP_ID']) && ! is_array($this->_req_data['GRP_ID'])
379
-            ? $this->_req_data['GRP_ID']
380
-            : 0;
381
-        $grp_id = empty($grp_id) && ! empty($this->_req_data['id'])
382
-            ? $this->_req_data['id']
383
-            : $grp_id;
384
-        $msg_id = ! empty($this->_req_data['MSG_ID']) && ! is_array($this->_req_data['MSG_ID'])
385
-            ? $this->_req_data['MSG_ID']
386
-            : 0;
387
-
388
-        $this->_page_routes = array(
389
-            'default'                          => array(
390
-                'func'       => '_message_queue_list_table',
391
-                'capability' => 'ee_read_global_messages',
392
-            ),
393
-            'global_mtps'                      => array(
394
-                'func'       => '_ee_default_messages_overview_list_table',
395
-                'capability' => 'ee_read_global_messages',
396
-            ),
397
-            'custom_mtps'                      => array(
398
-                'func'       => '_custom_mtps_preview',
399
-                'capability' => 'ee_read_messages',
400
-            ),
401
-            'add_new_message_template'         => array(
402
-                'func'       => '_add_message_template',
403
-                'capability' => 'ee_edit_messages',
404
-                'noheader'   => true,
405
-            ),
406
-            'edit_message_template'            => array(
407
-                'func'       => '_edit_message_template',
408
-                'capability' => 'ee_edit_message',
409
-                'obj_id'     => $grp_id,
410
-            ),
411
-            'preview_message'                  => array(
412
-                'func'               => '_preview_message',
413
-                'capability'         => 'ee_read_message',
414
-                'obj_id'             => $grp_id,
415
-                'noheader'           => true,
416
-                'headers_sent_route' => 'display_preview_message',
417
-            ),
418
-            'display_preview_message'          => array(
419
-                'func'       => '_display_preview_message',
420
-                'capability' => 'ee_read_message',
421
-                'obj_id'     => $grp_id,
422
-            ),
423
-            'insert_message_template'          => array(
424
-                'func'       => '_insert_or_update_message_template',
425
-                'capability' => 'ee_edit_messages',
426
-                'args'       => array('new_template' => true),
427
-                'noheader'   => true,
428
-            ),
429
-            'update_message_template'          => array(
430
-                'func'       => '_insert_or_update_message_template',
431
-                'capability' => 'ee_edit_message',
432
-                'obj_id'     => $grp_id,
433
-                'args'       => array('new_template' => false),
434
-                'noheader'   => true,
435
-            ),
436
-            'trash_message_template'           => array(
437
-                'func'       => '_trash_or_restore_message_template',
438
-                'capability' => 'ee_delete_message',
439
-                'obj_id'     => $grp_id,
440
-                'args'       => array('trash' => true, 'all' => true),
441
-                'noheader'   => true,
442
-            ),
443
-            'trash_message_template_context'   => array(
444
-                'func'       => '_trash_or_restore_message_template',
445
-                'capability' => 'ee_delete_message',
446
-                'obj_id'     => $grp_id,
447
-                'args'       => array('trash' => true),
448
-                'noheader'   => true,
449
-            ),
450
-            'restore_message_template'         => array(
451
-                'func'       => '_trash_or_restore_message_template',
452
-                'capability' => 'ee_delete_message',
453
-                'obj_id'     => $grp_id,
454
-                'args'       => array('trash' => false, 'all' => true),
455
-                'noheader'   => true,
456
-            ),
457
-            'restore_message_template_context' => array(
458
-                'func'       => '_trash_or_restore_message_template',
459
-                'capability' => 'ee_delete_message',
460
-                'obj_id'     => $grp_id,
461
-                'args'       => array('trash' => false),
462
-                'noheader'   => true,
463
-            ),
464
-            'delete_message_template'          => array(
465
-                'func'       => '_delete_message_template',
466
-                'capability' => 'ee_delete_message',
467
-                'obj_id'     => $grp_id,
468
-                'noheader'   => true,
469
-            ),
470
-            'reset_to_default'                 => array(
471
-                'func'       => '_reset_to_default_template',
472
-                'capability' => 'ee_edit_message',
473
-                'obj_id'     => $grp_id,
474
-                'noheader'   => true,
475
-            ),
476
-            'settings'                         => array(
477
-                'func'       => '_settings',
478
-                'capability' => 'manage_options',
479
-            ),
480
-            'update_global_settings'           => array(
481
-                'func'       => '_update_global_settings',
482
-                'capability' => 'manage_options',
483
-                'noheader'   => true,
484
-            ),
485
-            'generate_now'                     => array(
486
-                'func'       => '_generate_now',
487
-                'capability' => 'ee_send_message',
488
-                'noheader'   => true,
489
-            ),
490
-            'generate_and_send_now'            => array(
491
-                'func'       => '_generate_and_send_now',
492
-                'capability' => 'ee_send_message',
493
-                'noheader'   => true,
494
-            ),
495
-            'queue_for_resending'              => array(
496
-                'func'       => '_queue_for_resending',
497
-                'capability' => 'ee_send_message',
498
-                'noheader'   => true,
499
-            ),
500
-            'send_now'                         => array(
501
-                'func'       => '_send_now',
502
-                'capability' => 'ee_send_message',
503
-                'noheader'   => true,
504
-            ),
505
-            'delete_ee_message'                => array(
506
-                'func'       => '_delete_ee_messages',
507
-                'capability' => 'ee_delete_messages',
508
-                'noheader'   => true,
509
-            ),
510
-            'delete_ee_messages'               => array(
511
-                'func'       => '_delete_ee_messages',
512
-                'capability' => 'ee_delete_messages',
513
-                'noheader'   => true,
514
-                'obj_id'     => $msg_id,
515
-            ),
516
-        );
517
-    }
518
-
519
-
520
-    protected function _set_page_config()
521
-    {
522
-        $this->_page_config = array(
523
-            'default'                  => array(
524
-                'nav'           => array(
525
-                    'label' => esc_html__('Message Activity', 'event_espresso'),
526
-                    'order' => 10,
527
-                ),
528
-                'list_table'    => 'EE_Message_List_Table',
529
-                // 'qtips' => array( 'EE_Message_List_Table_Tips' ),
530
-                'require_nonce' => false,
531
-            ),
532
-            'global_mtps'              => array(
533
-                'nav'           => array(
534
-                    'label' => esc_html__('Default Message Templates', 'event_espresso'),
535
-                    'order' => 20,
536
-                ),
537
-                'list_table'    => 'Messages_Template_List_Table',
538
-                'help_tabs'     => array(
539
-                    'messages_overview_help_tab'                                => array(
540
-                        'title'    => esc_html__('Messages Overview', 'event_espresso'),
541
-                        'filename' => 'messages_overview',
542
-                    ),
543
-                    'messages_overview_messages_table_column_headings_help_tab' => array(
544
-                        'title'    => esc_html__('Messages Table Column Headings', 'event_espresso'),
545
-                        'filename' => 'messages_overview_table_column_headings',
546
-                    ),
547
-                    'messages_overview_messages_filters_help_tab'               => array(
548
-                        'title'    => esc_html__('Message Filters', 'event_espresso'),
549
-                        'filename' => 'messages_overview_filters',
550
-                    ),
551
-                    'messages_overview_messages_views_help_tab'                 => array(
552
-                        'title'    => esc_html__('Message Views', 'event_espresso'),
553
-                        'filename' => 'messages_overview_views',
554
-                    ),
555
-                    'message_overview_message_types_help_tab'                   => array(
556
-                        'title'    => esc_html__('Message Types', 'event_espresso'),
557
-                        'filename' => 'messages_overview_types',
558
-                    ),
559
-                    'messages_overview_messengers_help_tab'                     => array(
560
-                        'title'    => esc_html__('Messengers', 'event_espresso'),
561
-                        'filename' => 'messages_overview_messengers',
562
-                    ),
563
-                ),
564
-                'help_tour'     => array('Messages_Overview_Help_Tour'),
565
-                'require_nonce' => false,
566
-            ),
567
-            'custom_mtps'              => array(
568
-                'nav'           => array(
569
-                    'label' => esc_html__('Custom Message Templates', 'event_espresso'),
570
-                    'order' => 30,
571
-                ),
572
-                'help_tabs'     => array(),
573
-                'help_tour'     => array(),
574
-                'require_nonce' => false,
575
-            ),
576
-            'add_new_message_template' => array(
577
-                'nav'           => array(
578
-                    'label'      => esc_html__('Add New Message Templates', 'event_espresso'),
579
-                    'order'      => 5,
580
-                    'persistent' => false,
581
-                ),
582
-                'require_nonce' => false,
583
-            ),
584
-            'edit_message_template'    => array(
585
-                'labels'        => array(
586
-                    'buttons'    => array(
587
-                        'reset' => esc_html__('Reset Templates', 'event_espresso'),
588
-                    ),
589
-                    'publishbox' => esc_html__('Update Actions', 'event_espresso'),
590
-                ),
591
-                'nav'           => array(
592
-                    'label'      => esc_html__('Edit Message Templates', 'event_espresso'),
593
-                    'order'      => 5,
594
-                    'persistent' => false,
595
-                    'url'        => '',
596
-                ),
597
-                'metaboxes'     => array('_publish_post_box', '_register_edit_meta_boxes'),
598
-                'has_metaboxes' => true,
599
-                'help_tour'     => array('Message_Templates_Edit_Help_Tour'),
600
-                'help_tabs'     => array(
601
-                    'edit_message_template'            => array(
602
-                        'title'    => esc_html__('Message Template Editor', 'event_espresso'),
603
-                        'callback' => 'edit_message_template_help_tab',
604
-                    ),
605
-                    'message_templates_help_tab'       => array(
606
-                        'title'    => esc_html__('Message Templates', 'event_espresso'),
607
-                        'filename' => 'messages_templates',
608
-                    ),
609
-                    'message_template_shortcodes'      => array(
610
-                        'title'    => esc_html__('Message Shortcodes', 'event_espresso'),
611
-                        'callback' => 'message_template_shortcodes_help_tab',
612
-                    ),
613
-                    'message_preview_help_tab'         => array(
614
-                        'title'    => esc_html__('Message Preview', 'event_espresso'),
615
-                        'filename' => 'messages_preview',
616
-                    ),
617
-                    'messages_overview_other_help_tab' => array(
618
-                        'title'    => esc_html__('Messages Other', 'event_espresso'),
619
-                        'filename' => 'messages_overview_other',
620
-                    ),
621
-                ),
622
-                'require_nonce' => false,
623
-            ),
624
-            'display_preview_message'  => array(
625
-                'nav'           => array(
626
-                    'label'      => esc_html__('Message Preview', 'event_espresso'),
627
-                    'order'      => 5,
628
-                    'url'        => '',
629
-                    'persistent' => false,
630
-                ),
631
-                'help_tabs'     => array(
632
-                    'preview_message' => array(
633
-                        'title'    => esc_html__('About Previews', 'event_espresso'),
634
-                        'callback' => 'preview_message_help_tab',
635
-                    ),
636
-                ),
637
-                'require_nonce' => false,
638
-            ),
639
-            'settings'                 => array(
640
-                'nav'           => array(
641
-                    'label' => esc_html__('Settings', 'event_espresso'),
642
-                    'order' => 40,
643
-                ),
644
-                'metaboxes'     => array('_messages_settings_metaboxes'),
645
-                'help_tabs'     => array(
646
-                    'messages_settings_help_tab'               => array(
647
-                        'title'    => esc_html__('Messages Settings', 'event_espresso'),
648
-                        'filename' => 'messages_settings',
649
-                    ),
650
-                    'messages_settings_message_types_help_tab' => array(
651
-                        'title'    => esc_html__('Activating / Deactivating Message Types', 'event_espresso'),
652
-                        'filename' => 'messages_settings_message_types',
653
-                    ),
654
-                    'messages_settings_messengers_help_tab'    => array(
655
-                        'title'    => esc_html__('Activating / Deactivating Messengers', 'event_espresso'),
656
-                        'filename' => 'messages_settings_messengers',
657
-                    ),
658
-                ),
659
-                'help_tour'     => array('Messages_Settings_Help_Tour'),
660
-                'require_nonce' => false,
661
-            ),
662
-        );
663
-    }
664
-
665
-
666
-    protected function _add_screen_options()
667
-    {
668
-        // todo
669
-    }
670
-
671
-
672
-    protected function _add_screen_options_global_mtps()
673
-    {
674
-        /**
675
-         * Note: the reason for the value swap here on $this->_admin_page_title is because $this->_per_page_screen_options
676
-         * uses the $_admin_page_title property and we want different outputs in the different spots.
677
-         */
678
-        $page_title = $this->_admin_page_title;
679
-        $this->_admin_page_title = esc_html__('Global Message Templates', 'event_espresso');
680
-        $this->_per_page_screen_option();
681
-        $this->_admin_page_title = $page_title;
682
-    }
683
-
684
-
685
-    protected function _add_screen_options_default()
686
-    {
687
-        $this->_admin_page_title = esc_html__('Message Activity', 'event_espresso');
688
-        $this->_per_page_screen_option();
689
-    }
690
-
691
-
692
-    // none of the below group are currently used for Messages
693
-    protected function _add_feature_pointers()
694
-    {
695
-    }
696
-
697
-    public function admin_init()
698
-    {
699
-    }
700
-
701
-    public function admin_notices()
702
-    {
703
-    }
704
-
705
-    public function admin_footer_scripts()
706
-    {
707
-    }
708
-
709
-
710
-    public function messages_help_tab()
711
-    {
712
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_help_tab.template.php');
713
-    }
714
-
715
-
716
-    public function messengers_help_tab()
717
-    {
718
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messenger_help_tab.template.php');
719
-    }
720
-
721
-
722
-    public function message_types_help_tab()
723
-    {
724
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_type_help_tab.template.php');
725
-    }
726
-
727
-
728
-    public function messages_overview_help_tab()
729
-    {
730
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_overview_help_tab.template.php');
731
-    }
732
-
733
-
734
-    public function message_templates_help_tab()
735
-    {
736
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_templates_help_tab.template.php');
737
-    }
738
-
739
-
740
-    public function edit_message_template_help_tab()
741
-    {
742
-        $args['img1'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/editor.png' . '" alt="'
743
-                        . esc_attr__('Editor Title', 'event_espresso')
744
-                        . '" />';
745
-        $args['img2'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/switch-context.png' . '" alt="'
746
-                        . esc_attr__('Context Switcher and Preview', 'event_espresso')
747
-                        . '" />';
748
-        $args['img3'] = '<img class="left" src="' . EE_MSG_ASSETS_URL . 'images/form-fields.png' . '" alt="'
749
-                        . esc_attr__('Message Template Form Fields', 'event_espresso')
750
-                        . '" />';
751
-        $args['img4'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/shortcodes-metabox.png' . '" alt="'
752
-                        . esc_attr__('Shortcodes Metabox', 'event_espresso')
753
-                        . '" />';
754
-        $args['img5'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/publish-meta-box.png' . '" alt="'
755
-                        . esc_attr__('Publish Metabox', 'event_espresso')
756
-                        . '" />';
757
-        EEH_Template::display_template(
758
-            EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_templates_editor_help_tab.template.php',
759
-            $args
760
-        );
761
-    }
762
-
763
-
764
-    public function message_template_shortcodes_help_tab()
765
-    {
766
-        $this->_set_shortcodes();
767
-        $args['shortcodes'] = $this->_shortcodes;
768
-        EEH_Template::display_template(
769
-            EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_shortcodes_help_tab.template.php',
770
-            $args
771
-        );
772
-    }
773
-
774
-
775
-    public function preview_message_help_tab()
776
-    {
777
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_preview_help_tab.template.php');
778
-    }
779
-
780
-
781
-    public function settings_help_tab()
782
-    {
783
-        $args['img1'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-active.png'
784
-                        . '" alt="' . esc_attr__('Active Email Tab', 'event_espresso') . '" />';
785
-        $args['img2'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-inactive.png'
786
-                        . '" alt="' . esc_attr__('Inactive Email Tab', 'event_espresso') . '" />';
787
-        $args['img3'] = '<div class="switch">'
788
-                        . '<input class="ee-on-off-toggle ee-toggle-round-flat"'
789
-                        . ' type="checkbox" checked="checked">'
790
-                        . '<label for="ee-on-off-toggle-on"></label>'
791
-                        . '</div>';
792
-        $args['img4'] = '<div class="switch">'
793
-                        . '<input class="ee-on-off-toggle ee-toggle-round-flat"'
794
-                        . ' type="checkbox">'
795
-                        . '<label for="ee-on-off-toggle-on"></label>'
796
-                        . '</div>';
797
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_settings_help_tab.template.php', $args);
798
-    }
799
-
800
-
801
-    public function load_scripts_styles()
802
-    {
803
-        wp_register_style('espresso_ee_msg', EE_MSG_ASSETS_URL . 'ee_message_admin.css', EVENT_ESPRESSO_VERSION);
804
-        wp_enqueue_style('espresso_ee_msg');
805
-
806
-        wp_register_script(
807
-            'ee-messages-settings',
808
-            EE_MSG_ASSETS_URL . 'ee-messages-settings.js',
809
-            array('jquery-ui-droppable', 'ee-serialize-full-array'),
810
-            EVENT_ESPRESSO_VERSION,
811
-            true
812
-        );
813
-        wp_register_script(
814
-            'ee-msg-list-table-js',
815
-            EE_MSG_ASSETS_URL . 'ee_message_admin_list_table.js',
816
-            array('ee-dialog'),
817
-            EVENT_ESPRESSO_VERSION
818
-        );
819
-    }
820
-
821
-
822
-    public function load_scripts_styles_default()
823
-    {
824
-        wp_enqueue_script('ee-msg-list-table-js');
825
-    }
826
-
827
-
828
-    public function wp_editor_css($mce_css)
829
-    {
830
-        // if we're on the edit_message_template route
831
-        if ($this->_req_action === 'edit_message_template' && $this->_active_messenger instanceof EE_messenger) {
832
-            $message_type_name = $this->_active_message_type_name;
833
-
834
-            // we're going to REPLACE the existing mce css
835
-            // we need to get the css file location from the active messenger
836
-            $mce_css = $this->_active_messenger->get_variation(
837
-                $this->_template_pack,
838
-                $message_type_name,
839
-                true,
840
-                'wpeditor',
841
-                $this->_variation
842
-            );
843
-        }
844
-
845
-        return $mce_css;
846
-    }
847
-
848
-
849
-    public function load_scripts_styles_edit_message_template()
850
-    {
851
-
852
-        $this->_set_shortcodes();
853
-
854
-        EE_Registry::$i18n_js_strings['confirm_default_reset'] = sprintf(
855
-            esc_html__(
856
-                'Are you sure you want to reset the %s %s message templates?  Remember continuing will reset the templates for all contexts in this messenger and message type group.',
857
-                'event_espresso'
858
-            ),
859
-            $this->_message_template_group->messenger_obj()->label['singular'],
860
-            $this->_message_template_group->message_type_obj()->label['singular']
861
-        );
862
-        EE_Registry::$i18n_js_strings['confirm_switch_template_pack'] = esc_html__(
863
-            'Switching the template pack for a messages template will reset the content for the template so the new layout is loaded.  Any custom content in the existing template will be lost. Are you sure you wish to do this?',
864
-            'event_espresso'
865
-        );
866
-        EE_Registry::$i18n_js_strings['server_error'] = esc_html__(
867
-            'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
868
-            'event_espresso'
869
-        );
870
-
871
-        wp_register_script(
872
-            'ee_msgs_edit_js',
873
-            EE_MSG_ASSETS_URL . 'ee_message_editor.js',
874
-            array('jquery'),
875
-            EVENT_ESPRESSO_VERSION
876
-        );
877
-
878
-        wp_enqueue_script('ee_admin_js');
879
-        wp_enqueue_script('ee_msgs_edit_js');
880
-
881
-        // add in special css for tiny_mce
882
-        add_filter('mce_css', array($this, 'wp_editor_css'));
883
-    }
884
-
885
-
886
-    public function load_scripts_styles_display_preview_message()
887
-    {
888
-
889
-        $this->_set_message_template_group();
890
-
891
-        if (isset($this->_req_data['messenger'])) {
892
-            $this->_active_messenger = $this->_message_resource_manager->get_active_messenger(
893
-                $this->_req_data['messenger']
894
-            );
895
-        }
896
-
897
-        $message_type_name = isset($this->_req_data['message_type']) ? $this->_req_data['message_type'] : '';
898
-
899
-
900
-        wp_enqueue_style(
901
-            'espresso_preview_css',
902
-            $this->_active_messenger->get_variation(
903
-                $this->_template_pack,
904
-                $message_type_name,
905
-                true,
906
-                'preview',
907
-                $this->_variation
908
-            )
909
-        );
910
-    }
911
-
912
-
913
-    public function load_scripts_styles_settings()
914
-    {
915
-        wp_register_style(
916
-            'ee-message-settings',
917
-            EE_MSG_ASSETS_URL . 'ee_message_settings.css',
918
-            array(),
919
-            EVENT_ESPRESSO_VERSION
920
-        );
921
-        wp_enqueue_style('ee-text-links');
922
-        wp_enqueue_style('ee-message-settings');
923
-        wp_enqueue_script('ee-messages-settings');
924
-    }
925
-
926
-
927
-    /**
928
-     * set views array for List Table
929
-     */
930
-    public function _set_list_table_views_global_mtps()
931
-    {
932
-        $this->_views = array(
933
-            'in_use' => array(
934
-                'slug'  => 'in_use',
935
-                'label' => esc_html__('In Use', 'event_espresso'),
936
-                'count' => 0,
937
-            ),
938
-        );
939
-    }
940
-
941
-
942
-    /**
943
-     * Set views array for the Custom Template List Table
944
-     */
945
-    public function _set_list_table_views_custom_mtps()
946
-    {
947
-        $this->_set_list_table_views_global_mtps();
948
-        $this->_views['in_use']['bulk_action'] = array(
949
-            'trash_message_template' => esc_html__('Move to Trash', 'event_espresso'),
950
-        );
951
-    }
952
-
953
-
954
-    /**
955
-     * set views array for message queue list table
956
-     *
957
-     * @throws InvalidDataTypeException
958
-     * @throws InvalidInterfaceException
959
-     * @throws InvalidArgumentException
960
-     * @throws EE_Error
961
-     * @throws ReflectionException
962
-     */
963
-    public function _set_list_table_views_default()
964
-    {
965
-        EE_Registry::instance()->load_helper('Template');
966
-
967
-        $common_bulk_actions = EE_Registry::instance()->CAP->current_user_can(
968
-            'ee_send_message',
969
-            'message_list_table_bulk_actions'
970
-        )
971
-            ? array(
972
-                'generate_now'          => esc_html__('Generate Now', 'event_espresso'),
973
-                'generate_and_send_now' => esc_html__('Generate and Send Now', 'event_espresso'),
974
-                'queue_for_resending'   => esc_html__('Queue for Resending', 'event_espresso'),
975
-                'send_now'              => esc_html__('Send Now', 'event_espresso'),
976
-            )
977
-            : array();
978
-
979
-        $delete_bulk_action = EE_Registry::instance()->CAP->current_user_can(
980
-            'ee_delete_messages',
981
-            'message_list_table_bulk_actions'
982
-        )
983
-            ? array('delete_ee_messages' => esc_html__('Delete Messages', 'event_espresso'))
984
-            : array();
985
-
986
-
987
-        $this->_views = array(
988
-            'all' => array(
989
-                'slug'        => 'all',
990
-                'label'       => esc_html__('All', 'event_espresso'),
991
-                'count'       => 0,
992
-                'bulk_action' => array_merge($common_bulk_actions, $delete_bulk_action),
993
-            ),
994
-        );
995
-
996
-
997
-        foreach (EEM_Message::instance()->all_statuses() as $status) {
998
-            if ($status === EEM_Message::status_debug_only && ! EEM_Message::debug()) {
999
-                continue;
1000
-            }
1001
-            $status_bulk_actions = $common_bulk_actions;
1002
-            // unset bulk actions not applying to status
1003
-            if (! empty($status_bulk_actions)) {
1004
-                switch ($status) {
1005
-                    case EEM_Message::status_idle:
1006
-                    case EEM_Message::status_resend:
1007
-                        $status_bulk_actions['send_now'] = $common_bulk_actions['send_now'];
1008
-                        break;
1009
-
1010
-                    case EEM_Message::status_failed:
1011
-                    case EEM_Message::status_debug_only:
1012
-                    case EEM_Message::status_messenger_executing:
1013
-                        $status_bulk_actions = array();
1014
-                        break;
1015
-
1016
-                    case EEM_Message::status_incomplete:
1017
-                        unset($status_bulk_actions['queue_for_resending'], $status_bulk_actions['send_now']);
1018
-                        break;
1019
-
1020
-                    case EEM_Message::status_retry:
1021
-                    case EEM_Message::status_sent:
1022
-                        unset($status_bulk_actions['generate_now'], $status_bulk_actions['generate_and_send_now']);
1023
-                        break;
1024
-                }
1025
-            }
1026
-
1027
-            // skip adding messenger executing status to views because it will be included with the Failed view.
1028
-            if ($status === EEM_Message::status_messenger_executing) {
1029
-                continue;
1030
-            }
1031
-
1032
-            $this->_views[ strtolower($status) ] = array(
1033
-                'slug'        => strtolower($status),
1034
-                'label'       => EEH_Template::pretty_status($status, false, 'sentence'),
1035
-                'count'       => 0,
1036
-                'bulk_action' => array_merge($status_bulk_actions, $delete_bulk_action),
1037
-            );
1038
-        }
1039
-    }
1040
-
1041
-
1042
-    protected function _ee_default_messages_overview_list_table()
1043
-    {
1044
-        $this->_admin_page_title = esc_html__('Default Message Templates', 'event_espresso');
1045
-        $this->display_admin_list_table_page_with_no_sidebar();
1046
-    }
1047
-
1048
-
1049
-    protected function _message_queue_list_table()
1050
-    {
1051
-        $this->_search_btn_label = esc_html__('Message Activity', 'event_espresso');
1052
-        $this->_template_args['per_column'] = 6;
1053
-        $this->_template_args['after_list_table'] = $this->_display_legend($this->_message_legend_items());
1054
-        $this->_template_args['before_list_table'] = '<h3>'
1055
-                                                     . EEM_Message::instance()->get_pretty_label_for_results()
1056
-                                                     . '</h3>';
1057
-        $this->display_admin_list_table_page_with_no_sidebar();
1058
-    }
1059
-
1060
-
1061
-    protected function _message_legend_items()
1062
-    {
1063
-
1064
-        $action_css_classes = EEH_MSG_Template::get_message_action_icons();
1065
-        $action_items = array();
1066
-
1067
-        foreach ($action_css_classes as $action_item => $action_details) {
1068
-            if ($action_item === 'see_notifications_for') {
1069
-                continue;
1070
-            }
1071
-            $action_items[ $action_item ] = array(
1072
-                'class' => $action_details['css_class'],
1073
-                'desc'  => $action_details['label'],
1074
-            );
1075
-        }
1076
-
1077
-        /** @type array $status_items status legend setup */
1078
-        $status_items = array(
1079
-            'sent_status'                => array(
1080
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_sent,
1081
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_sent, false, 'sentence'),
1082
-            ),
1083
-            'idle_status'                => array(
1084
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_idle,
1085
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_idle, false, 'sentence'),
1086
-            ),
1087
-            'failed_status'              => array(
1088
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_failed,
1089
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_failed, false, 'sentence'),
1090
-            ),
1091
-            'messenger_executing_status' => array(
1092
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_messenger_executing,
1093
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_messenger_executing, false, 'sentence'),
1094
-            ),
1095
-            'resend_status'              => array(
1096
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_resend,
1097
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_resend, false, 'sentence'),
1098
-            ),
1099
-            'incomplete_status'          => array(
1100
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_incomplete,
1101
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_incomplete, false, 'sentence'),
1102
-            ),
1103
-            'retry_status'               => array(
1104
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_retry,
1105
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_retry, false, 'sentence'),
1106
-            ),
1107
-        );
1108
-        if (EEM_Message::debug()) {
1109
-            $status_items['debug_only_status'] = array(
1110
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_debug_only,
1111
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_debug_only, false, 'sentence'),
1112
-            );
1113
-        }
1114
-
1115
-        return array_merge($action_items, $status_items);
1116
-    }
1117
-
1118
-
1119
-    protected function _custom_mtps_preview()
1120
-    {
1121
-        $this->_admin_page_title = esc_html__('Custom Message Templates (Preview)', 'event_espresso');
1122
-        $this->_template_args['preview_img'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/custom_mtps_preview.png"'
1123
-                                               . ' alt="' . esc_attr__(
1124
-                                                   'Preview Custom Message Templates screenshot',
1125
-                                                   'event_espresso'
1126
-                                               ) . '" />';
1127
-        $this->_template_args['preview_text'] = '<strong>'
1128
-                                                . esc_html__(
1129
-                                                    'Custom Message Templates is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. With the Custom Message Templates feature, you are able to create custom message templates and assign them on a per-event basis.',
1130
-                                                    'event_espresso'
1131
-                                                )
1132
-                                                . '</strong>';
1133
-
1134
-        $this->display_admin_caf_preview_page('custom_message_types', false);
1135
-    }
1136
-
1137
-
1138
-    /**
1139
-     * get_message_templates
1140
-     * This gets all the message templates for listing on the overview list.
1141
-     *
1142
-     * @access public
1143
-     * @param int    $perpage the amount of templates groups to show per page
1144
-     * @param string $type    the current _view we're getting templates for
1145
-     * @param bool   $count   return count?
1146
-     * @param bool   $all     disregard any paging info (get all data);
1147
-     * @param bool   $global  whether to return just global (true) or custom templates (false)
1148
-     * @return array
1149
-     * @throws EE_Error
1150
-     * @throws InvalidArgumentException
1151
-     * @throws InvalidDataTypeException
1152
-     * @throws InvalidInterfaceException
1153
-     */
1154
-    public function get_message_templates(
1155
-        $perpage = 10,
1156
-        $type = 'in_use',
1157
-        $count = false,
1158
-        $all = false,
1159
-        $global = true
1160
-    ) {
1161
-
1162
-        $MTP = EEM_Message_Template_Group::instance();
1163
-
1164
-        $this->_req_data['orderby'] = empty($this->_req_data['orderby']) ? 'GRP_ID' : $this->_req_data['orderby'];
1165
-        $orderby = $this->_req_data['orderby'];
1166
-
1167
-        $order = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
1168
-            ? $this->_req_data['order']
1169
-            : 'ASC';
1170
-
1171
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
1172
-            ? $this->_req_data['paged']
1173
-            : 1;
1174
-        $per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
1175
-            ? $this->_req_data['perpage']
1176
-            : $perpage;
1177
-
1178
-        $offset = ($current_page - 1) * $per_page;
1179
-        $limit = $all ? null : array($offset, $per_page);
1180
-
1181
-
1182
-        // options will match what is in the _views array property
1183
-        switch ($type) {
1184
-            case 'in_use':
1185
-                $templates = $MTP->get_all_active_message_templates($orderby, $order, $limit, $count, $global, true);
1186
-                break;
1187
-            default:
1188
-                $templates = $MTP->get_all_trashed_grouped_message_templates($orderby, $order, $limit, $count, $global);
1189
-        }
1190
-
1191
-        return $templates;
1192
-    }
1193
-
1194
-
1195
-    /**
1196
-     * filters etc might need a list of installed message_types
1197
-     *
1198
-     * @return array an array of message type objects
1199
-     */
1200
-    public function get_installed_message_types()
1201
-    {
1202
-        $installed_message_types = $this->_message_resource_manager->installed_message_types();
1203
-        $installed = array();
1204
-
1205
-        foreach ($installed_message_types as $message_type) {
1206
-            $installed[ $message_type->name ] = $message_type;
1207
-        }
1208
-
1209
-        return $installed;
1210
-    }
1211
-
1212
-
1213
-    /**
1214
-     * _add_message_template
1215
-     *
1216
-     * This is used when creating a custom template. All Custom Templates start based off another template.
1217
-     *
1218
-     * @param string $message_type
1219
-     * @param string $messenger
1220
-     * @param string $GRP_ID
1221
-     *
1222
-     * @throws EE_error
1223
-     */
1224
-    protected function _add_message_template($message_type = '', $messenger = '', $GRP_ID = '')
1225
-    {
1226
-        // set values override any request data
1227
-        $message_type = ! empty($message_type) ? $message_type : '';
1228
-        $message_type = empty($message_type) && ! empty($this->_req_data['message_type'])
1229
-            ? $this->_req_data['message_type']
1230
-            : $message_type;
1231
-
1232
-        $messenger = ! empty($messenger) ? $messenger : '';
1233
-        $messenger = empty($messenger) && ! empty($this->_req_data['messenger'])
1234
-            ? $this->_req_data['messenger']
1235
-            : $messenger;
1236
-
1237
-        $GRP_ID = ! empty($GRP_ID) ? $GRP_ID : '';
1238
-        $GRP_ID = empty($GRP_ID) && ! empty($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : $GRP_ID;
1239
-
1240
-        // we need messenger and message type.  They should be coming from the event editor. If not here then return error
1241
-        if (empty($message_type) || empty($messenger)) {
1242
-            throw new EE_Error(
1243
-                esc_html__(
1244
-                    'Sorry, but we can\'t create new templates because we\'re missing the messenger or message type',
1245
-                    'event_espresso'
1246
-                )
1247
-            );
1248
-        }
1249
-
1250
-        // we need the GRP_ID for the template being used as the base for the new template
1251
-        if (empty($GRP_ID)) {
1252
-            throw new EE_Error(
1253
-                esc_html__(
1254
-                    'In order to create a custom message template the GRP_ID of the template being used as a base is needed',
1255
-                    'event_espresso'
1256
-                )
1257
-            );
1258
-        }
1259
-
1260
-        // let's just make sure the template gets generated!
1261
-
1262
-        // we need to reassign some variables for what the insert is expecting
1263
-        $this->_req_data['MTP_messenger'] = $messenger;
1264
-        $this->_req_data['MTP_message_type'] = $message_type;
1265
-        $this->_req_data['GRP_ID'] = $GRP_ID;
1266
-        $this->_insert_or_update_message_template(true);
1267
-    }
1268
-
1269
-
1270
-    /**
1271
-     * public wrapper for the _add_message_template method
1272
-     *
1273
-     * @param string $message_type     message type slug
1274
-     * @param string $messenger        messenger slug
1275
-     * @param int    $GRP_ID           GRP_ID for the related message template group this new template will be based
1276
-     *                                 off of.
1277
-     * @throws EE_error
1278
-     */
1279
-    public function add_message_template($message_type, $messenger, $GRP_ID)
1280
-    {
1281
-        $this->_add_message_template($message_type, $messenger, $GRP_ID);
1282
-    }
1283
-
1284
-
1285
-    /**
1286
-     * _edit_message_template
1287
-     *
1288
-     * @access protected
1289
-     * @return void
1290
-     * @throws InvalidIdentifierException
1291
-     * @throws DomainException
1292
-     * @throws EE_Error
1293
-     * @throws InvalidArgumentException
1294
-     * @throws ReflectionException
1295
-     * @throws InvalidDataTypeException
1296
-     * @throws InvalidInterfaceException
1297
-     */
1298
-    protected function _edit_message_template()
1299
-    {
1300
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1301
-        $template_fields = '';
1302
-        $sidebar_fields = '';
1303
-        // we filter the tinyMCE settings to remove the validation since message templates by their nature will not have
1304
-        // valid html in the templates.
1305
-        add_filter('tiny_mce_before_init', array($this, 'filter_tinymce_init'), 10, 2);
1306
-
1307
-        $GRP_ID = isset($this->_req_data['id']) && ! empty($this->_req_data['id'])
1308
-            ? absint($this->_req_data['id'])
1309
-            : false;
1310
-
1311
-        $EVT_ID = isset($this->_req_data['evt_id']) && ! empty($this->_req_data['evt_id'])
1312
-        ? absint($this->_req_data['evt_id'])
1313
-        : false;
1314
-
1315
-        $this->_set_shortcodes(); // this also sets the _message_template property.
1316
-        $message_template_group = $this->_message_template_group;
1317
-        $c_label = $message_template_group->context_label();
1318
-        $c_config = $message_template_group->contexts_config();
1319
-
1320
-        reset($c_config);
1321
-        $context = isset($this->_req_data['context']) && ! empty($this->_req_data['context'])
1322
-            ? strtolower($this->_req_data['context'])
1323
-            : key($c_config);
1324
-
1325
-
1326
-        if (empty($GRP_ID)) {
1327
-            $action = 'insert_message_template';
1328
-            $edit_message_template_form_url = add_query_arg(
1329
-                array('action' => $action, 'noheader' => true),
1330
-                EE_MSG_ADMIN_URL
1331
-            );
1332
-        } else {
1333
-            $action = 'update_message_template';
1334
-            $edit_message_template_form_url = add_query_arg(
1335
-                array('action' => $action, 'noheader' => true),
1336
-                EE_MSG_ADMIN_URL
1337
-            );
1338
-        }
1339
-
1340
-        // set active messenger for this view
1341
-        $this->_active_messenger = $this->_message_resource_manager->get_active_messenger(
1342
-            $message_template_group->messenger()
1343
-        );
1344
-        $this->_active_message_type_name = $message_template_group->message_type();
1345
-
1346
-
1347
-        // Do we have any validation errors?
1348
-        $validators = $this->_get_transient();
1349
-        $v_fields = ! empty($validators) ? array_keys($validators) : array();
1350
-
1351
-
1352
-        // we need to assemble the title from Various details
1353
-        $context_label = sprintf(
1354
-            esc_html__('(%s %s)', 'event_espresso'),
1355
-            $c_config[ $context ]['label'],
1356
-            ucwords($c_label['label'])
1357
-        );
1358
-
1359
-        $title = sprintf(
1360
-            esc_html__(' %s %s Template %s', 'event_espresso'),
1361
-            ucwords($message_template_group->messenger_obj()->label['singular']),
1362
-            ucwords($message_template_group->message_type_obj()->label['singular']),
1363
-            $context_label
1364
-        );
1365
-
1366
-        $this->_template_args['GRP_ID'] = $GRP_ID;
1367
-        $this->_template_args['message_template'] = $message_template_group;
1368
-        $this->_template_args['is_extra_fields'] = false;
1369
-
1370
-
1371
-        // let's get EEH_MSG_Template so we can get template form fields
1372
-        $template_field_structure = EEH_MSG_Template::get_fields(
1373
-            $message_template_group->messenger(),
1374
-            $message_template_group->message_type()
1375
-        );
1376
-
1377
-        if (! $template_field_structure) {
1378
-            $template_field_structure = false;
1379
-            $template_fields = esc_html__(
1380
-                'There was an error in assembling the fields for this display (you should see an error message)',
1381
-                'event_espresso'
1382
-            );
1383
-        }
1384
-
1385
-
1386
-        $message_templates = $message_template_group->context_templates();
1387
-
1388
-
1389
-        // if we have the extra key.. then we need to remove the content index from the template_field_structure as it
1390
-        // will get handled in the "extra" array.
1391
-        if (is_array($template_field_structure[ $context ]) && isset($template_field_structure[ $context ]['extra'])) {
1392
-            foreach ($template_field_structure[ $context ]['extra'] as $reference_field => $new_fields) {
1393
-                unset($template_field_structure[ $context ][ $reference_field ]);
1394
-            }
1395
-        }
1396
-
1397
-        // let's loop through the template_field_structure and actually assemble the input fields!
1398
-        if (! empty($template_field_structure)) {
1399
-            foreach ($template_field_structure[ $context ] as $template_field => $field_setup_array) {
1400
-                // if this is an 'extra' template field then we need to remove any existing fields that are keyed up in
1401
-                // the extra array and reset them.
1402
-                if ($template_field === 'extra') {
1403
-                    $this->_template_args['is_extra_fields'] = true;
1404
-                    foreach ($field_setup_array as $reference_field => $new_fields_array) {
1405
-                        $message_template = $message_templates[ $context ][ $reference_field ];
1406
-                        $content = $message_template instanceof EE_Message_Template
1407
-                            ? $message_template->get('MTP_content')
1408
-                            : '';
1409
-                        foreach ($new_fields_array as $extra_field => $extra_array) {
1410
-                            // let's verify if we need this extra field via the shortcodes parameter.
1411
-                            $continue = false;
1412
-                            if (isset($extra_array['shortcodes_required'])) {
1413
-                                foreach ((array) $extra_array['shortcodes_required'] as $shortcode) {
1414
-                                    if (! array_key_exists($shortcode, $this->_shortcodes)) {
1415
-                                        $continue = true;
1416
-                                    }
1417
-                                }
1418
-                                if ($continue) {
1419
-                                    continue;
1420
-                                }
1421
-                            }
1422
-
1423
-                            $field_id = $reference_field
1424
-                                        . '-'
1425
-                                        . $extra_field
1426
-                                        . '-content';
1427
-                            $template_form_fields[ $field_id ] = $extra_array;
1428
-                            $template_form_fields[ $field_id ]['name'] = 'MTP_template_fields['
1429
-                                                                         . $reference_field
1430
-                                                                         . '][content]['
1431
-                                                                         . $extra_field . ']';
1432
-                            $css_class = isset($extra_array['css_class'])
1433
-                                ? $extra_array['css_class']
1434
-                                : '';
1435
-
1436
-                            $template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1437
-                                                                              && in_array($extra_field, $v_fields, true)
1438
-                                                                              &&
1439
-                                                                              (
1440
-                                                                                  is_array($validators[ $extra_field ])
1441
-                                                                                  && isset($validators[ $extra_field ]['msg'])
1442
-                                                                              )
1443
-                                ? 'validate-error ' . $css_class
1444
-                                : $css_class;
1445
-
1446
-                            $template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1447
-                                                                          && isset($content[ $extra_field ])
1448
-                                ? $content[ $extra_field ]
1449
-                                : '';
1450
-
1451
-                            // do we have a validation error?  if we do then let's use that value instead
1452
-                            $template_form_fields[ $field_id ]['value'] = isset($validators[ $extra_field ])
1453
-                                ? $validators[ $extra_field ]['value']
1454
-                                : $template_form_fields[ $field_id ]['value'];
1455
-
1456
-
1457
-                            $template_form_fields[ $field_id ]['db-col'] = 'MTP_content';
1458
-
1459
-                            // shortcode selector
1460
-                            $field_name_to_use = $extra_field === 'main'
1461
-                                ? 'content'
1462
-                                : $extra_field;
1463
-                            $template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1464
-                                $field_name_to_use,
1465
-                                $field_id
1466
-                            );
1467
-
1468
-                            if (isset($extra_array['input']) && $extra_array['input'] === 'wp_editor') {
1469
-                                // we want to decode the entities
1470
-                                $template_form_fields[ $field_id ]['value'] = $template_form_fields[ $field_id ]['value'];
1471
-                            }/**/
1472
-                        }
1473
-                        $templatefield_MTP_id = $reference_field . '-MTP_ID';
1474
-                        $templatefield_templatename_id = $reference_field . '-name';
1475
-
1476
-                        $template_form_fields[ $templatefield_MTP_id ] = array(
1477
-                            'name'       => 'MTP_template_fields[' . $reference_field . '][MTP_ID]',
1478
-                            'label'      => null,
1479
-                            'input'      => 'hidden',
1480
-                            'type'       => 'int',
1481
-                            'required'   => false,
1482
-                            'validation' => false,
1483
-                            'value'      => ! empty($message_templates) ? $message_template->ID() : '',
1484
-                            'css_class'  => '',
1485
-                            'format'     => '%d',
1486
-                            'db-col'     => 'MTP_ID',
1487
-                        );
1488
-
1489
-                        $template_form_fields[ $templatefield_templatename_id ] = array(
1490
-                            'name'       => 'MTP_template_fields[' . $reference_field . '][name]',
1491
-                            'label'      => null,
1492
-                            'input'      => 'hidden',
1493
-                            'type'       => 'string',
1494
-                            'required'   => false,
1495
-                            'validation' => true,
1496
-                            'value'      => $reference_field,
1497
-                            'css_class'  => '',
1498
-                            'format'     => '%s',
1499
-                            'db-col'     => 'MTP_template_field',
1500
-                        );
1501
-                    }
1502
-                    continue; // skip the next stuff, we got the necessary fields here for this dataset.
1503
-                } else {
1504
-                    $field_id = $template_field . '-content';
1505
-                    $template_form_fields[ $field_id ] = $field_setup_array;
1506
-                    $template_form_fields[ $field_id ]['name'] = 'MTP_template_fields[' . $template_field . '][content]';
1507
-                    $message_template = isset($message_templates[ $context ][ $template_field ])
1508
-                        ? $message_templates[ $context ][ $template_field ]
1509
-                        : null;
1510
-                    $template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1511
-                                                                  && is_array($message_templates[ $context ])
1512
-                                                                  && $message_template instanceof EE_Message_Template
1513
-                        ? $message_template->get('MTP_content')
1514
-                        : '';
1515
-
1516
-                    // do we have a validator error for this field?  if we do then we'll use that value instead
1517
-                    $template_form_fields[ $field_id ]['value'] = isset($validators[ $template_field ])
1518
-                        ? $validators[ $template_field ]['value']
1519
-                        : $template_form_fields[ $field_id ]['value'];
1520
-
1521
-
1522
-                    $template_form_fields[ $field_id ]['db-col'] = 'MTP_content';
1523
-                    $css_class = isset($field_setup_array['css_class'])
1524
-                        ? $field_setup_array['css_class']
1525
-                        : '';
1526
-                    $template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1527
-                                                                      && in_array($template_field, $v_fields, true)
1528
-                                                                      && isset($validators[ $template_field ]['msg'])
1529
-                        ? 'validate-error ' . $css_class
1530
-                        : $css_class;
1531
-
1532
-                    // shortcode selector
1533
-                    $template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1534
-                        $template_field,
1535
-                        $field_id
1536
-                    );
1537
-                }
1538
-
1539
-                // k took care of content field(s) now let's take care of others.
1540
-
1541
-                $templatefield_MTP_id = $template_field . '-MTP_ID';
1542
-                $templatefield_field_templatename_id = $template_field . '-name';
1543
-
1544
-                // foreach template field there are actually two form fields created
1545
-                $template_form_fields[ $templatefield_MTP_id ] = array(
1546
-                    'name'       => 'MTP_template_fields[' . $template_field . '][MTP_ID]',
1547
-                    'label'      => null,
1548
-                    'input'      => 'hidden',
1549
-                    'type'       => 'int',
1550
-                    'required'   => false,
1551
-                    'validation' => true,
1552
-                    'value'      => $message_template instanceof EE_Message_Template ? $message_template->ID() : '',
1553
-                    'css_class'  => '',
1554
-                    'format'     => '%d',
1555
-                    'db-col'     => 'MTP_ID',
1556
-                );
1557
-
1558
-                $template_form_fields[ $templatefield_field_templatename_id ] = array(
1559
-                    'name'       => 'MTP_template_fields[' . $template_field . '][name]',
1560
-                    'label'      => null,
1561
-                    'input'      => 'hidden',
1562
-                    'type'       => 'string',
1563
-                    'required'   => false,
1564
-                    'validation' => true,
1565
-                    'value'      => $template_field,
1566
-                    'css_class'  => '',
1567
-                    'format'     => '%s',
1568
-                    'db-col'     => 'MTP_template_field',
1569
-                );
1570
-            }
1571
-
1572
-            // add other fields
1573
-            $template_form_fields['ee-msg-current-context'] = array(
1574
-                'name'       => 'MTP_context',
1575
-                'label'      => null,
1576
-                'input'      => 'hidden',
1577
-                'type'       => 'string',
1578
-                'required'   => false,
1579
-                'validation' => true,
1580
-                'value'      => $context,
1581
-                'css_class'  => '',
1582
-                'format'     => '%s',
1583
-                'db-col'     => 'MTP_context',
1584
-            );
1585
-
1586
-            $template_form_fields['ee-msg-grp-id'] = array(
1587
-                'name'       => 'GRP_ID',
1588
-                'label'      => null,
1589
-                'input'      => 'hidden',
1590
-                'type'       => 'int',
1591
-                'required'   => false,
1592
-                'validation' => true,
1593
-                'value'      => $GRP_ID,
1594
-                'css_class'  => '',
1595
-                'format'     => '%d',
1596
-                'db-col'     => 'GRP_ID',
1597
-            );
1598
-
1599
-            $template_form_fields['ee-msg-messenger'] = array(
1600
-                'name'       => 'MTP_messenger',
1601
-                'label'      => null,
1602
-                'input'      => 'hidden',
1603
-                'type'       => 'string',
1604
-                'required'   => false,
1605
-                'validation' => true,
1606
-                'value'      => $message_template_group->messenger(),
1607
-                'css_class'  => '',
1608
-                'format'     => '%s',
1609
-                'db-col'     => 'MTP_messenger',
1610
-            );
1611
-
1612
-            $template_form_fields['ee-msg-message-type'] = array(
1613
-                'name'       => 'MTP_message_type',
1614
-                'label'      => null,
1615
-                'input'      => 'hidden',
1616
-                'type'       => 'string',
1617
-                'required'   => false,
1618
-                'validation' => true,
1619
-                'value'      => $message_template_group->message_type(),
1620
-                'css_class'  => '',
1621
-                'format'     => '%s',
1622
-                'db-col'     => 'MTP_message_type',
1623
-            );
1624
-
1625
-            $sidebar_form_fields['ee-msg-is-global'] = array(
1626
-                'name'       => 'MTP_is_global',
1627
-                'label'      => esc_html__('Global Template', 'event_espresso'),
1628
-                'input'      => 'hidden',
1629
-                'type'       => 'int',
1630
-                'required'   => false,
1631
-                'validation' => true,
1632
-                'value'      => $message_template_group->get('MTP_is_global'),
1633
-                'css_class'  => '',
1634
-                'format'     => '%d',
1635
-                'db-col'     => 'MTP_is_global',
1636
-            );
1637
-
1638
-            $sidebar_form_fields['ee-msg-is-override'] = array(
1639
-                'name'       => 'MTP_is_override',
1640
-                'label'      => esc_html__('Override all custom', 'event_espresso'),
1641
-                'input'      => $message_template_group->is_global() ? 'checkbox' : 'hidden',
1642
-                'type'       => 'int',
1643
-                'required'   => false,
1644
-                'validation' => true,
1645
-                'value'      => $message_template_group->get('MTP_is_override'),
1646
-                'css_class'  => '',
1647
-                'format'     => '%d',
1648
-                'db-col'     => 'MTP_is_override',
1649
-            );
1650
-
1651
-            $sidebar_form_fields['ee-msg-is-active'] = array(
1652
-                'name'       => 'MTP_is_active',
1653
-                'label'      => esc_html__('Active Template', 'event_espresso'),
1654
-                'input'      => 'hidden',
1655
-                'type'       => 'int',
1656
-                'required'   => false,
1657
-                'validation' => true,
1658
-                'value'      => $message_template_group->is_active(),
1659
-                'css_class'  => '',
1660
-                'format'     => '%d',
1661
-                'db-col'     => 'MTP_is_active',
1662
-            );
1663
-
1664
-            $sidebar_form_fields['ee-msg-deleted'] = array(
1665
-                'name'       => 'MTP_deleted',
1666
-                'label'      => null,
1667
-                'input'      => 'hidden',
1668
-                'type'       => 'int',
1669
-                'required'   => false,
1670
-                'validation' => true,
1671
-                'value'      => $message_template_group->get('MTP_deleted'),
1672
-                'css_class'  => '',
1673
-                'format'     => '%d',
1674
-                'db-col'     => 'MTP_deleted',
1675
-            );
1676
-            $sidebar_form_fields['ee-msg-author'] = array(
1677
-                'name'       => 'MTP_user_id',
1678
-                'label'      => esc_html__('Author', 'event_espresso'),
1679
-                'input'      => 'hidden',
1680
-                'type'       => 'int',
1681
-                'required'   => false,
1682
-                'validation' => false,
1683
-                'value'      => $message_template_group->user(),
1684
-                'format'     => '%d',
1685
-                'db-col'     => 'MTP_user_id',
1686
-            );
1687
-
1688
-            $sidebar_form_fields['ee-msg-route'] = array(
1689
-                'name'  => 'action',
1690
-                'input' => 'hidden',
1691
-                'type'  => 'string',
1692
-                'value' => $action,
1693
-            );
1694
-
1695
-            $sidebar_form_fields['ee-msg-id'] = array(
1696
-                'name'  => 'id',
1697
-                'input' => 'hidden',
1698
-                'type'  => 'int',
1699
-                'value' => $GRP_ID,
1700
-            );
1701
-            $sidebar_form_fields['ee-msg-evt-nonce'] = array(
1702
-                'name'  => $action . '_nonce',
1703
-                'input' => 'hidden',
1704
-                'type'  => 'string',
1705
-                'value' => wp_create_nonce($action . '_nonce'),
1706
-            );
1707
-
1708
-            if (isset($this->_req_data['template_switch']) && $this->_req_data['template_switch']) {
1709
-                $sidebar_form_fields['ee-msg-template-switch'] = array(
1710
-                    'name'  => 'template_switch',
1711
-                    'input' => 'hidden',
1712
-                    'type'  => 'int',
1713
-                    'value' => 1,
1714
-                );
1715
-            }
1716
-
1717
-
1718
-            $template_fields = $this->_generate_admin_form_fields($template_form_fields);
1719
-            $sidebar_fields = $this->_generate_admin_form_fields($sidebar_form_fields);
1720
-        } //end if ( !empty($template_field_structure) )
1721
-
1722
-        // set extra content for publish box
1723
-        $this->_template_args['publish_box_extra_content'] = $sidebar_fields;
1724
-        $this->_set_publish_post_box_vars(
1725
-            'id',
1726
-            $GRP_ID,
1727
-            false,
1728
-            add_query_arg(
1729
-                array('action' => 'global_mtps'),
1730
-                $this->_admin_base_url
1731
-            )
1732
-        );
1733
-
1734
-        // add preview button
1735
-        $preview_url = parent::add_query_args_and_nonce(
1736
-            array(
1737
-                'message_type' => $message_template_group->message_type(),
1738
-                'messenger'    => $message_template_group->messenger(),
1739
-                'context'      => $context,
1740
-                'GRP_ID'       => $GRP_ID,
1741
-                'evt_id'       => $EVT_ID,
1742
-                'action'       => 'preview_message',
1743
-            ),
1744
-            $this->_admin_base_url
1745
-        );
1746
-        $preview_button = '<a href="' . $preview_url . '" class="button-secondary messages-preview-button">'
1747
-                          . esc_html__('Preview', 'event_espresso')
1748
-                          . '</a>';
1749
-
1750
-
1751
-        // setup context switcher
1752
-        $context_switcher_args = array(
1753
-            'page'    => 'espresso_messages',
1754
-            'action'  => 'edit_message_template',
1755
-            'id'      => $GRP_ID,
1756
-            'evt_id'  => $EVT_ID,
1757
-            'context' => $context,
1758
-            'extra'   => $preview_button,
1759
-        );
1760
-        $this->_set_context_switcher($message_template_group, $context_switcher_args);
1761
-
1762
-
1763
-        // main box
1764
-        $this->_template_args['template_fields'] = $template_fields;
1765
-        $this->_template_args['sidebar_box_id'] = 'details';
1766
-        $this->_template_args['action'] = $action;
1767
-        $this->_template_args['context'] = $context;
1768
-        $this->_template_args['edit_message_template_form_url'] = $edit_message_template_form_url;
1769
-        $this->_template_args['learn_more_about_message_templates_link'] =
1770
-            $this->_learn_more_about_message_templates_link();
1771
-
1772
-
1773
-        $this->_template_args['before_admin_page_content'] = $this->add_context_switcher();
1774
-        $this->_template_args['before_admin_page_content'] .= $this->add_active_context_element(
1775
-            $message_template_group,
1776
-            $context,
1777
-            $context_label
1778
-        );
1779
-        $this->_template_args['before_admin_page_content'] .= $this->_add_form_element_before();
1780
-        $this->_template_args['after_admin_page_content'] = $this->_add_form_element_after();
1781
-
1782
-        $this->_template_path = $this->_template_args['GRP_ID']
1783
-            ? EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_edit_meta_box.template.php'
1784
-            : EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_add_meta_box.template.php';
1785
-
1786
-        // send along EE_Message_Template_Group object for further template use.
1787
-        $this->_template_args['MTP'] = $message_template_group;
1788
-
1789
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
1790
-            $this->_template_path,
1791
-            $this->_template_args,
1792
-            true
1793
-        );
1794
-
1795
-
1796
-        // finally, let's set the admin_page title
1797
-        $this->_admin_page_title = sprintf(__('Editing %s', 'event_espresso'), $title);
1798
-
1799
-
1800
-        // we need to take care of setting the shortcodes property for use elsewhere.
1801
-        $this->_set_shortcodes();
1802
-
1803
-
1804
-        // final template wrapper
1805
-        $this->display_admin_page_with_sidebar();
1806
-    }
1807
-
1808
-
1809
-    public function filter_tinymce_init($mceInit, $editor_id)
1810
-    {
1811
-        return $mceInit;
1812
-    }
1813
-
1814
-
1815
-    public function add_context_switcher()
1816
-    {
1817
-        return $this->_context_switcher;
1818
-    }
1819
-
1820
-
1821
-    /**
1822
-     * Adds the activation/deactivation toggle for the message template context.
1823
-     *
1824
-     * @param EE_Message_Template_Group $message_template_group
1825
-     * @param string                    $context
1826
-     * @param string                    $context_label
1827
-     * @return string
1828
-     * @throws DomainException
1829
-     * @throws EE_Error
1830
-     * @throws InvalidIdentifierException
1831
-     */
1832
-    protected function add_active_context_element(
1833
-        EE_Message_Template_Group $message_template_group,
1834
-        $context,
1835
-        $context_label
1836
-    ) {
1837
-        $template_args = array(
1838
-            'context'                   => $context,
1839
-            'nonce'                     => wp_create_nonce('activate_' . $context . '_toggle_nonce'),
1840
-            'is_active'                 => $message_template_group->is_context_active($context),
1841
-            'on_off_action'             => $message_template_group->is_context_active($context)
1842
-                ? 'context-off'
1843
-                : 'context-on',
1844
-            'context_label'             => str_replace(array('(', ')'), '', $context_label),
1845
-            'message_template_group_id' => $message_template_group->ID(),
1846
-        );
1847
-        return EEH_Template::display_template(
1848
-            EE_MSG_TEMPLATE_PATH . 'ee_msg_editor_active_context_element.template.php',
1849
-            $template_args,
1850
-            true
1851
-        );
1852
-    }
1853
-
1854
-
1855
-    /**
1856
-     * Ajax callback for `toggle_context_template` ajax action.
1857
-     * Handles toggling the message context on or off.
1858
-     *
1859
-     * @throws EE_Error
1860
-     * @throws InvalidArgumentException
1861
-     * @throws InvalidDataTypeException
1862
-     * @throws InvalidIdentifierException
1863
-     * @throws InvalidInterfaceException
1864
-     */
1865
-    public function toggle_context_template()
1866
-    {
1867
-        $success = true;
1868
-        // check for required data
1869
-        if (! isset(
1870
-            $this->_req_data['message_template_group_id'],
1871
-            $this->_req_data['context'],
1872
-            $this->_req_data['status']
1873
-        )) {
1874
-            EE_Error::add_error(
1875
-                esc_html__('Required data for doing this action is not available.', 'event_espresso'),
1876
-                __FILE__,
1877
-                __FUNCTION__,
1878
-                __LINE__
1879
-            );
1880
-            $success = false;
1881
-        }
1882
-
1883
-        $nonce = isset($this->_req_data['toggle_context_nonce'])
1884
-            ? sanitize_text_field($this->_req_data['toggle_context_nonce'])
1885
-            : '';
1886
-        $nonce_ref = 'activate_' . $this->_req_data['context'] . '_toggle_nonce';
1887
-        $this->_verify_nonce($nonce, $nonce_ref);
1888
-        $status = $this->_req_data['status'];
1889
-        if ($status !== 'off' && $status !== 'on') {
1890
-            EE_Error::add_error(
1891
-                sprintf(
1892
-                    esc_html__('The given status (%s) is not valid. Must be "off" or "on"', 'event_espresso'),
1893
-                    $this->_req_data['status']
1894
-                ),
1895
-                __FILE__,
1896
-                __FUNCTION__,
1897
-                __LINE__
1898
-            );
1899
-            $success = false;
1900
-        }
1901
-        $message_template_group = EEM_Message_Template_Group::instance()->get_one_by_ID(
1902
-            $this->_req_data['message_template_group_id']
1903
-        );
1904
-        if (! $message_template_group instanceof EE_Message_Template_Group) {
1905
-            EE_Error::add_error(
1906
-                sprintf(
1907
-                    esc_html__(
1908
-                        'Unable to change the active state because the given id "%1$d" does not match a valid "%2$s"',
1909
-                        'event_espresso'
1910
-                    ),
1911
-                    $this->_req_data['message_template_group_id'],
1912
-                    'EE_Message_Template_Group'
1913
-                ),
1914
-                __FILE__,
1915
-                __FUNCTION__,
1916
-                __LINE__
1917
-            );
1918
-            $success = false;
1919
-        }
1920
-        if ($success) {
1921
-            $success = $status === 'off'
1922
-                ? $message_template_group->deactivate_context($this->_req_data['context'])
1923
-                : $message_template_group->activate_context($this->_req_data['context']);
1924
-        }
1925
-        $this->_template_args['success'] = $success;
1926
-        $this->_return_json();
1927
-    }
1928
-
1929
-
1930
-    public function _add_form_element_before()
1931
-    {
1932
-        return '<form method="post" action="'
1933
-               . $this->_template_args["edit_message_template_form_url"]
1934
-               . '" id="ee-msg-edit-frm">';
1935
-    }
1936
-
1937
-    public function _add_form_element_after()
1938
-    {
1939
-        return '</form>';
1940
-    }
1941
-
1942
-
1943
-    /**
1944
-     * This executes switching the template pack for a message template.
1945
-     *
1946
-     * @since 4.5.0
1947
-     * @throws EE_Error
1948
-     * @throws InvalidDataTypeException
1949
-     * @throws InvalidInterfaceException
1950
-     * @throws InvalidArgumentException
1951
-     * @throws ReflectionException
1952
-     */
1953
-    public function switch_template_pack()
1954
-    {
1955
-        $GRP_ID = ! empty($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : 0;
1956
-        $template_pack = ! empty($this->_req_data['template_pack']) ? $this->_req_data['template_pack'] : '';
1957
-
1958
-        // verify we have needed values.
1959
-        if (empty($GRP_ID) || empty($template_pack)) {
1960
-            $this->_template_args['error'] = true;
1961
-            EE_Error::add_error(
1962
-                esc_html__('The required date for switching templates is not available.', 'event_espresso'),
1963
-                __FILE__,
1964
-                __FUNCTION__,
1965
-                __LINE__
1966
-            );
1967
-        } else {
1968
-            // get template, set the new template_pack and then reset to default
1969
-            /** @type EE_Message_Template_Group $message_template_group */
1970
-            $message_template_group = EEM_Message_Template_Group::instance()->get_one_by_ID($GRP_ID);
1971
-
1972
-            $message_template_group->set_template_pack_name($template_pack);
1973
-            $this->_req_data['msgr'] = $message_template_group->messenger();
1974
-            $this->_req_data['mt'] = $message_template_group->message_type();
1975
-
1976
-            $query_args = $this->_reset_to_default_template();
1977
-
1978
-            if (empty($query_args['id'])) {
1979
-                EE_Error::add_error(
1980
-                    esc_html__(
1981
-                        'Something went wrong with switching the template pack. Please try again or contact EE support',
1982
-                        'event_espresso'
1983
-                    ),
1984
-                    __FILE__,
1985
-                    __FUNCTION__,
1986
-                    __LINE__
1987
-                );
1988
-                $this->_template_args['error'] = true;
1989
-            } else {
1990
-                $template_label = $message_template_group->get_template_pack()->label;
1991
-                $template_pack_labels = $message_template_group->messenger_obj()->get_supports_labels();
1992
-                EE_Error::add_success(
1993
-                    sprintf(
1994
-                        esc_html__(
1995
-                            'This message template has been successfully switched to use the %1$s %2$s.  Please wait while the page reloads with your new template.',
1996
-                            'event_espresso'
1997
-                        ),
1998
-                        $template_label,
1999
-                        $template_pack_labels->template_pack
2000
-                    )
2001
-                );
2002
-                // generate the redirect url for js.
2003
-                $url = self::add_query_args_and_nonce(
2004
-                    $query_args,
2005
-                    $this->_admin_base_url
2006
-                );
2007
-                $this->_template_args['data']['redirect_url'] = $url;
2008
-                $this->_template_args['success'] = true;
2009
-            }
2010
-
2011
-            $this->_return_json();
2012
-        }
2013
-    }
2014
-
2015
-
2016
-    /**
2017
-     * This handles resetting the template for the given messenger/message_type so that users can start from scratch if
2018
-     * they want.
2019
-     *
2020
-     * @access protected
2021
-     * @return array|null
2022
-     * @throws EE_Error
2023
-     * @throws InvalidArgumentException
2024
-     * @throws InvalidDataTypeException
2025
-     * @throws InvalidInterfaceException
2026
-     */
2027
-    protected function _reset_to_default_template()
2028
-    {
2029
-
2030
-        $templates = array();
2031
-        $GRP_ID = ! empty($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : 0;
2032
-        // we need to make sure we've got the info we need.
2033
-        if (! isset($this->_req_data['msgr'], $this->_req_data['mt'], $this->_req_data['GRP_ID'])) {
2034
-            EE_Error::add_error(
2035
-                esc_html__(
2036
-                    'In order to reset the template to its default we require the messenger, message type, and message template GRP_ID to know what is being reset.  At least one of these is missing.',
2037
-                    'event_espresso'
2038
-                ),
2039
-                __FILE__,
2040
-                __FUNCTION__,
2041
-                __LINE__
2042
-            );
2043
-        }
2044
-
2045
-        // all templates will be reset to whatever the defaults are
2046
-        // for the global template matching the messenger and message type.
2047
-        $success = ! empty($GRP_ID) ? true : false;
2048
-
2049
-        if ($success) {
2050
-            // let's first determine if the incoming template is a global template,
2051
-            // if it isn't then we need to get the global template matching messenger and message type.
2052
-            // $MTPG = EEM_Message_Template_Group::instance()->get_one_by_ID( $GRP_ID );
2053
-
2054
-
2055
-            // note this is ONLY deleting the template fields (Message Template rows) NOT the message template group.
2056
-            $success = $this->_delete_mtp_permanently($GRP_ID, false);
2057
-
2058
-            if ($success) {
2059
-                // if successfully deleted, lets generate the new ones.
2060
-                // Note. We set GLOBAL to true, because resets on ANY template
2061
-                // will use the related global template defaults for regeneration.
2062
-                // This means that if a custom template is reset it resets to whatever the related global template is.
2063
-                // HOWEVER, we DO keep the template pack and template variation set
2064
-                // for the current custom template when resetting.
2065
-                $templates = $this->_generate_new_templates(
2066
-                    $this->_req_data['msgr'],
2067
-                    $this->_req_data['mt'],
2068
-                    $GRP_ID,
2069
-                    true
2070
-                );
2071
-            }
2072
-        }
2073
-
2074
-        // any error messages?
2075
-        if (! $success) {
2076
-            EE_Error::add_error(
2077
-                esc_html__(
2078
-                    'Something went wrong with deleting existing templates. Unable to reset to default',
2079
-                    'event_espresso'
2080
-                ),
2081
-                __FILE__,
2082
-                __FUNCTION__,
2083
-                __LINE__
2084
-            );
2085
-        }
2086
-
2087
-        // all good, let's add a success message!
2088
-        if ($success && ! empty($templates)) {
2089
-            // the info for the template we generated is the first element in the returned array
2090
-            // $templates = $templates[0];
2091
-            EE_Error::overwrite_success();
2092
-            EE_Error::add_success(__('Templates have been reset to defaults.', 'event_espresso'));
2093
-        }
2094
-
2095
-
2096
-        $query_args = array(
2097
-            'id'      => isset($templates[0]['GRP_ID']) ? $templates[0]['GRP_ID'] : null,
2098
-            'context' => isset($templates[0]['MTP_context']) ? $templates[0]['MTP_context'] : null,
2099
-            'action'  => isset($templates[0]['GRP_ID']) ? 'edit_message_template' : 'global_mtps',
2100
-        );
2101
-
2102
-        // if called via ajax then we return query args otherwise redirect
2103
-        if (defined('DOING_AJAX') && DOING_AJAX) {
2104
-            return $query_args;
2105
-        } else {
2106
-            $this->_redirect_after_action(false, '', '', $query_args, true);
2107
-
2108
-            return null;
2109
-        }
2110
-    }
2111
-
2112
-
2113
-    /**
2114
-     * Retrieve and set the message preview for display.
2115
-     *
2116
-     * @param bool $send if TRUE then we are doing an actual TEST send with the results of the preview.
2117
-     * @return string
2118
-     * @throws ReflectionException
2119
-     * @throws EE_Error
2120
-     * @throws InvalidArgumentException
2121
-     * @throws InvalidDataTypeException
2122
-     * @throws InvalidInterfaceException
2123
-     */
2124
-    public function _preview_message($send = false)
2125
-    {
2126
-        // first make sure we've got the necessary parameters
2127
-        if (! isset(
2128
-            $this->_req_data['message_type'],
2129
-            $this->_req_data['messenger'],
2130
-            $this->_req_data['messenger'],
2131
-            $this->_req_data['GRP_ID']
2132
-        )) {
2133
-            EE_Error::add_error(
2134
-                esc_html__('Missing necessary parameters for displaying preview', 'event_espresso'),
2135
-                __FILE__,
2136
-                __FUNCTION__,
2137
-                __LINE__
2138
-            );
2139
-        }
2140
-
2141
-        EE_Registry::instance()->REQ->set('GRP_ID', $this->_req_data['GRP_ID']);
22
+	/**
23
+	 * @type EE_Message_Resource_Manager $_message_resource_manager
24
+	 */
25
+	protected $_message_resource_manager;
26
+
27
+	/**
28
+	 * @type string $_active_message_type_name
29
+	 */
30
+	protected $_active_message_type_name = '';
31
+
32
+	/**
33
+	 * @type EE_messenger $_active_messenger
34
+	 */
35
+	protected $_active_messenger;
36
+	protected $_activate_state;
37
+	protected $_activate_meta_box_type;
38
+	protected $_current_message_meta_box;
39
+	protected $_current_message_meta_box_object;
40
+	protected $_context_switcher;
41
+	protected $_shortcodes = array();
42
+	protected $_active_messengers = array();
43
+	protected $_active_message_types = array();
44
+
45
+	/**
46
+	 * @var EE_Message_Template_Group $_message_template_group
47
+	 */
48
+	protected $_message_template_group;
49
+	protected $_m_mt_settings = array();
50
+
51
+
52
+	/**
53
+	 * This is set via the _set_message_template_group method and holds whatever the template pack for the group is.
54
+	 * IF there is no group then it gets automatically set to the Default template pack.
55
+	 *
56
+	 * @since 4.5.0
57
+	 *
58
+	 * @var EE_Messages_Template_Pack
59
+	 */
60
+	protected $_template_pack;
61
+
62
+
63
+	/**
64
+	 * This is set via the _set_message_template_group method and holds whatever the template pack variation for the
65
+	 * group is.  If there is no group then it automatically gets set to default.
66
+	 *
67
+	 * @since 4.5.0
68
+	 *
69
+	 * @var string
70
+	 */
71
+	protected $_variation;
72
+
73
+
74
+	/**
75
+	 * @param bool $routing
76
+	 * @throws EE_Error
77
+	 */
78
+	public function __construct($routing = true)
79
+	{
80
+		// make sure messages autoloader is running
81
+		EED_Messages::set_autoloaders();
82
+		parent::__construct($routing);
83
+	}
84
+
85
+
86
+	protected function _init_page_props()
87
+	{
88
+		$this->page_slug = EE_MSG_PG_SLUG;
89
+		$this->page_label = esc_html__('Messages Settings', 'event_espresso');
90
+		$this->_admin_base_url = EE_MSG_ADMIN_URL;
91
+		$this->_admin_base_path = EE_MSG_ADMIN;
92
+
93
+		$this->_activate_state = isset($this->_req_data['activate_state']) ? (array) $this->_req_data['activate_state']
94
+			: array();
95
+
96
+		$this->_active_messenger = isset($this->_req_data['messenger']) ? $this->_req_data['messenger'] : null;
97
+		$this->_load_message_resource_manager();
98
+	}
99
+
100
+
101
+	/**
102
+	 * loads messenger objects into the $_active_messengers property (so we can access the needed methods)
103
+	 *
104
+	 * @throws EE_Error
105
+	 * @throws InvalidDataTypeException
106
+	 * @throws InvalidInterfaceException
107
+	 * @throws InvalidArgumentException
108
+	 * @throws ReflectionException
109
+	 */
110
+	protected function _load_message_resource_manager()
111
+	{
112
+		$this->_message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
113
+	}
114
+
115
+
116
+	/**
117
+	 * @deprecated 4.9.9.rc.014
118
+	 * @return array
119
+	 * @throws EE_Error
120
+	 * @throws InvalidArgumentException
121
+	 * @throws InvalidDataTypeException
122
+	 * @throws InvalidInterfaceException
123
+	 */
124
+	public function get_messengers_for_list_table()
125
+	{
126
+		EE_Error::doing_it_wrong(
127
+			__METHOD__,
128
+			sprintf(
129
+				esc_html__(
130
+					'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a messenger filter dropdown which is now generated differently via %s',
131
+					'event_espresso'
132
+				),
133
+				'Messages_Admin_Page::get_messengers_select_input()'
134
+			),
135
+			'4.9.9.rc.014'
136
+		);
137
+
138
+		$m_values = array();
139
+		$active_messengers = EEM_Message::instance()->get_all(array('group_by' => 'MSG_messenger'));
140
+		// setup messengers for selects
141
+		$i = 1;
142
+		foreach ($active_messengers as $active_messenger) {
143
+			if ($active_messenger instanceof EE_Message) {
144
+				$m_values[ $i ]['id'] = $active_messenger->messenger();
145
+				$m_values[ $i ]['text'] = ucwords($active_messenger->messenger_label());
146
+				$i++;
147
+			}
148
+		}
149
+
150
+		return $m_values;
151
+	}
152
+
153
+
154
+	/**
155
+	 * @deprecated 4.9.9.rc.014
156
+	 * @return array
157
+	 * @throws EE_Error
158
+	 * @throws InvalidArgumentException
159
+	 * @throws InvalidDataTypeException
160
+	 * @throws InvalidInterfaceException
161
+	 */
162
+	public function get_message_types_for_list_table()
163
+	{
164
+		EE_Error::doing_it_wrong(
165
+			__METHOD__,
166
+			sprintf(
167
+				esc_html__(
168
+					'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a message type filter dropdown which is now generated differently via %s',
169
+					'event_espresso'
170
+				),
171
+				'Messages_Admin_Page::get_message_types_select_input()'
172
+			),
173
+			'4.9.9.rc.014'
174
+		);
175
+
176
+		$mt_values = array();
177
+		$active_messages = EEM_Message::instance()->get_all(array('group_by' => 'MSG_message_type'));
178
+		$i = 1;
179
+		foreach ($active_messages as $active_message) {
180
+			if ($active_message instanceof EE_Message) {
181
+				$mt_values[ $i ]['id'] = $active_message->message_type();
182
+				$mt_values[ $i ]['text'] = ucwords($active_message->message_type_label());
183
+				$i++;
184
+			}
185
+		}
186
+
187
+		return $mt_values;
188
+	}
189
+
190
+
191
+	/**
192
+	 * @deprecated 4.9.9.rc.014
193
+	 * @return array
194
+	 * @throws EE_Error
195
+	 * @throws InvalidArgumentException
196
+	 * @throws InvalidDataTypeException
197
+	 * @throws InvalidInterfaceException
198
+	 */
199
+	public function get_contexts_for_message_types_for_list_table()
200
+	{
201
+		EE_Error::doing_it_wrong(
202
+			__METHOD__,
203
+			sprintf(
204
+				esc_html__(
205
+					'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a message type context filter dropdown which is now generated differently via %s',
206
+					'event_espresso'
207
+				),
208
+				'Messages_Admin_Page::get_contexts_for_message_types_select_input()'
209
+			),
210
+			'4.9.9.rc.014'
211
+		);
212
+
213
+		$contexts = array();
214
+		$active_message_contexts = EEM_Message::instance()->get_all(array('group_by' => 'MSG_context'));
215
+		foreach ($active_message_contexts as $active_message) {
216
+			if ($active_message instanceof EE_Message) {
217
+				$message_type = $active_message->message_type_object();
218
+				if ($message_type instanceof EE_message_type) {
219
+					$message_type_contexts = $message_type->get_contexts();
220
+					foreach ($message_type_contexts as $context => $context_details) {
221
+						$contexts[ $context ] = $context_details['label'];
222
+					}
223
+				}
224
+			}
225
+		}
226
+
227
+		return $contexts;
228
+	}
229
+
230
+
231
+	/**
232
+	 * Generate select input with provided messenger options array.
233
+	 *
234
+	 * @param array $messenger_options Array of messengers indexed by messenger slug and values are the messenger
235
+	 *                                 labels.
236
+	 * @return string
237
+	 * @throws EE_Error
238
+	 */
239
+	public function get_messengers_select_input($messenger_options)
240
+	{
241
+		// if empty or just one value then just return an empty string
242
+		if (empty($messenger_options)
243
+			|| ! is_array($messenger_options)
244
+			|| count($messenger_options) === 1
245
+		) {
246
+			return '';
247
+		}
248
+		// merge in default
249
+		$messenger_options = array_merge(
250
+			array('none_selected' => esc_html__('Show All Messengers', 'event_espresso')),
251
+			$messenger_options
252
+		);
253
+		$input = new EE_Select_Input(
254
+			$messenger_options,
255
+			array(
256
+				'html_name'  => 'ee_messenger_filter_by',
257
+				'html_id'    => 'ee_messenger_filter_by',
258
+				'html_class' => 'wide',
259
+				'default'    => isset($this->_req_data['ee_messenger_filter_by'])
260
+					? sanitize_title($this->_req_data['ee_messenger_filter_by'])
261
+					: 'none_selected',
262
+			)
263
+		);
264
+
265
+		return $input->get_html_for_input();
266
+	}
267
+
268
+
269
+	/**
270
+	 * Generate select input with provided message type options array.
271
+	 *
272
+	 * @param array $message_type_options Array of message types indexed by message type slug, and values are the
273
+	 *                                    message type labels
274
+	 * @return string
275
+	 * @throws EE_Error
276
+	 */
277
+	public function get_message_types_select_input($message_type_options)
278
+	{
279
+		// if empty or count of options is 1 then just return an empty string
280
+		if (empty($message_type_options)
281
+			|| ! is_array($message_type_options)
282
+			|| count($message_type_options) === 1
283
+		) {
284
+			return '';
285
+		}
286
+		// merge in default
287
+		$message_type_options = array_merge(
288
+			array('none_selected' => esc_html__('Show All Message Types', 'event_espresso')),
289
+			$message_type_options
290
+		);
291
+		$input = new EE_Select_Input(
292
+			$message_type_options,
293
+			array(
294
+				'html_name'  => 'ee_message_type_filter_by',
295
+				'html_id'    => 'ee_message_type_filter_by',
296
+				'html_class' => 'wide',
297
+				'default'    => isset($this->_req_data['ee_message_type_filter_by'])
298
+					? sanitize_title($this->_req_data['ee_message_type_filter_by'])
299
+					: 'none_selected',
300
+			)
301
+		);
302
+
303
+		return $input->get_html_for_input();
304
+	}
305
+
306
+
307
+	/**
308
+	 * Generate select input with provide message type contexts array.
309
+	 *
310
+	 * @param array $context_options Array of message type contexts indexed by context slug, and values are the
311
+	 *                               context label.
312
+	 * @return string
313
+	 * @throws EE_Error
314
+	 */
315
+	public function get_contexts_for_message_types_select_input($context_options)
316
+	{
317
+		// if empty or count of options is one then just return empty string
318
+		if (empty($context_options)
319
+			|| ! is_array($context_options)
320
+			|| count($context_options) === 1
321
+		) {
322
+			return '';
323
+		}
324
+		// merge in default
325
+		$context_options = array_merge(
326
+			array('none_selected' => esc_html__('Show all Contexts', 'event_espresso')),
327
+			$context_options
328
+		);
329
+		$input = new EE_Select_Input(
330
+			$context_options,
331
+			array(
332
+				'html_name'  => 'ee_context_filter_by',
333
+				'html_id'    => 'ee_context_filter_by',
334
+				'html_class' => 'wide',
335
+				'default'    => isset($this->_req_data['ee_context_filter_by'])
336
+					? sanitize_title($this->_req_data['ee_context_filter_by'])
337
+					: 'none_selected',
338
+			)
339
+		);
340
+
341
+		return $input->get_html_for_input();
342
+	}
343
+
344
+
345
+	protected function _ajax_hooks()
346
+	{
347
+		add_action('wp_ajax_activate_messenger', array($this, 'activate_messenger_toggle'));
348
+		add_action('wp_ajax_activate_mt', array($this, 'activate_mt_toggle'));
349
+		add_action('wp_ajax_ee_msgs_save_settings', array($this, 'save_settings'));
350
+		add_action('wp_ajax_ee_msgs_update_mt_form', array($this, 'update_mt_form'));
351
+		add_action('wp_ajax_switch_template_pack', array($this, 'switch_template_pack'));
352
+		add_action('wp_ajax_toggle_context_template', array($this, 'toggle_context_template'));
353
+	}
354
+
355
+
356
+	protected function _define_page_props()
357
+	{
358
+		$this->_admin_page_title = $this->page_label;
359
+		$this->_labels = array(
360
+			'buttons'    => array(
361
+				'add'    => esc_html__('Add New Message Template', 'event_espresso'),
362
+				'edit'   => esc_html__('Edit Message Template', 'event_espresso'),
363
+				'delete' => esc_html__('Delete Message Template', 'event_espresso'),
364
+			),
365
+			'publishbox' => esc_html__('Update Actions', 'event_espresso'),
366
+		);
367
+	}
368
+
369
+
370
+	/**
371
+	 *        an array for storing key => value pairs of request actions and their corresponding methods
372
+	 *
373
+	 * @access protected
374
+	 * @return void
375
+	 */
376
+	protected function _set_page_routes()
377
+	{
378
+		$grp_id = ! empty($this->_req_data['GRP_ID']) && ! is_array($this->_req_data['GRP_ID'])
379
+			? $this->_req_data['GRP_ID']
380
+			: 0;
381
+		$grp_id = empty($grp_id) && ! empty($this->_req_data['id'])
382
+			? $this->_req_data['id']
383
+			: $grp_id;
384
+		$msg_id = ! empty($this->_req_data['MSG_ID']) && ! is_array($this->_req_data['MSG_ID'])
385
+			? $this->_req_data['MSG_ID']
386
+			: 0;
387
+
388
+		$this->_page_routes = array(
389
+			'default'                          => array(
390
+				'func'       => '_message_queue_list_table',
391
+				'capability' => 'ee_read_global_messages',
392
+			),
393
+			'global_mtps'                      => array(
394
+				'func'       => '_ee_default_messages_overview_list_table',
395
+				'capability' => 'ee_read_global_messages',
396
+			),
397
+			'custom_mtps'                      => array(
398
+				'func'       => '_custom_mtps_preview',
399
+				'capability' => 'ee_read_messages',
400
+			),
401
+			'add_new_message_template'         => array(
402
+				'func'       => '_add_message_template',
403
+				'capability' => 'ee_edit_messages',
404
+				'noheader'   => true,
405
+			),
406
+			'edit_message_template'            => array(
407
+				'func'       => '_edit_message_template',
408
+				'capability' => 'ee_edit_message',
409
+				'obj_id'     => $grp_id,
410
+			),
411
+			'preview_message'                  => array(
412
+				'func'               => '_preview_message',
413
+				'capability'         => 'ee_read_message',
414
+				'obj_id'             => $grp_id,
415
+				'noheader'           => true,
416
+				'headers_sent_route' => 'display_preview_message',
417
+			),
418
+			'display_preview_message'          => array(
419
+				'func'       => '_display_preview_message',
420
+				'capability' => 'ee_read_message',
421
+				'obj_id'     => $grp_id,
422
+			),
423
+			'insert_message_template'          => array(
424
+				'func'       => '_insert_or_update_message_template',
425
+				'capability' => 'ee_edit_messages',
426
+				'args'       => array('new_template' => true),
427
+				'noheader'   => true,
428
+			),
429
+			'update_message_template'          => array(
430
+				'func'       => '_insert_or_update_message_template',
431
+				'capability' => 'ee_edit_message',
432
+				'obj_id'     => $grp_id,
433
+				'args'       => array('new_template' => false),
434
+				'noheader'   => true,
435
+			),
436
+			'trash_message_template'           => array(
437
+				'func'       => '_trash_or_restore_message_template',
438
+				'capability' => 'ee_delete_message',
439
+				'obj_id'     => $grp_id,
440
+				'args'       => array('trash' => true, 'all' => true),
441
+				'noheader'   => true,
442
+			),
443
+			'trash_message_template_context'   => array(
444
+				'func'       => '_trash_or_restore_message_template',
445
+				'capability' => 'ee_delete_message',
446
+				'obj_id'     => $grp_id,
447
+				'args'       => array('trash' => true),
448
+				'noheader'   => true,
449
+			),
450
+			'restore_message_template'         => array(
451
+				'func'       => '_trash_or_restore_message_template',
452
+				'capability' => 'ee_delete_message',
453
+				'obj_id'     => $grp_id,
454
+				'args'       => array('trash' => false, 'all' => true),
455
+				'noheader'   => true,
456
+			),
457
+			'restore_message_template_context' => array(
458
+				'func'       => '_trash_or_restore_message_template',
459
+				'capability' => 'ee_delete_message',
460
+				'obj_id'     => $grp_id,
461
+				'args'       => array('trash' => false),
462
+				'noheader'   => true,
463
+			),
464
+			'delete_message_template'          => array(
465
+				'func'       => '_delete_message_template',
466
+				'capability' => 'ee_delete_message',
467
+				'obj_id'     => $grp_id,
468
+				'noheader'   => true,
469
+			),
470
+			'reset_to_default'                 => array(
471
+				'func'       => '_reset_to_default_template',
472
+				'capability' => 'ee_edit_message',
473
+				'obj_id'     => $grp_id,
474
+				'noheader'   => true,
475
+			),
476
+			'settings'                         => array(
477
+				'func'       => '_settings',
478
+				'capability' => 'manage_options',
479
+			),
480
+			'update_global_settings'           => array(
481
+				'func'       => '_update_global_settings',
482
+				'capability' => 'manage_options',
483
+				'noheader'   => true,
484
+			),
485
+			'generate_now'                     => array(
486
+				'func'       => '_generate_now',
487
+				'capability' => 'ee_send_message',
488
+				'noheader'   => true,
489
+			),
490
+			'generate_and_send_now'            => array(
491
+				'func'       => '_generate_and_send_now',
492
+				'capability' => 'ee_send_message',
493
+				'noheader'   => true,
494
+			),
495
+			'queue_for_resending'              => array(
496
+				'func'       => '_queue_for_resending',
497
+				'capability' => 'ee_send_message',
498
+				'noheader'   => true,
499
+			),
500
+			'send_now'                         => array(
501
+				'func'       => '_send_now',
502
+				'capability' => 'ee_send_message',
503
+				'noheader'   => true,
504
+			),
505
+			'delete_ee_message'                => array(
506
+				'func'       => '_delete_ee_messages',
507
+				'capability' => 'ee_delete_messages',
508
+				'noheader'   => true,
509
+			),
510
+			'delete_ee_messages'               => array(
511
+				'func'       => '_delete_ee_messages',
512
+				'capability' => 'ee_delete_messages',
513
+				'noheader'   => true,
514
+				'obj_id'     => $msg_id,
515
+			),
516
+		);
517
+	}
518
+
519
+
520
+	protected function _set_page_config()
521
+	{
522
+		$this->_page_config = array(
523
+			'default'                  => array(
524
+				'nav'           => array(
525
+					'label' => esc_html__('Message Activity', 'event_espresso'),
526
+					'order' => 10,
527
+				),
528
+				'list_table'    => 'EE_Message_List_Table',
529
+				// 'qtips' => array( 'EE_Message_List_Table_Tips' ),
530
+				'require_nonce' => false,
531
+			),
532
+			'global_mtps'              => array(
533
+				'nav'           => array(
534
+					'label' => esc_html__('Default Message Templates', 'event_espresso'),
535
+					'order' => 20,
536
+				),
537
+				'list_table'    => 'Messages_Template_List_Table',
538
+				'help_tabs'     => array(
539
+					'messages_overview_help_tab'                                => array(
540
+						'title'    => esc_html__('Messages Overview', 'event_espresso'),
541
+						'filename' => 'messages_overview',
542
+					),
543
+					'messages_overview_messages_table_column_headings_help_tab' => array(
544
+						'title'    => esc_html__('Messages Table Column Headings', 'event_espresso'),
545
+						'filename' => 'messages_overview_table_column_headings',
546
+					),
547
+					'messages_overview_messages_filters_help_tab'               => array(
548
+						'title'    => esc_html__('Message Filters', 'event_espresso'),
549
+						'filename' => 'messages_overview_filters',
550
+					),
551
+					'messages_overview_messages_views_help_tab'                 => array(
552
+						'title'    => esc_html__('Message Views', 'event_espresso'),
553
+						'filename' => 'messages_overview_views',
554
+					),
555
+					'message_overview_message_types_help_tab'                   => array(
556
+						'title'    => esc_html__('Message Types', 'event_espresso'),
557
+						'filename' => 'messages_overview_types',
558
+					),
559
+					'messages_overview_messengers_help_tab'                     => array(
560
+						'title'    => esc_html__('Messengers', 'event_espresso'),
561
+						'filename' => 'messages_overview_messengers',
562
+					),
563
+				),
564
+				'help_tour'     => array('Messages_Overview_Help_Tour'),
565
+				'require_nonce' => false,
566
+			),
567
+			'custom_mtps'              => array(
568
+				'nav'           => array(
569
+					'label' => esc_html__('Custom Message Templates', 'event_espresso'),
570
+					'order' => 30,
571
+				),
572
+				'help_tabs'     => array(),
573
+				'help_tour'     => array(),
574
+				'require_nonce' => false,
575
+			),
576
+			'add_new_message_template' => array(
577
+				'nav'           => array(
578
+					'label'      => esc_html__('Add New Message Templates', 'event_espresso'),
579
+					'order'      => 5,
580
+					'persistent' => false,
581
+				),
582
+				'require_nonce' => false,
583
+			),
584
+			'edit_message_template'    => array(
585
+				'labels'        => array(
586
+					'buttons'    => array(
587
+						'reset' => esc_html__('Reset Templates', 'event_espresso'),
588
+					),
589
+					'publishbox' => esc_html__('Update Actions', 'event_espresso'),
590
+				),
591
+				'nav'           => array(
592
+					'label'      => esc_html__('Edit Message Templates', 'event_espresso'),
593
+					'order'      => 5,
594
+					'persistent' => false,
595
+					'url'        => '',
596
+				),
597
+				'metaboxes'     => array('_publish_post_box', '_register_edit_meta_boxes'),
598
+				'has_metaboxes' => true,
599
+				'help_tour'     => array('Message_Templates_Edit_Help_Tour'),
600
+				'help_tabs'     => array(
601
+					'edit_message_template'            => array(
602
+						'title'    => esc_html__('Message Template Editor', 'event_espresso'),
603
+						'callback' => 'edit_message_template_help_tab',
604
+					),
605
+					'message_templates_help_tab'       => array(
606
+						'title'    => esc_html__('Message Templates', 'event_espresso'),
607
+						'filename' => 'messages_templates',
608
+					),
609
+					'message_template_shortcodes'      => array(
610
+						'title'    => esc_html__('Message Shortcodes', 'event_espresso'),
611
+						'callback' => 'message_template_shortcodes_help_tab',
612
+					),
613
+					'message_preview_help_tab'         => array(
614
+						'title'    => esc_html__('Message Preview', 'event_espresso'),
615
+						'filename' => 'messages_preview',
616
+					),
617
+					'messages_overview_other_help_tab' => array(
618
+						'title'    => esc_html__('Messages Other', 'event_espresso'),
619
+						'filename' => 'messages_overview_other',
620
+					),
621
+				),
622
+				'require_nonce' => false,
623
+			),
624
+			'display_preview_message'  => array(
625
+				'nav'           => array(
626
+					'label'      => esc_html__('Message Preview', 'event_espresso'),
627
+					'order'      => 5,
628
+					'url'        => '',
629
+					'persistent' => false,
630
+				),
631
+				'help_tabs'     => array(
632
+					'preview_message' => array(
633
+						'title'    => esc_html__('About Previews', 'event_espresso'),
634
+						'callback' => 'preview_message_help_tab',
635
+					),
636
+				),
637
+				'require_nonce' => false,
638
+			),
639
+			'settings'                 => array(
640
+				'nav'           => array(
641
+					'label' => esc_html__('Settings', 'event_espresso'),
642
+					'order' => 40,
643
+				),
644
+				'metaboxes'     => array('_messages_settings_metaboxes'),
645
+				'help_tabs'     => array(
646
+					'messages_settings_help_tab'               => array(
647
+						'title'    => esc_html__('Messages Settings', 'event_espresso'),
648
+						'filename' => 'messages_settings',
649
+					),
650
+					'messages_settings_message_types_help_tab' => array(
651
+						'title'    => esc_html__('Activating / Deactivating Message Types', 'event_espresso'),
652
+						'filename' => 'messages_settings_message_types',
653
+					),
654
+					'messages_settings_messengers_help_tab'    => array(
655
+						'title'    => esc_html__('Activating / Deactivating Messengers', 'event_espresso'),
656
+						'filename' => 'messages_settings_messengers',
657
+					),
658
+				),
659
+				'help_tour'     => array('Messages_Settings_Help_Tour'),
660
+				'require_nonce' => false,
661
+			),
662
+		);
663
+	}
664
+
665
+
666
+	protected function _add_screen_options()
667
+	{
668
+		// todo
669
+	}
670
+
671
+
672
+	protected function _add_screen_options_global_mtps()
673
+	{
674
+		/**
675
+		 * Note: the reason for the value swap here on $this->_admin_page_title is because $this->_per_page_screen_options
676
+		 * uses the $_admin_page_title property and we want different outputs in the different spots.
677
+		 */
678
+		$page_title = $this->_admin_page_title;
679
+		$this->_admin_page_title = esc_html__('Global Message Templates', 'event_espresso');
680
+		$this->_per_page_screen_option();
681
+		$this->_admin_page_title = $page_title;
682
+	}
683
+
684
+
685
+	protected function _add_screen_options_default()
686
+	{
687
+		$this->_admin_page_title = esc_html__('Message Activity', 'event_espresso');
688
+		$this->_per_page_screen_option();
689
+	}
690
+
691
+
692
+	// none of the below group are currently used for Messages
693
+	protected function _add_feature_pointers()
694
+	{
695
+	}
696
+
697
+	public function admin_init()
698
+	{
699
+	}
700
+
701
+	public function admin_notices()
702
+	{
703
+	}
704
+
705
+	public function admin_footer_scripts()
706
+	{
707
+	}
708
+
709
+
710
+	public function messages_help_tab()
711
+	{
712
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_help_tab.template.php');
713
+	}
714
+
715
+
716
+	public function messengers_help_tab()
717
+	{
718
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messenger_help_tab.template.php');
719
+	}
720
+
721
+
722
+	public function message_types_help_tab()
723
+	{
724
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_type_help_tab.template.php');
725
+	}
726
+
727
+
728
+	public function messages_overview_help_tab()
729
+	{
730
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_overview_help_tab.template.php');
731
+	}
732
+
733
+
734
+	public function message_templates_help_tab()
735
+	{
736
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_templates_help_tab.template.php');
737
+	}
738
+
739
+
740
+	public function edit_message_template_help_tab()
741
+	{
742
+		$args['img1'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/editor.png' . '" alt="'
743
+						. esc_attr__('Editor Title', 'event_espresso')
744
+						. '" />';
745
+		$args['img2'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/switch-context.png' . '" alt="'
746
+						. esc_attr__('Context Switcher and Preview', 'event_espresso')
747
+						. '" />';
748
+		$args['img3'] = '<img class="left" src="' . EE_MSG_ASSETS_URL . 'images/form-fields.png' . '" alt="'
749
+						. esc_attr__('Message Template Form Fields', 'event_espresso')
750
+						. '" />';
751
+		$args['img4'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/shortcodes-metabox.png' . '" alt="'
752
+						. esc_attr__('Shortcodes Metabox', 'event_espresso')
753
+						. '" />';
754
+		$args['img5'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/publish-meta-box.png' . '" alt="'
755
+						. esc_attr__('Publish Metabox', 'event_espresso')
756
+						. '" />';
757
+		EEH_Template::display_template(
758
+			EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_templates_editor_help_tab.template.php',
759
+			$args
760
+		);
761
+	}
762
+
763
+
764
+	public function message_template_shortcodes_help_tab()
765
+	{
766
+		$this->_set_shortcodes();
767
+		$args['shortcodes'] = $this->_shortcodes;
768
+		EEH_Template::display_template(
769
+			EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_shortcodes_help_tab.template.php',
770
+			$args
771
+		);
772
+	}
773
+
774
+
775
+	public function preview_message_help_tab()
776
+	{
777
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_preview_help_tab.template.php');
778
+	}
779
+
780
+
781
+	public function settings_help_tab()
782
+	{
783
+		$args['img1'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-active.png'
784
+						. '" alt="' . esc_attr__('Active Email Tab', 'event_espresso') . '" />';
785
+		$args['img2'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-inactive.png'
786
+						. '" alt="' . esc_attr__('Inactive Email Tab', 'event_espresso') . '" />';
787
+		$args['img3'] = '<div class="switch">'
788
+						. '<input class="ee-on-off-toggle ee-toggle-round-flat"'
789
+						. ' type="checkbox" checked="checked">'
790
+						. '<label for="ee-on-off-toggle-on"></label>'
791
+						. '</div>';
792
+		$args['img4'] = '<div class="switch">'
793
+						. '<input class="ee-on-off-toggle ee-toggle-round-flat"'
794
+						. ' type="checkbox">'
795
+						. '<label for="ee-on-off-toggle-on"></label>'
796
+						. '</div>';
797
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_settings_help_tab.template.php', $args);
798
+	}
799
+
800
+
801
+	public function load_scripts_styles()
802
+	{
803
+		wp_register_style('espresso_ee_msg', EE_MSG_ASSETS_URL . 'ee_message_admin.css', EVENT_ESPRESSO_VERSION);
804
+		wp_enqueue_style('espresso_ee_msg');
805
+
806
+		wp_register_script(
807
+			'ee-messages-settings',
808
+			EE_MSG_ASSETS_URL . 'ee-messages-settings.js',
809
+			array('jquery-ui-droppable', 'ee-serialize-full-array'),
810
+			EVENT_ESPRESSO_VERSION,
811
+			true
812
+		);
813
+		wp_register_script(
814
+			'ee-msg-list-table-js',
815
+			EE_MSG_ASSETS_URL . 'ee_message_admin_list_table.js',
816
+			array('ee-dialog'),
817
+			EVENT_ESPRESSO_VERSION
818
+		);
819
+	}
820
+
821
+
822
+	public function load_scripts_styles_default()
823
+	{
824
+		wp_enqueue_script('ee-msg-list-table-js');
825
+	}
826
+
827
+
828
+	public function wp_editor_css($mce_css)
829
+	{
830
+		// if we're on the edit_message_template route
831
+		if ($this->_req_action === 'edit_message_template' && $this->_active_messenger instanceof EE_messenger) {
832
+			$message_type_name = $this->_active_message_type_name;
833
+
834
+			// we're going to REPLACE the existing mce css
835
+			// we need to get the css file location from the active messenger
836
+			$mce_css = $this->_active_messenger->get_variation(
837
+				$this->_template_pack,
838
+				$message_type_name,
839
+				true,
840
+				'wpeditor',
841
+				$this->_variation
842
+			);
843
+		}
844
+
845
+		return $mce_css;
846
+	}
847
+
848
+
849
+	public function load_scripts_styles_edit_message_template()
850
+	{
851
+
852
+		$this->_set_shortcodes();
853
+
854
+		EE_Registry::$i18n_js_strings['confirm_default_reset'] = sprintf(
855
+			esc_html__(
856
+				'Are you sure you want to reset the %s %s message templates?  Remember continuing will reset the templates for all contexts in this messenger and message type group.',
857
+				'event_espresso'
858
+			),
859
+			$this->_message_template_group->messenger_obj()->label['singular'],
860
+			$this->_message_template_group->message_type_obj()->label['singular']
861
+		);
862
+		EE_Registry::$i18n_js_strings['confirm_switch_template_pack'] = esc_html__(
863
+			'Switching the template pack for a messages template will reset the content for the template so the new layout is loaded.  Any custom content in the existing template will be lost. Are you sure you wish to do this?',
864
+			'event_espresso'
865
+		);
866
+		EE_Registry::$i18n_js_strings['server_error'] = esc_html__(
867
+			'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
868
+			'event_espresso'
869
+		);
870
+
871
+		wp_register_script(
872
+			'ee_msgs_edit_js',
873
+			EE_MSG_ASSETS_URL . 'ee_message_editor.js',
874
+			array('jquery'),
875
+			EVENT_ESPRESSO_VERSION
876
+		);
877
+
878
+		wp_enqueue_script('ee_admin_js');
879
+		wp_enqueue_script('ee_msgs_edit_js');
880
+
881
+		// add in special css for tiny_mce
882
+		add_filter('mce_css', array($this, 'wp_editor_css'));
883
+	}
884
+
885
+
886
+	public function load_scripts_styles_display_preview_message()
887
+	{
888
+
889
+		$this->_set_message_template_group();
890
+
891
+		if (isset($this->_req_data['messenger'])) {
892
+			$this->_active_messenger = $this->_message_resource_manager->get_active_messenger(
893
+				$this->_req_data['messenger']
894
+			);
895
+		}
896
+
897
+		$message_type_name = isset($this->_req_data['message_type']) ? $this->_req_data['message_type'] : '';
898
+
899
+
900
+		wp_enqueue_style(
901
+			'espresso_preview_css',
902
+			$this->_active_messenger->get_variation(
903
+				$this->_template_pack,
904
+				$message_type_name,
905
+				true,
906
+				'preview',
907
+				$this->_variation
908
+			)
909
+		);
910
+	}
911
+
912
+
913
+	public function load_scripts_styles_settings()
914
+	{
915
+		wp_register_style(
916
+			'ee-message-settings',
917
+			EE_MSG_ASSETS_URL . 'ee_message_settings.css',
918
+			array(),
919
+			EVENT_ESPRESSO_VERSION
920
+		);
921
+		wp_enqueue_style('ee-text-links');
922
+		wp_enqueue_style('ee-message-settings');
923
+		wp_enqueue_script('ee-messages-settings');
924
+	}
925
+
926
+
927
+	/**
928
+	 * set views array for List Table
929
+	 */
930
+	public function _set_list_table_views_global_mtps()
931
+	{
932
+		$this->_views = array(
933
+			'in_use' => array(
934
+				'slug'  => 'in_use',
935
+				'label' => esc_html__('In Use', 'event_espresso'),
936
+				'count' => 0,
937
+			),
938
+		);
939
+	}
940
+
941
+
942
+	/**
943
+	 * Set views array for the Custom Template List Table
944
+	 */
945
+	public function _set_list_table_views_custom_mtps()
946
+	{
947
+		$this->_set_list_table_views_global_mtps();
948
+		$this->_views['in_use']['bulk_action'] = array(
949
+			'trash_message_template' => esc_html__('Move to Trash', 'event_espresso'),
950
+		);
951
+	}
952
+
953
+
954
+	/**
955
+	 * set views array for message queue list table
956
+	 *
957
+	 * @throws InvalidDataTypeException
958
+	 * @throws InvalidInterfaceException
959
+	 * @throws InvalidArgumentException
960
+	 * @throws EE_Error
961
+	 * @throws ReflectionException
962
+	 */
963
+	public function _set_list_table_views_default()
964
+	{
965
+		EE_Registry::instance()->load_helper('Template');
966
+
967
+		$common_bulk_actions = EE_Registry::instance()->CAP->current_user_can(
968
+			'ee_send_message',
969
+			'message_list_table_bulk_actions'
970
+		)
971
+			? array(
972
+				'generate_now'          => esc_html__('Generate Now', 'event_espresso'),
973
+				'generate_and_send_now' => esc_html__('Generate and Send Now', 'event_espresso'),
974
+				'queue_for_resending'   => esc_html__('Queue for Resending', 'event_espresso'),
975
+				'send_now'              => esc_html__('Send Now', 'event_espresso'),
976
+			)
977
+			: array();
978
+
979
+		$delete_bulk_action = EE_Registry::instance()->CAP->current_user_can(
980
+			'ee_delete_messages',
981
+			'message_list_table_bulk_actions'
982
+		)
983
+			? array('delete_ee_messages' => esc_html__('Delete Messages', 'event_espresso'))
984
+			: array();
985
+
986
+
987
+		$this->_views = array(
988
+			'all' => array(
989
+				'slug'        => 'all',
990
+				'label'       => esc_html__('All', 'event_espresso'),
991
+				'count'       => 0,
992
+				'bulk_action' => array_merge($common_bulk_actions, $delete_bulk_action),
993
+			),
994
+		);
995
+
996
+
997
+		foreach (EEM_Message::instance()->all_statuses() as $status) {
998
+			if ($status === EEM_Message::status_debug_only && ! EEM_Message::debug()) {
999
+				continue;
1000
+			}
1001
+			$status_bulk_actions = $common_bulk_actions;
1002
+			// unset bulk actions not applying to status
1003
+			if (! empty($status_bulk_actions)) {
1004
+				switch ($status) {
1005
+					case EEM_Message::status_idle:
1006
+					case EEM_Message::status_resend:
1007
+						$status_bulk_actions['send_now'] = $common_bulk_actions['send_now'];
1008
+						break;
1009
+
1010
+					case EEM_Message::status_failed:
1011
+					case EEM_Message::status_debug_only:
1012
+					case EEM_Message::status_messenger_executing:
1013
+						$status_bulk_actions = array();
1014
+						break;
1015
+
1016
+					case EEM_Message::status_incomplete:
1017
+						unset($status_bulk_actions['queue_for_resending'], $status_bulk_actions['send_now']);
1018
+						break;
1019
+
1020
+					case EEM_Message::status_retry:
1021
+					case EEM_Message::status_sent:
1022
+						unset($status_bulk_actions['generate_now'], $status_bulk_actions['generate_and_send_now']);
1023
+						break;
1024
+				}
1025
+			}
1026
+
1027
+			// skip adding messenger executing status to views because it will be included with the Failed view.
1028
+			if ($status === EEM_Message::status_messenger_executing) {
1029
+				continue;
1030
+			}
1031
+
1032
+			$this->_views[ strtolower($status) ] = array(
1033
+				'slug'        => strtolower($status),
1034
+				'label'       => EEH_Template::pretty_status($status, false, 'sentence'),
1035
+				'count'       => 0,
1036
+				'bulk_action' => array_merge($status_bulk_actions, $delete_bulk_action),
1037
+			);
1038
+		}
1039
+	}
1040
+
1041
+
1042
+	protected function _ee_default_messages_overview_list_table()
1043
+	{
1044
+		$this->_admin_page_title = esc_html__('Default Message Templates', 'event_espresso');
1045
+		$this->display_admin_list_table_page_with_no_sidebar();
1046
+	}
1047
+
1048
+
1049
+	protected function _message_queue_list_table()
1050
+	{
1051
+		$this->_search_btn_label = esc_html__('Message Activity', 'event_espresso');
1052
+		$this->_template_args['per_column'] = 6;
1053
+		$this->_template_args['after_list_table'] = $this->_display_legend($this->_message_legend_items());
1054
+		$this->_template_args['before_list_table'] = '<h3>'
1055
+													 . EEM_Message::instance()->get_pretty_label_for_results()
1056
+													 . '</h3>';
1057
+		$this->display_admin_list_table_page_with_no_sidebar();
1058
+	}
1059
+
1060
+
1061
+	protected function _message_legend_items()
1062
+	{
1063
+
1064
+		$action_css_classes = EEH_MSG_Template::get_message_action_icons();
1065
+		$action_items = array();
1066
+
1067
+		foreach ($action_css_classes as $action_item => $action_details) {
1068
+			if ($action_item === 'see_notifications_for') {
1069
+				continue;
1070
+			}
1071
+			$action_items[ $action_item ] = array(
1072
+				'class' => $action_details['css_class'],
1073
+				'desc'  => $action_details['label'],
1074
+			);
1075
+		}
1076
+
1077
+		/** @type array $status_items status legend setup */
1078
+		$status_items = array(
1079
+			'sent_status'                => array(
1080
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_sent,
1081
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_sent, false, 'sentence'),
1082
+			),
1083
+			'idle_status'                => array(
1084
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_idle,
1085
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_idle, false, 'sentence'),
1086
+			),
1087
+			'failed_status'              => array(
1088
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_failed,
1089
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_failed, false, 'sentence'),
1090
+			),
1091
+			'messenger_executing_status' => array(
1092
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_messenger_executing,
1093
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_messenger_executing, false, 'sentence'),
1094
+			),
1095
+			'resend_status'              => array(
1096
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_resend,
1097
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_resend, false, 'sentence'),
1098
+			),
1099
+			'incomplete_status'          => array(
1100
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_incomplete,
1101
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_incomplete, false, 'sentence'),
1102
+			),
1103
+			'retry_status'               => array(
1104
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_retry,
1105
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_retry, false, 'sentence'),
1106
+			),
1107
+		);
1108
+		if (EEM_Message::debug()) {
1109
+			$status_items['debug_only_status'] = array(
1110
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_debug_only,
1111
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_debug_only, false, 'sentence'),
1112
+			);
1113
+		}
1114
+
1115
+		return array_merge($action_items, $status_items);
1116
+	}
1117
+
1118
+
1119
+	protected function _custom_mtps_preview()
1120
+	{
1121
+		$this->_admin_page_title = esc_html__('Custom Message Templates (Preview)', 'event_espresso');
1122
+		$this->_template_args['preview_img'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/custom_mtps_preview.png"'
1123
+											   . ' alt="' . esc_attr__(
1124
+												   'Preview Custom Message Templates screenshot',
1125
+												   'event_espresso'
1126
+											   ) . '" />';
1127
+		$this->_template_args['preview_text'] = '<strong>'
1128
+												. esc_html__(
1129
+													'Custom Message Templates is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. With the Custom Message Templates feature, you are able to create custom message templates and assign them on a per-event basis.',
1130
+													'event_espresso'
1131
+												)
1132
+												. '</strong>';
1133
+
1134
+		$this->display_admin_caf_preview_page('custom_message_types', false);
1135
+	}
1136
+
1137
+
1138
+	/**
1139
+	 * get_message_templates
1140
+	 * This gets all the message templates for listing on the overview list.
1141
+	 *
1142
+	 * @access public
1143
+	 * @param int    $perpage the amount of templates groups to show per page
1144
+	 * @param string $type    the current _view we're getting templates for
1145
+	 * @param bool   $count   return count?
1146
+	 * @param bool   $all     disregard any paging info (get all data);
1147
+	 * @param bool   $global  whether to return just global (true) or custom templates (false)
1148
+	 * @return array
1149
+	 * @throws EE_Error
1150
+	 * @throws InvalidArgumentException
1151
+	 * @throws InvalidDataTypeException
1152
+	 * @throws InvalidInterfaceException
1153
+	 */
1154
+	public function get_message_templates(
1155
+		$perpage = 10,
1156
+		$type = 'in_use',
1157
+		$count = false,
1158
+		$all = false,
1159
+		$global = true
1160
+	) {
1161
+
1162
+		$MTP = EEM_Message_Template_Group::instance();
1163
+
1164
+		$this->_req_data['orderby'] = empty($this->_req_data['orderby']) ? 'GRP_ID' : $this->_req_data['orderby'];
1165
+		$orderby = $this->_req_data['orderby'];
1166
+
1167
+		$order = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
1168
+			? $this->_req_data['order']
1169
+			: 'ASC';
1170
+
1171
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
1172
+			? $this->_req_data['paged']
1173
+			: 1;
1174
+		$per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
1175
+			? $this->_req_data['perpage']
1176
+			: $perpage;
1177
+
1178
+		$offset = ($current_page - 1) * $per_page;
1179
+		$limit = $all ? null : array($offset, $per_page);
1180
+
1181
+
1182
+		// options will match what is in the _views array property
1183
+		switch ($type) {
1184
+			case 'in_use':
1185
+				$templates = $MTP->get_all_active_message_templates($orderby, $order, $limit, $count, $global, true);
1186
+				break;
1187
+			default:
1188
+				$templates = $MTP->get_all_trashed_grouped_message_templates($orderby, $order, $limit, $count, $global);
1189
+		}
1190
+
1191
+		return $templates;
1192
+	}
1193
+
1194
+
1195
+	/**
1196
+	 * filters etc might need a list of installed message_types
1197
+	 *
1198
+	 * @return array an array of message type objects
1199
+	 */
1200
+	public function get_installed_message_types()
1201
+	{
1202
+		$installed_message_types = $this->_message_resource_manager->installed_message_types();
1203
+		$installed = array();
1204
+
1205
+		foreach ($installed_message_types as $message_type) {
1206
+			$installed[ $message_type->name ] = $message_type;
1207
+		}
1208
+
1209
+		return $installed;
1210
+	}
1211
+
1212
+
1213
+	/**
1214
+	 * _add_message_template
1215
+	 *
1216
+	 * This is used when creating a custom template. All Custom Templates start based off another template.
1217
+	 *
1218
+	 * @param string $message_type
1219
+	 * @param string $messenger
1220
+	 * @param string $GRP_ID
1221
+	 *
1222
+	 * @throws EE_error
1223
+	 */
1224
+	protected function _add_message_template($message_type = '', $messenger = '', $GRP_ID = '')
1225
+	{
1226
+		// set values override any request data
1227
+		$message_type = ! empty($message_type) ? $message_type : '';
1228
+		$message_type = empty($message_type) && ! empty($this->_req_data['message_type'])
1229
+			? $this->_req_data['message_type']
1230
+			: $message_type;
1231
+
1232
+		$messenger = ! empty($messenger) ? $messenger : '';
1233
+		$messenger = empty($messenger) && ! empty($this->_req_data['messenger'])
1234
+			? $this->_req_data['messenger']
1235
+			: $messenger;
1236
+
1237
+		$GRP_ID = ! empty($GRP_ID) ? $GRP_ID : '';
1238
+		$GRP_ID = empty($GRP_ID) && ! empty($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : $GRP_ID;
1239
+
1240
+		// we need messenger and message type.  They should be coming from the event editor. If not here then return error
1241
+		if (empty($message_type) || empty($messenger)) {
1242
+			throw new EE_Error(
1243
+				esc_html__(
1244
+					'Sorry, but we can\'t create new templates because we\'re missing the messenger or message type',
1245
+					'event_espresso'
1246
+				)
1247
+			);
1248
+		}
1249
+
1250
+		// we need the GRP_ID for the template being used as the base for the new template
1251
+		if (empty($GRP_ID)) {
1252
+			throw new EE_Error(
1253
+				esc_html__(
1254
+					'In order to create a custom message template the GRP_ID of the template being used as a base is needed',
1255
+					'event_espresso'
1256
+				)
1257
+			);
1258
+		}
1259
+
1260
+		// let's just make sure the template gets generated!
1261
+
1262
+		// we need to reassign some variables for what the insert is expecting
1263
+		$this->_req_data['MTP_messenger'] = $messenger;
1264
+		$this->_req_data['MTP_message_type'] = $message_type;
1265
+		$this->_req_data['GRP_ID'] = $GRP_ID;
1266
+		$this->_insert_or_update_message_template(true);
1267
+	}
1268
+
1269
+
1270
+	/**
1271
+	 * public wrapper for the _add_message_template method
1272
+	 *
1273
+	 * @param string $message_type     message type slug
1274
+	 * @param string $messenger        messenger slug
1275
+	 * @param int    $GRP_ID           GRP_ID for the related message template group this new template will be based
1276
+	 *                                 off of.
1277
+	 * @throws EE_error
1278
+	 */
1279
+	public function add_message_template($message_type, $messenger, $GRP_ID)
1280
+	{
1281
+		$this->_add_message_template($message_type, $messenger, $GRP_ID);
1282
+	}
1283
+
1284
+
1285
+	/**
1286
+	 * _edit_message_template
1287
+	 *
1288
+	 * @access protected
1289
+	 * @return void
1290
+	 * @throws InvalidIdentifierException
1291
+	 * @throws DomainException
1292
+	 * @throws EE_Error
1293
+	 * @throws InvalidArgumentException
1294
+	 * @throws ReflectionException
1295
+	 * @throws InvalidDataTypeException
1296
+	 * @throws InvalidInterfaceException
1297
+	 */
1298
+	protected function _edit_message_template()
1299
+	{
1300
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1301
+		$template_fields = '';
1302
+		$sidebar_fields = '';
1303
+		// we filter the tinyMCE settings to remove the validation since message templates by their nature will not have
1304
+		// valid html in the templates.
1305
+		add_filter('tiny_mce_before_init', array($this, 'filter_tinymce_init'), 10, 2);
1306
+
1307
+		$GRP_ID = isset($this->_req_data['id']) && ! empty($this->_req_data['id'])
1308
+			? absint($this->_req_data['id'])
1309
+			: false;
1310
+
1311
+		$EVT_ID = isset($this->_req_data['evt_id']) && ! empty($this->_req_data['evt_id'])
1312
+		? absint($this->_req_data['evt_id'])
1313
+		: false;
1314
+
1315
+		$this->_set_shortcodes(); // this also sets the _message_template property.
1316
+		$message_template_group = $this->_message_template_group;
1317
+		$c_label = $message_template_group->context_label();
1318
+		$c_config = $message_template_group->contexts_config();
1319
+
1320
+		reset($c_config);
1321
+		$context = isset($this->_req_data['context']) && ! empty($this->_req_data['context'])
1322
+			? strtolower($this->_req_data['context'])
1323
+			: key($c_config);
1324
+
1325
+
1326
+		if (empty($GRP_ID)) {
1327
+			$action = 'insert_message_template';
1328
+			$edit_message_template_form_url = add_query_arg(
1329
+				array('action' => $action, 'noheader' => true),
1330
+				EE_MSG_ADMIN_URL
1331
+			);
1332
+		} else {
1333
+			$action = 'update_message_template';
1334
+			$edit_message_template_form_url = add_query_arg(
1335
+				array('action' => $action, 'noheader' => true),
1336
+				EE_MSG_ADMIN_URL
1337
+			);
1338
+		}
1339
+
1340
+		// set active messenger for this view
1341
+		$this->_active_messenger = $this->_message_resource_manager->get_active_messenger(
1342
+			$message_template_group->messenger()
1343
+		);
1344
+		$this->_active_message_type_name = $message_template_group->message_type();
1345
+
1346
+
1347
+		// Do we have any validation errors?
1348
+		$validators = $this->_get_transient();
1349
+		$v_fields = ! empty($validators) ? array_keys($validators) : array();
1350
+
1351
+
1352
+		// we need to assemble the title from Various details
1353
+		$context_label = sprintf(
1354
+			esc_html__('(%s %s)', 'event_espresso'),
1355
+			$c_config[ $context ]['label'],
1356
+			ucwords($c_label['label'])
1357
+		);
1358
+
1359
+		$title = sprintf(
1360
+			esc_html__(' %s %s Template %s', 'event_espresso'),
1361
+			ucwords($message_template_group->messenger_obj()->label['singular']),
1362
+			ucwords($message_template_group->message_type_obj()->label['singular']),
1363
+			$context_label
1364
+		);
1365
+
1366
+		$this->_template_args['GRP_ID'] = $GRP_ID;
1367
+		$this->_template_args['message_template'] = $message_template_group;
1368
+		$this->_template_args['is_extra_fields'] = false;
1369
+
1370
+
1371
+		// let's get EEH_MSG_Template so we can get template form fields
1372
+		$template_field_structure = EEH_MSG_Template::get_fields(
1373
+			$message_template_group->messenger(),
1374
+			$message_template_group->message_type()
1375
+		);
1376
+
1377
+		if (! $template_field_structure) {
1378
+			$template_field_structure = false;
1379
+			$template_fields = esc_html__(
1380
+				'There was an error in assembling the fields for this display (you should see an error message)',
1381
+				'event_espresso'
1382
+			);
1383
+		}
1384
+
1385
+
1386
+		$message_templates = $message_template_group->context_templates();
1387
+
1388
+
1389
+		// if we have the extra key.. then we need to remove the content index from the template_field_structure as it
1390
+		// will get handled in the "extra" array.
1391
+		if (is_array($template_field_structure[ $context ]) && isset($template_field_structure[ $context ]['extra'])) {
1392
+			foreach ($template_field_structure[ $context ]['extra'] as $reference_field => $new_fields) {
1393
+				unset($template_field_structure[ $context ][ $reference_field ]);
1394
+			}
1395
+		}
1396
+
1397
+		// let's loop through the template_field_structure and actually assemble the input fields!
1398
+		if (! empty($template_field_structure)) {
1399
+			foreach ($template_field_structure[ $context ] as $template_field => $field_setup_array) {
1400
+				// if this is an 'extra' template field then we need to remove any existing fields that are keyed up in
1401
+				// the extra array and reset them.
1402
+				if ($template_field === 'extra') {
1403
+					$this->_template_args['is_extra_fields'] = true;
1404
+					foreach ($field_setup_array as $reference_field => $new_fields_array) {
1405
+						$message_template = $message_templates[ $context ][ $reference_field ];
1406
+						$content = $message_template instanceof EE_Message_Template
1407
+							? $message_template->get('MTP_content')
1408
+							: '';
1409
+						foreach ($new_fields_array as $extra_field => $extra_array) {
1410
+							// let's verify if we need this extra field via the shortcodes parameter.
1411
+							$continue = false;
1412
+							if (isset($extra_array['shortcodes_required'])) {
1413
+								foreach ((array) $extra_array['shortcodes_required'] as $shortcode) {
1414
+									if (! array_key_exists($shortcode, $this->_shortcodes)) {
1415
+										$continue = true;
1416
+									}
1417
+								}
1418
+								if ($continue) {
1419
+									continue;
1420
+								}
1421
+							}
1422
+
1423
+							$field_id = $reference_field
1424
+										. '-'
1425
+										. $extra_field
1426
+										. '-content';
1427
+							$template_form_fields[ $field_id ] = $extra_array;
1428
+							$template_form_fields[ $field_id ]['name'] = 'MTP_template_fields['
1429
+																		 . $reference_field
1430
+																		 . '][content]['
1431
+																		 . $extra_field . ']';
1432
+							$css_class = isset($extra_array['css_class'])
1433
+								? $extra_array['css_class']
1434
+								: '';
1435
+
1436
+							$template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1437
+																			  && in_array($extra_field, $v_fields, true)
1438
+																			  &&
1439
+																			  (
1440
+																				  is_array($validators[ $extra_field ])
1441
+																				  && isset($validators[ $extra_field ]['msg'])
1442
+																			  )
1443
+								? 'validate-error ' . $css_class
1444
+								: $css_class;
1445
+
1446
+							$template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1447
+																		  && isset($content[ $extra_field ])
1448
+								? $content[ $extra_field ]
1449
+								: '';
1450
+
1451
+							// do we have a validation error?  if we do then let's use that value instead
1452
+							$template_form_fields[ $field_id ]['value'] = isset($validators[ $extra_field ])
1453
+								? $validators[ $extra_field ]['value']
1454
+								: $template_form_fields[ $field_id ]['value'];
1455
+
1456
+
1457
+							$template_form_fields[ $field_id ]['db-col'] = 'MTP_content';
1458
+
1459
+							// shortcode selector
1460
+							$field_name_to_use = $extra_field === 'main'
1461
+								? 'content'
1462
+								: $extra_field;
1463
+							$template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1464
+								$field_name_to_use,
1465
+								$field_id
1466
+							);
1467
+
1468
+							if (isset($extra_array['input']) && $extra_array['input'] === 'wp_editor') {
1469
+								// we want to decode the entities
1470
+								$template_form_fields[ $field_id ]['value'] = $template_form_fields[ $field_id ]['value'];
1471
+							}/**/
1472
+						}
1473
+						$templatefield_MTP_id = $reference_field . '-MTP_ID';
1474
+						$templatefield_templatename_id = $reference_field . '-name';
1475
+
1476
+						$template_form_fields[ $templatefield_MTP_id ] = array(
1477
+							'name'       => 'MTP_template_fields[' . $reference_field . '][MTP_ID]',
1478
+							'label'      => null,
1479
+							'input'      => 'hidden',
1480
+							'type'       => 'int',
1481
+							'required'   => false,
1482
+							'validation' => false,
1483
+							'value'      => ! empty($message_templates) ? $message_template->ID() : '',
1484
+							'css_class'  => '',
1485
+							'format'     => '%d',
1486
+							'db-col'     => 'MTP_ID',
1487
+						);
1488
+
1489
+						$template_form_fields[ $templatefield_templatename_id ] = array(
1490
+							'name'       => 'MTP_template_fields[' . $reference_field . '][name]',
1491
+							'label'      => null,
1492
+							'input'      => 'hidden',
1493
+							'type'       => 'string',
1494
+							'required'   => false,
1495
+							'validation' => true,
1496
+							'value'      => $reference_field,
1497
+							'css_class'  => '',
1498
+							'format'     => '%s',
1499
+							'db-col'     => 'MTP_template_field',
1500
+						);
1501
+					}
1502
+					continue; // skip the next stuff, we got the necessary fields here for this dataset.
1503
+				} else {
1504
+					$field_id = $template_field . '-content';
1505
+					$template_form_fields[ $field_id ] = $field_setup_array;
1506
+					$template_form_fields[ $field_id ]['name'] = 'MTP_template_fields[' . $template_field . '][content]';
1507
+					$message_template = isset($message_templates[ $context ][ $template_field ])
1508
+						? $message_templates[ $context ][ $template_field ]
1509
+						: null;
1510
+					$template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1511
+																  && is_array($message_templates[ $context ])
1512
+																  && $message_template instanceof EE_Message_Template
1513
+						? $message_template->get('MTP_content')
1514
+						: '';
1515
+
1516
+					// do we have a validator error for this field?  if we do then we'll use that value instead
1517
+					$template_form_fields[ $field_id ]['value'] = isset($validators[ $template_field ])
1518
+						? $validators[ $template_field ]['value']
1519
+						: $template_form_fields[ $field_id ]['value'];
1520
+
1521
+
1522
+					$template_form_fields[ $field_id ]['db-col'] = 'MTP_content';
1523
+					$css_class = isset($field_setup_array['css_class'])
1524
+						? $field_setup_array['css_class']
1525
+						: '';
1526
+					$template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1527
+																	  && in_array($template_field, $v_fields, true)
1528
+																	  && isset($validators[ $template_field ]['msg'])
1529
+						? 'validate-error ' . $css_class
1530
+						: $css_class;
1531
+
1532
+					// shortcode selector
1533
+					$template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1534
+						$template_field,
1535
+						$field_id
1536
+					);
1537
+				}
1538
+
1539
+				// k took care of content field(s) now let's take care of others.
1540
+
1541
+				$templatefield_MTP_id = $template_field . '-MTP_ID';
1542
+				$templatefield_field_templatename_id = $template_field . '-name';
1543
+
1544
+				// foreach template field there are actually two form fields created
1545
+				$template_form_fields[ $templatefield_MTP_id ] = array(
1546
+					'name'       => 'MTP_template_fields[' . $template_field . '][MTP_ID]',
1547
+					'label'      => null,
1548
+					'input'      => 'hidden',
1549
+					'type'       => 'int',
1550
+					'required'   => false,
1551
+					'validation' => true,
1552
+					'value'      => $message_template instanceof EE_Message_Template ? $message_template->ID() : '',
1553
+					'css_class'  => '',
1554
+					'format'     => '%d',
1555
+					'db-col'     => 'MTP_ID',
1556
+				);
1557
+
1558
+				$template_form_fields[ $templatefield_field_templatename_id ] = array(
1559
+					'name'       => 'MTP_template_fields[' . $template_field . '][name]',
1560
+					'label'      => null,
1561
+					'input'      => 'hidden',
1562
+					'type'       => 'string',
1563
+					'required'   => false,
1564
+					'validation' => true,
1565
+					'value'      => $template_field,
1566
+					'css_class'  => '',
1567
+					'format'     => '%s',
1568
+					'db-col'     => 'MTP_template_field',
1569
+				);
1570
+			}
1571
+
1572
+			// add other fields
1573
+			$template_form_fields['ee-msg-current-context'] = array(
1574
+				'name'       => 'MTP_context',
1575
+				'label'      => null,
1576
+				'input'      => 'hidden',
1577
+				'type'       => 'string',
1578
+				'required'   => false,
1579
+				'validation' => true,
1580
+				'value'      => $context,
1581
+				'css_class'  => '',
1582
+				'format'     => '%s',
1583
+				'db-col'     => 'MTP_context',
1584
+			);
1585
+
1586
+			$template_form_fields['ee-msg-grp-id'] = array(
1587
+				'name'       => 'GRP_ID',
1588
+				'label'      => null,
1589
+				'input'      => 'hidden',
1590
+				'type'       => 'int',
1591
+				'required'   => false,
1592
+				'validation' => true,
1593
+				'value'      => $GRP_ID,
1594
+				'css_class'  => '',
1595
+				'format'     => '%d',
1596
+				'db-col'     => 'GRP_ID',
1597
+			);
1598
+
1599
+			$template_form_fields['ee-msg-messenger'] = array(
1600
+				'name'       => 'MTP_messenger',
1601
+				'label'      => null,
1602
+				'input'      => 'hidden',
1603
+				'type'       => 'string',
1604
+				'required'   => false,
1605
+				'validation' => true,
1606
+				'value'      => $message_template_group->messenger(),
1607
+				'css_class'  => '',
1608
+				'format'     => '%s',
1609
+				'db-col'     => 'MTP_messenger',
1610
+			);
1611
+
1612
+			$template_form_fields['ee-msg-message-type'] = array(
1613
+				'name'       => 'MTP_message_type',
1614
+				'label'      => null,
1615
+				'input'      => 'hidden',
1616
+				'type'       => 'string',
1617
+				'required'   => false,
1618
+				'validation' => true,
1619
+				'value'      => $message_template_group->message_type(),
1620
+				'css_class'  => '',
1621
+				'format'     => '%s',
1622
+				'db-col'     => 'MTP_message_type',
1623
+			);
1624
+
1625
+			$sidebar_form_fields['ee-msg-is-global'] = array(
1626
+				'name'       => 'MTP_is_global',
1627
+				'label'      => esc_html__('Global Template', 'event_espresso'),
1628
+				'input'      => 'hidden',
1629
+				'type'       => 'int',
1630
+				'required'   => false,
1631
+				'validation' => true,
1632
+				'value'      => $message_template_group->get('MTP_is_global'),
1633
+				'css_class'  => '',
1634
+				'format'     => '%d',
1635
+				'db-col'     => 'MTP_is_global',
1636
+			);
1637
+
1638
+			$sidebar_form_fields['ee-msg-is-override'] = array(
1639
+				'name'       => 'MTP_is_override',
1640
+				'label'      => esc_html__('Override all custom', 'event_espresso'),
1641
+				'input'      => $message_template_group->is_global() ? 'checkbox' : 'hidden',
1642
+				'type'       => 'int',
1643
+				'required'   => false,
1644
+				'validation' => true,
1645
+				'value'      => $message_template_group->get('MTP_is_override'),
1646
+				'css_class'  => '',
1647
+				'format'     => '%d',
1648
+				'db-col'     => 'MTP_is_override',
1649
+			);
1650
+
1651
+			$sidebar_form_fields['ee-msg-is-active'] = array(
1652
+				'name'       => 'MTP_is_active',
1653
+				'label'      => esc_html__('Active Template', 'event_espresso'),
1654
+				'input'      => 'hidden',
1655
+				'type'       => 'int',
1656
+				'required'   => false,
1657
+				'validation' => true,
1658
+				'value'      => $message_template_group->is_active(),
1659
+				'css_class'  => '',
1660
+				'format'     => '%d',
1661
+				'db-col'     => 'MTP_is_active',
1662
+			);
1663
+
1664
+			$sidebar_form_fields['ee-msg-deleted'] = array(
1665
+				'name'       => 'MTP_deleted',
1666
+				'label'      => null,
1667
+				'input'      => 'hidden',
1668
+				'type'       => 'int',
1669
+				'required'   => false,
1670
+				'validation' => true,
1671
+				'value'      => $message_template_group->get('MTP_deleted'),
1672
+				'css_class'  => '',
1673
+				'format'     => '%d',
1674
+				'db-col'     => 'MTP_deleted',
1675
+			);
1676
+			$sidebar_form_fields['ee-msg-author'] = array(
1677
+				'name'       => 'MTP_user_id',
1678
+				'label'      => esc_html__('Author', 'event_espresso'),
1679
+				'input'      => 'hidden',
1680
+				'type'       => 'int',
1681
+				'required'   => false,
1682
+				'validation' => false,
1683
+				'value'      => $message_template_group->user(),
1684
+				'format'     => '%d',
1685
+				'db-col'     => 'MTP_user_id',
1686
+			);
1687
+
1688
+			$sidebar_form_fields['ee-msg-route'] = array(
1689
+				'name'  => 'action',
1690
+				'input' => 'hidden',
1691
+				'type'  => 'string',
1692
+				'value' => $action,
1693
+			);
1694
+
1695
+			$sidebar_form_fields['ee-msg-id'] = array(
1696
+				'name'  => 'id',
1697
+				'input' => 'hidden',
1698
+				'type'  => 'int',
1699
+				'value' => $GRP_ID,
1700
+			);
1701
+			$sidebar_form_fields['ee-msg-evt-nonce'] = array(
1702
+				'name'  => $action . '_nonce',
1703
+				'input' => 'hidden',
1704
+				'type'  => 'string',
1705
+				'value' => wp_create_nonce($action . '_nonce'),
1706
+			);
1707
+
1708
+			if (isset($this->_req_data['template_switch']) && $this->_req_data['template_switch']) {
1709
+				$sidebar_form_fields['ee-msg-template-switch'] = array(
1710
+					'name'  => 'template_switch',
1711
+					'input' => 'hidden',
1712
+					'type'  => 'int',
1713
+					'value' => 1,
1714
+				);
1715
+			}
1716
+
1717
+
1718
+			$template_fields = $this->_generate_admin_form_fields($template_form_fields);
1719
+			$sidebar_fields = $this->_generate_admin_form_fields($sidebar_form_fields);
1720
+		} //end if ( !empty($template_field_structure) )
1721
+
1722
+		// set extra content for publish box
1723
+		$this->_template_args['publish_box_extra_content'] = $sidebar_fields;
1724
+		$this->_set_publish_post_box_vars(
1725
+			'id',
1726
+			$GRP_ID,
1727
+			false,
1728
+			add_query_arg(
1729
+				array('action' => 'global_mtps'),
1730
+				$this->_admin_base_url
1731
+			)
1732
+		);
1733
+
1734
+		// add preview button
1735
+		$preview_url = parent::add_query_args_and_nonce(
1736
+			array(
1737
+				'message_type' => $message_template_group->message_type(),
1738
+				'messenger'    => $message_template_group->messenger(),
1739
+				'context'      => $context,
1740
+				'GRP_ID'       => $GRP_ID,
1741
+				'evt_id'       => $EVT_ID,
1742
+				'action'       => 'preview_message',
1743
+			),
1744
+			$this->_admin_base_url
1745
+		);
1746
+		$preview_button = '<a href="' . $preview_url . '" class="button-secondary messages-preview-button">'
1747
+						  . esc_html__('Preview', 'event_espresso')
1748
+						  . '</a>';
1749
+
1750
+
1751
+		// setup context switcher
1752
+		$context_switcher_args = array(
1753
+			'page'    => 'espresso_messages',
1754
+			'action'  => 'edit_message_template',
1755
+			'id'      => $GRP_ID,
1756
+			'evt_id'  => $EVT_ID,
1757
+			'context' => $context,
1758
+			'extra'   => $preview_button,
1759
+		);
1760
+		$this->_set_context_switcher($message_template_group, $context_switcher_args);
1761
+
1762
+
1763
+		// main box
1764
+		$this->_template_args['template_fields'] = $template_fields;
1765
+		$this->_template_args['sidebar_box_id'] = 'details';
1766
+		$this->_template_args['action'] = $action;
1767
+		$this->_template_args['context'] = $context;
1768
+		$this->_template_args['edit_message_template_form_url'] = $edit_message_template_form_url;
1769
+		$this->_template_args['learn_more_about_message_templates_link'] =
1770
+			$this->_learn_more_about_message_templates_link();
1771
+
1772
+
1773
+		$this->_template_args['before_admin_page_content'] = $this->add_context_switcher();
1774
+		$this->_template_args['before_admin_page_content'] .= $this->add_active_context_element(
1775
+			$message_template_group,
1776
+			$context,
1777
+			$context_label
1778
+		);
1779
+		$this->_template_args['before_admin_page_content'] .= $this->_add_form_element_before();
1780
+		$this->_template_args['after_admin_page_content'] = $this->_add_form_element_after();
1781
+
1782
+		$this->_template_path = $this->_template_args['GRP_ID']
1783
+			? EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_edit_meta_box.template.php'
1784
+			: EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_add_meta_box.template.php';
1785
+
1786
+		// send along EE_Message_Template_Group object for further template use.
1787
+		$this->_template_args['MTP'] = $message_template_group;
1788
+
1789
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
1790
+			$this->_template_path,
1791
+			$this->_template_args,
1792
+			true
1793
+		);
1794
+
1795
+
1796
+		// finally, let's set the admin_page title
1797
+		$this->_admin_page_title = sprintf(__('Editing %s', 'event_espresso'), $title);
1798
+
1799
+
1800
+		// we need to take care of setting the shortcodes property for use elsewhere.
1801
+		$this->_set_shortcodes();
1802
+
1803
+
1804
+		// final template wrapper
1805
+		$this->display_admin_page_with_sidebar();
1806
+	}
1807
+
1808
+
1809
+	public function filter_tinymce_init($mceInit, $editor_id)
1810
+	{
1811
+		return $mceInit;
1812
+	}
1813
+
1814
+
1815
+	public function add_context_switcher()
1816
+	{
1817
+		return $this->_context_switcher;
1818
+	}
1819
+
1820
+
1821
+	/**
1822
+	 * Adds the activation/deactivation toggle for the message template context.
1823
+	 *
1824
+	 * @param EE_Message_Template_Group $message_template_group
1825
+	 * @param string                    $context
1826
+	 * @param string                    $context_label
1827
+	 * @return string
1828
+	 * @throws DomainException
1829
+	 * @throws EE_Error
1830
+	 * @throws InvalidIdentifierException
1831
+	 */
1832
+	protected function add_active_context_element(
1833
+		EE_Message_Template_Group $message_template_group,
1834
+		$context,
1835
+		$context_label
1836
+	) {
1837
+		$template_args = array(
1838
+			'context'                   => $context,
1839
+			'nonce'                     => wp_create_nonce('activate_' . $context . '_toggle_nonce'),
1840
+			'is_active'                 => $message_template_group->is_context_active($context),
1841
+			'on_off_action'             => $message_template_group->is_context_active($context)
1842
+				? 'context-off'
1843
+				: 'context-on',
1844
+			'context_label'             => str_replace(array('(', ')'), '', $context_label),
1845
+			'message_template_group_id' => $message_template_group->ID(),
1846
+		);
1847
+		return EEH_Template::display_template(
1848
+			EE_MSG_TEMPLATE_PATH . 'ee_msg_editor_active_context_element.template.php',
1849
+			$template_args,
1850
+			true
1851
+		);
1852
+	}
1853
+
1854
+
1855
+	/**
1856
+	 * Ajax callback for `toggle_context_template` ajax action.
1857
+	 * Handles toggling the message context on or off.
1858
+	 *
1859
+	 * @throws EE_Error
1860
+	 * @throws InvalidArgumentException
1861
+	 * @throws InvalidDataTypeException
1862
+	 * @throws InvalidIdentifierException
1863
+	 * @throws InvalidInterfaceException
1864
+	 */
1865
+	public function toggle_context_template()
1866
+	{
1867
+		$success = true;
1868
+		// check for required data
1869
+		if (! isset(
1870
+			$this->_req_data['message_template_group_id'],
1871
+			$this->_req_data['context'],
1872
+			$this->_req_data['status']
1873
+		)) {
1874
+			EE_Error::add_error(
1875
+				esc_html__('Required data for doing this action is not available.', 'event_espresso'),
1876
+				__FILE__,
1877
+				__FUNCTION__,
1878
+				__LINE__
1879
+			);
1880
+			$success = false;
1881
+		}
1882
+
1883
+		$nonce = isset($this->_req_data['toggle_context_nonce'])
1884
+			? sanitize_text_field($this->_req_data['toggle_context_nonce'])
1885
+			: '';
1886
+		$nonce_ref = 'activate_' . $this->_req_data['context'] . '_toggle_nonce';
1887
+		$this->_verify_nonce($nonce, $nonce_ref);
1888
+		$status = $this->_req_data['status'];
1889
+		if ($status !== 'off' && $status !== 'on') {
1890
+			EE_Error::add_error(
1891
+				sprintf(
1892
+					esc_html__('The given status (%s) is not valid. Must be "off" or "on"', 'event_espresso'),
1893
+					$this->_req_data['status']
1894
+				),
1895
+				__FILE__,
1896
+				__FUNCTION__,
1897
+				__LINE__
1898
+			);
1899
+			$success = false;
1900
+		}
1901
+		$message_template_group = EEM_Message_Template_Group::instance()->get_one_by_ID(
1902
+			$this->_req_data['message_template_group_id']
1903
+		);
1904
+		if (! $message_template_group instanceof EE_Message_Template_Group) {
1905
+			EE_Error::add_error(
1906
+				sprintf(
1907
+					esc_html__(
1908
+						'Unable to change the active state because the given id "%1$d" does not match a valid "%2$s"',
1909
+						'event_espresso'
1910
+					),
1911
+					$this->_req_data['message_template_group_id'],
1912
+					'EE_Message_Template_Group'
1913
+				),
1914
+				__FILE__,
1915
+				__FUNCTION__,
1916
+				__LINE__
1917
+			);
1918
+			$success = false;
1919
+		}
1920
+		if ($success) {
1921
+			$success = $status === 'off'
1922
+				? $message_template_group->deactivate_context($this->_req_data['context'])
1923
+				: $message_template_group->activate_context($this->_req_data['context']);
1924
+		}
1925
+		$this->_template_args['success'] = $success;
1926
+		$this->_return_json();
1927
+	}
1928
+
1929
+
1930
+	public function _add_form_element_before()
1931
+	{
1932
+		return '<form method="post" action="'
1933
+			   . $this->_template_args["edit_message_template_form_url"]
1934
+			   . '" id="ee-msg-edit-frm">';
1935
+	}
1936
+
1937
+	public function _add_form_element_after()
1938
+	{
1939
+		return '</form>';
1940
+	}
1941
+
1942
+
1943
+	/**
1944
+	 * This executes switching the template pack for a message template.
1945
+	 *
1946
+	 * @since 4.5.0
1947
+	 * @throws EE_Error
1948
+	 * @throws InvalidDataTypeException
1949
+	 * @throws InvalidInterfaceException
1950
+	 * @throws InvalidArgumentException
1951
+	 * @throws ReflectionException
1952
+	 */
1953
+	public function switch_template_pack()
1954
+	{
1955
+		$GRP_ID = ! empty($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : 0;
1956
+		$template_pack = ! empty($this->_req_data['template_pack']) ? $this->_req_data['template_pack'] : '';
1957
+
1958
+		// verify we have needed values.
1959
+		if (empty($GRP_ID) || empty($template_pack)) {
1960
+			$this->_template_args['error'] = true;
1961
+			EE_Error::add_error(
1962
+				esc_html__('The required date for switching templates is not available.', 'event_espresso'),
1963
+				__FILE__,
1964
+				__FUNCTION__,
1965
+				__LINE__
1966
+			);
1967
+		} else {
1968
+			// get template, set the new template_pack and then reset to default
1969
+			/** @type EE_Message_Template_Group $message_template_group */
1970
+			$message_template_group = EEM_Message_Template_Group::instance()->get_one_by_ID($GRP_ID);
1971
+
1972
+			$message_template_group->set_template_pack_name($template_pack);
1973
+			$this->_req_data['msgr'] = $message_template_group->messenger();
1974
+			$this->_req_data['mt'] = $message_template_group->message_type();
1975
+
1976
+			$query_args = $this->_reset_to_default_template();
1977
+
1978
+			if (empty($query_args['id'])) {
1979
+				EE_Error::add_error(
1980
+					esc_html__(
1981
+						'Something went wrong with switching the template pack. Please try again or contact EE support',
1982
+						'event_espresso'
1983
+					),
1984
+					__FILE__,
1985
+					__FUNCTION__,
1986
+					__LINE__
1987
+				);
1988
+				$this->_template_args['error'] = true;
1989
+			} else {
1990
+				$template_label = $message_template_group->get_template_pack()->label;
1991
+				$template_pack_labels = $message_template_group->messenger_obj()->get_supports_labels();
1992
+				EE_Error::add_success(
1993
+					sprintf(
1994
+						esc_html__(
1995
+							'This message template has been successfully switched to use the %1$s %2$s.  Please wait while the page reloads with your new template.',
1996
+							'event_espresso'
1997
+						),
1998
+						$template_label,
1999
+						$template_pack_labels->template_pack
2000
+					)
2001
+				);
2002
+				// generate the redirect url for js.
2003
+				$url = self::add_query_args_and_nonce(
2004
+					$query_args,
2005
+					$this->_admin_base_url
2006
+				);
2007
+				$this->_template_args['data']['redirect_url'] = $url;
2008
+				$this->_template_args['success'] = true;
2009
+			}
2010
+
2011
+			$this->_return_json();
2012
+		}
2013
+	}
2014
+
2015
+
2016
+	/**
2017
+	 * This handles resetting the template for the given messenger/message_type so that users can start from scratch if
2018
+	 * they want.
2019
+	 *
2020
+	 * @access protected
2021
+	 * @return array|null
2022
+	 * @throws EE_Error
2023
+	 * @throws InvalidArgumentException
2024
+	 * @throws InvalidDataTypeException
2025
+	 * @throws InvalidInterfaceException
2026
+	 */
2027
+	protected function _reset_to_default_template()
2028
+	{
2029
+
2030
+		$templates = array();
2031
+		$GRP_ID = ! empty($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : 0;
2032
+		// we need to make sure we've got the info we need.
2033
+		if (! isset($this->_req_data['msgr'], $this->_req_data['mt'], $this->_req_data['GRP_ID'])) {
2034
+			EE_Error::add_error(
2035
+				esc_html__(
2036
+					'In order to reset the template to its default we require the messenger, message type, and message template GRP_ID to know what is being reset.  At least one of these is missing.',
2037
+					'event_espresso'
2038
+				),
2039
+				__FILE__,
2040
+				__FUNCTION__,
2041
+				__LINE__
2042
+			);
2043
+		}
2044
+
2045
+		// all templates will be reset to whatever the defaults are
2046
+		// for the global template matching the messenger and message type.
2047
+		$success = ! empty($GRP_ID) ? true : false;
2048
+
2049
+		if ($success) {
2050
+			// let's first determine if the incoming template is a global template,
2051
+			// if it isn't then we need to get the global template matching messenger and message type.
2052
+			// $MTPG = EEM_Message_Template_Group::instance()->get_one_by_ID( $GRP_ID );
2053
+
2054
+
2055
+			// note this is ONLY deleting the template fields (Message Template rows) NOT the message template group.
2056
+			$success = $this->_delete_mtp_permanently($GRP_ID, false);
2057
+
2058
+			if ($success) {
2059
+				// if successfully deleted, lets generate the new ones.
2060
+				// Note. We set GLOBAL to true, because resets on ANY template
2061
+				// will use the related global template defaults for regeneration.
2062
+				// This means that if a custom template is reset it resets to whatever the related global template is.
2063
+				// HOWEVER, we DO keep the template pack and template variation set
2064
+				// for the current custom template when resetting.
2065
+				$templates = $this->_generate_new_templates(
2066
+					$this->_req_data['msgr'],
2067
+					$this->_req_data['mt'],
2068
+					$GRP_ID,
2069
+					true
2070
+				);
2071
+			}
2072
+		}
2073
+
2074
+		// any error messages?
2075
+		if (! $success) {
2076
+			EE_Error::add_error(
2077
+				esc_html__(
2078
+					'Something went wrong with deleting existing templates. Unable to reset to default',
2079
+					'event_espresso'
2080
+				),
2081
+				__FILE__,
2082
+				__FUNCTION__,
2083
+				__LINE__
2084
+			);
2085
+		}
2086
+
2087
+		// all good, let's add a success message!
2088
+		if ($success && ! empty($templates)) {
2089
+			// the info for the template we generated is the first element in the returned array
2090
+			// $templates = $templates[0];
2091
+			EE_Error::overwrite_success();
2092
+			EE_Error::add_success(__('Templates have been reset to defaults.', 'event_espresso'));
2093
+		}
2094
+
2095
+
2096
+		$query_args = array(
2097
+			'id'      => isset($templates[0]['GRP_ID']) ? $templates[0]['GRP_ID'] : null,
2098
+			'context' => isset($templates[0]['MTP_context']) ? $templates[0]['MTP_context'] : null,
2099
+			'action'  => isset($templates[0]['GRP_ID']) ? 'edit_message_template' : 'global_mtps',
2100
+		);
2101
+
2102
+		// if called via ajax then we return query args otherwise redirect
2103
+		if (defined('DOING_AJAX') && DOING_AJAX) {
2104
+			return $query_args;
2105
+		} else {
2106
+			$this->_redirect_after_action(false, '', '', $query_args, true);
2107
+
2108
+			return null;
2109
+		}
2110
+	}
2111
+
2112
+
2113
+	/**
2114
+	 * Retrieve and set the message preview for display.
2115
+	 *
2116
+	 * @param bool $send if TRUE then we are doing an actual TEST send with the results of the preview.
2117
+	 * @return string
2118
+	 * @throws ReflectionException
2119
+	 * @throws EE_Error
2120
+	 * @throws InvalidArgumentException
2121
+	 * @throws InvalidDataTypeException
2122
+	 * @throws InvalidInterfaceException
2123
+	 */
2124
+	public function _preview_message($send = false)
2125
+	{
2126
+		// first make sure we've got the necessary parameters
2127
+		if (! isset(
2128
+			$this->_req_data['message_type'],
2129
+			$this->_req_data['messenger'],
2130
+			$this->_req_data['messenger'],
2131
+			$this->_req_data['GRP_ID']
2132
+		)) {
2133
+			EE_Error::add_error(
2134
+				esc_html__('Missing necessary parameters for displaying preview', 'event_espresso'),
2135
+				__FILE__,
2136
+				__FUNCTION__,
2137
+				__LINE__
2138
+			);
2139
+		}
2140
+
2141
+		EE_Registry::instance()->REQ->set('GRP_ID', $this->_req_data['GRP_ID']);
2142 2142
         
2143
-        // if we have an evt_id set on the request, use it.
2144
-        $EVT_ID = isset($this->_req_data['evt_id']) && ! empty($this->_req_data['evt_id'])
2145
-        ? absint($this->_req_data['evt_id'])
2146
-        : false;
2147
-
2148
-
2149
-        // get the preview!
2150
-        $preview = EED_Messages::preview_message(
2151
-            $this->_req_data['message_type'],
2152
-            $this->_req_data['context'],
2153
-            $this->_req_data['messenger'],
2154
-            $send
2155
-        );
2156
-
2157
-        if ($send) {
2158
-            return $preview;
2159
-        }
2160
-
2161
-        // let's add a button to go back to the edit view
2162
-        $query_args = array(
2163
-            'id'      => $this->_req_data['GRP_ID'],
2164
-            'evt_id'  => $EVT_ID,
2165
-            'context' => $this->_req_data['context'],
2166
-            'action'  => 'edit_message_template',
2167
-        );
2168
-        $go_back_url = parent::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2169
-        $preview_button = '<a href="'
2170
-                          . $go_back_url
2171
-                          . '" class="button-secondary messages-preview-go-back-button">'
2172
-                          . esc_html__('Go Back to Edit', 'event_espresso')
2173
-                          . '</a>';
2174
-        $message_types = $this->get_installed_message_types();
2175
-        $active_messenger = $this->_message_resource_manager->get_active_messenger(
2176
-            $this->_req_data['messenger']
2177
-        );
2178
-        $active_messenger_label = $active_messenger instanceof EE_messenger
2179
-            ? ucwords($active_messenger->label['singular'])
2180
-            : esc_html__('Unknown Messenger', 'event_espresso');
2181
-        // let's provide a helpful title for context
2182
-        $preview_title = sprintf(
2183
-            esc_html__('Viewing Preview for %s %s Message Template', 'event_espresso'),
2184
-            $active_messenger_label,
2185
-            ucwords($message_types[ $this->_req_data['message_type'] ]->label['singular'])
2186
-        );
2187
-        if (empty($preview)) {
2188
-            $this->noEventsErrorMessage();
2189
-        }
2190
-        // setup display of preview.
2191
-        $this->_admin_page_title = $preview_title;
2192
-        $this->_template_args['admin_page_title'] = $preview_title;
2193
-        $this->_template_args['admin_page_content'] = $preview_button . '<br />' . $preview;
2194
-        $this->_template_args['data']['force_json'] = true;
2195
-
2196
-        return '';
2197
-    }
2198
-
2199
-
2200
-    /**
2201
-     * Used to set an error if there are no events available for generating a preview/test send.
2202
-     *
2203
-     * @param bool $test_send  Whether the error should be generated for the context of a test send.
2204
-     */
2205
-    protected function noEventsErrorMessage($test_send = false)
2206
-    {
2207
-        $events_url = parent::add_query_args_and_nonce(
2208
-            array(
2209
-                'action' => 'default',
2210
-                'page'   => 'espresso_events',
2211
-            ),
2212
-            admin_url('admin.php')
2213
-        );
2214
-        $message = $test_send
2215
-            ? __(
2216
-                'A test message could not be sent for this message template because there are no events created yet. The preview system uses actual events for generating the test message. %1$sGo see your events%2$s!',
2217
-                'event_espresso'
2218
-            )
2219
-            : __(
2220
-                'There is no preview for this message template available because there are no events created yet. The preview system uses actual events for generating the preview. %1$sGo see your events%2$s!',
2221
-                'event_espresso'
2222
-            );
2223
-
2224
-        EE_Error::add_attention(
2225
-            sprintf(
2226
-                $message,
2227
-                "<a href='{$events_url}'>",
2228
-                '</a>'
2229
-            )
2230
-        );
2231
-    }
2232
-
2233
-
2234
-    /**
2235
-     * The initial _preview_message is on a no headers route.  It will optionally call this if necessary otherwise it
2236
-     * gets called automatically.
2237
-     *
2238
-     * @since 4.5.0
2239
-     *
2240
-     * @return string
2241
-     */
2242
-    protected function _display_preview_message()
2243
-    {
2244
-        $this->display_admin_page_with_no_sidebar();
2245
-    }
2246
-
2247
-
2248
-    /**
2249
-     * registers metaboxes that should show up on the "edit_message_template" page
2250
-     *
2251
-     * @access protected
2252
-     * @return void
2253
-     */
2254
-    protected function _register_edit_meta_boxes()
2255
-    {
2256
-        add_meta_box(
2257
-            'mtp_valid_shortcodes',
2258
-            esc_html__('Valid Shortcodes', 'event_espresso'),
2259
-            array($this, 'shortcode_meta_box'),
2260
-            $this->_current_screen->id,
2261
-            'side',
2262
-            'default'
2263
-        );
2264
-        add_meta_box(
2265
-            'mtp_extra_actions',
2266
-            esc_html__('Extra Actions', 'event_espresso'),
2267
-            array($this, 'extra_actions_meta_box'),
2268
-            $this->_current_screen->id,
2269
-            'side',
2270
-            'high'
2271
-        );
2272
-        add_meta_box(
2273
-            'mtp_templates',
2274
-            esc_html__('Template Styles', 'event_espresso'),
2275
-            array($this, 'template_pack_meta_box'),
2276
-            $this->_current_screen->id,
2277
-            'side',
2278
-            'high'
2279
-        );
2280
-    }
2281
-
2282
-
2283
-    /**
2284
-     * metabox content for all template pack and variation selection.
2285
-     *
2286
-     * @since 4.5.0
2287
-     * @return string
2288
-     * @throws DomainException
2289
-     * @throws EE_Error
2290
-     * @throws InvalidArgumentException
2291
-     * @throws ReflectionException
2292
-     * @throws InvalidDataTypeException
2293
-     * @throws InvalidInterfaceException
2294
-     */
2295
-    public function template_pack_meta_box()
2296
-    {
2297
-        $this->_set_message_template_group();
2298
-
2299
-        $tp_collection = EEH_MSG_Template::get_template_pack_collection();
2300
-
2301
-        $tp_select_values = array();
2302
-
2303
-        foreach ($tp_collection as $tp) {
2304
-            // only include template packs that support this messenger and message type!
2305
-            $supports = $tp->get_supports();
2306
-            if (! isset($supports[ $this->_message_template_group->messenger() ])
2307
-                || ! in_array(
2308
-                    $this->_message_template_group->message_type(),
2309
-                    $supports[ $this->_message_template_group->messenger() ],
2310
-                    true
2311
-                )
2312
-            ) {
2313
-                // not supported
2314
-                continue;
2315
-            }
2316
-
2317
-            $tp_select_values[] = array(
2318
-                'text' => $tp->label,
2319
-                'id'   => $tp->dbref,
2320
-            );
2321
-        }
2322
-
2323
-        // if empty $tp_select_values then we make sure default is set because EVERY message type should be supported by
2324
-        // the default template pack.  This still allows for the odd template pack to override.
2325
-        if (empty($tp_select_values)) {
2326
-            $tp_select_values[] = array(
2327
-                'text' => esc_html__('Default', 'event_espresso'),
2328
-                'id'   => 'default',
2329
-            );
2330
-        }
2331
-
2332
-        // setup variation select values for the currently selected template.
2333
-        $variations = $this->_message_template_group->get_template_pack()->get_variations(
2334
-            $this->_message_template_group->messenger(),
2335
-            $this->_message_template_group->message_type()
2336
-        );
2337
-        $variations_select_values = array();
2338
-        foreach ($variations as $variation => $label) {
2339
-            $variations_select_values[] = array(
2340
-                'text' => $label,
2341
-                'id'   => $variation,
2342
-            );
2343
-        }
2344
-
2345
-        $template_pack_labels = $this->_message_template_group->messenger_obj()->get_supports_labels();
2346
-
2347
-        $template_args['template_packs_selector'] = EEH_Form_Fields::select_input(
2348
-            'MTP_template_pack',
2349
-            $tp_select_values,
2350
-            $this->_message_template_group->get_template_pack_name()
2351
-        );
2352
-        $template_args['variations_selector'] = EEH_Form_Fields::select_input(
2353
-            'MTP_template_variation',
2354
-            $variations_select_values,
2355
-            $this->_message_template_group->get_template_pack_variation()
2356
-        );
2357
-        $template_args['template_pack_label'] = $template_pack_labels->template_pack;
2358
-        $template_args['template_variation_label'] = $template_pack_labels->template_variation;
2359
-        $template_args['template_pack_description'] = $template_pack_labels->template_pack_description;
2360
-        $template_args['template_variation_description'] = $template_pack_labels->template_variation_description;
2361
-
2362
-        $template = EE_MSG_TEMPLATE_PATH . 'template_pack_and_variations_metabox.template.php';
2363
-
2364
-        EEH_Template::display_template($template, $template_args);
2365
-    }
2366
-
2367
-
2368
-    /**
2369
-     * This meta box holds any extra actions related to Message Templates
2370
-     * For now, this includes Resetting templates to defaults and sending a test email.
2371
-     *
2372
-     * @access  public
2373
-     * @return void
2374
-     * @throws EE_Error
2375
-     */
2376
-    public function extra_actions_meta_box()
2377
-    {
2378
-        $template_form_fields = array();
2379
-
2380
-        $extra_args = array(
2381
-            'msgr'   => $this->_message_template_group->messenger(),
2382
-            'mt'     => $this->_message_template_group->message_type(),
2383
-            'GRP_ID' => $this->_message_template_group->GRP_ID(),
2384
-        );
2385
-        // first we need to see if there are any fields
2386
-        $fields = $this->_message_template_group->messenger_obj()->get_test_settings_fields();
2387
-
2388
-        if (! empty($fields)) {
2389
-            // yup there be fields
2390
-            foreach ($fields as $field => $config) {
2391
-                $field_id = $this->_message_template_group->messenger() . '_' . $field;
2392
-                $existing = $this->_message_template_group->messenger_obj()->get_existing_test_settings();
2393
-                $default = isset($config['default']) ? $config['default'] : '';
2394
-                $default = isset($config['value']) ? $config['value'] : $default;
2395
-
2396
-                // if type is hidden and the value is empty
2397
-                // something may have gone wrong so let's correct with the defaults
2398
-                $fix = $config['input'] === 'hidden'
2399
-                       && isset($existing[ $field ])
2400
-                       && empty($existing[ $field ])
2401
-                    ? $default
2402
-                    : '';
2403
-                $existing[ $field ] = isset($existing[ $field ]) && empty($fix)
2404
-                    ? $existing[ $field ]
2405
-                    : $fix;
2406
-
2407
-                $template_form_fields[ $field_id ] = array(
2408
-                    'name'       => 'test_settings_fld[' . $field . ']',
2409
-                    'label'      => $config['label'],
2410
-                    'input'      => $config['input'],
2411
-                    'type'       => $config['type'],
2412
-                    'required'   => $config['required'],
2413
-                    'validation' => $config['validation'],
2414
-                    'value'      => isset($existing[ $field ]) ? $existing[ $field ] : $default,
2415
-                    'css_class'  => $config['css_class'],
2416
-                    'options'    => isset($config['options']) ? $config['options'] : array(),
2417
-                    'default'    => $default,
2418
-                    'format'     => $config['format'],
2419
-                );
2420
-            }
2421
-        }
2422
-
2423
-        $test_settings_fields = ! empty($template_form_fields)
2424
-            ? $this->_generate_admin_form_fields($template_form_fields, 'string', 'ee_tst_settings_flds')
2425
-            : '';
2426
-
2427
-        $test_settings_html = '';
2428
-        // print out $test_settings_fields
2429
-        if (! empty($test_settings_fields)) {
2430
-            echo $test_settings_fields;
2431
-            $test_settings_html = '<input type="submit" class="button-primary mtp-test-button alignright" ';
2432
-            $test_settings_html .= 'name="test_button" value="';
2433
-            $test_settings_html .= esc_html__('Test Send', 'event_espresso');
2434
-            $test_settings_html .= '" /><div style="clear:both"></div>';
2435
-        }
2436
-
2437
-        // and button
2438
-        $test_settings_html .= '<p>'
2439
-                               . esc_html__('Need to reset this message type and start over?', 'event_espresso')
2440
-                               . '</p>';
2441
-        $test_settings_html .= '<div class="publishing-action alignright resetbutton">';
2442
-        $test_settings_html .= $this->get_action_link_or_button(
2443
-            'reset_to_default',
2444
-            'reset',
2445
-            $extra_args,
2446
-            'button-primary reset-default-button'
2447
-        );
2448
-        $test_settings_html .= '</div><div style="clear:both"></div>';
2449
-        echo $test_settings_html;
2450
-    }
2451
-
2452
-
2453
-    /**
2454
-     * This returns the shortcode selector skeleton for a given context and field.
2455
-     *
2456
-     * @since 4.9.rc.000
2457
-     * @param string $field           The name of the field retrieving shortcodes for.
2458
-     * @param string $linked_input_id The css id of the input that the shortcodes get added to.
2459
-     * @return string
2460
-     * @throws DomainException
2461
-     * @throws EE_Error
2462
-     * @throws InvalidArgumentException
2463
-     * @throws ReflectionException
2464
-     * @throws InvalidDataTypeException
2465
-     * @throws InvalidInterfaceException
2466
-     */
2467
-    protected function _get_shortcode_selector($field, $linked_input_id)
2468
-    {
2469
-        $template_args = array(
2470
-            'shortcodes'      => $this->_get_shortcodes(array($field), true),
2471
-            'fieldname'       => $field,
2472
-            'linked_input_id' => $linked_input_id,
2473
-        );
2474
-
2475
-        return EEH_Template::display_template(
2476
-            EE_MSG_TEMPLATE_PATH . 'shortcode_selector_skeleton.template.php',
2477
-            $template_args,
2478
-            true
2479
-        );
2480
-    }
2481
-
2482
-
2483
-    /**
2484
-     * This just takes care of returning the meta box content for shortcodes (only used on the edit message template
2485
-     * page)
2486
-     *
2487
-     * @access public
2488
-     * @return void
2489
-     * @throws EE_Error
2490
-     * @throws InvalidArgumentException
2491
-     * @throws ReflectionException
2492
-     * @throws InvalidDataTypeException
2493
-     * @throws InvalidInterfaceException
2494
-     */
2495
-    public function shortcode_meta_box()
2496
-    {
2497
-        $shortcodes = $this->_get_shortcodes(array(), false); // just make sure shortcodes property is set
2498
-        // $messenger = $this->_message_template_group->messenger_obj();
2499
-        // now let's set the content depending on the status of the shortcodes array
2500
-        if (empty($shortcodes)) {
2501
-            $content = '<p>' . esc_html__('There are no valid shortcodes available', 'event_espresso') . '</p>';
2502
-            echo $content;
2503
-        } else {
2504
-            // $alt = 0;
2505
-            ?>
2143
+		// if we have an evt_id set on the request, use it.
2144
+		$EVT_ID = isset($this->_req_data['evt_id']) && ! empty($this->_req_data['evt_id'])
2145
+		? absint($this->_req_data['evt_id'])
2146
+		: false;
2147
+
2148
+
2149
+		// get the preview!
2150
+		$preview = EED_Messages::preview_message(
2151
+			$this->_req_data['message_type'],
2152
+			$this->_req_data['context'],
2153
+			$this->_req_data['messenger'],
2154
+			$send
2155
+		);
2156
+
2157
+		if ($send) {
2158
+			return $preview;
2159
+		}
2160
+
2161
+		// let's add a button to go back to the edit view
2162
+		$query_args = array(
2163
+			'id'      => $this->_req_data['GRP_ID'],
2164
+			'evt_id'  => $EVT_ID,
2165
+			'context' => $this->_req_data['context'],
2166
+			'action'  => 'edit_message_template',
2167
+		);
2168
+		$go_back_url = parent::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2169
+		$preview_button = '<a href="'
2170
+						  . $go_back_url
2171
+						  . '" class="button-secondary messages-preview-go-back-button">'
2172
+						  . esc_html__('Go Back to Edit', 'event_espresso')
2173
+						  . '</a>';
2174
+		$message_types = $this->get_installed_message_types();
2175
+		$active_messenger = $this->_message_resource_manager->get_active_messenger(
2176
+			$this->_req_data['messenger']
2177
+		);
2178
+		$active_messenger_label = $active_messenger instanceof EE_messenger
2179
+			? ucwords($active_messenger->label['singular'])
2180
+			: esc_html__('Unknown Messenger', 'event_espresso');
2181
+		// let's provide a helpful title for context
2182
+		$preview_title = sprintf(
2183
+			esc_html__('Viewing Preview for %s %s Message Template', 'event_espresso'),
2184
+			$active_messenger_label,
2185
+			ucwords($message_types[ $this->_req_data['message_type'] ]->label['singular'])
2186
+		);
2187
+		if (empty($preview)) {
2188
+			$this->noEventsErrorMessage();
2189
+		}
2190
+		// setup display of preview.
2191
+		$this->_admin_page_title = $preview_title;
2192
+		$this->_template_args['admin_page_title'] = $preview_title;
2193
+		$this->_template_args['admin_page_content'] = $preview_button . '<br />' . $preview;
2194
+		$this->_template_args['data']['force_json'] = true;
2195
+
2196
+		return '';
2197
+	}
2198
+
2199
+
2200
+	/**
2201
+	 * Used to set an error if there are no events available for generating a preview/test send.
2202
+	 *
2203
+	 * @param bool $test_send  Whether the error should be generated for the context of a test send.
2204
+	 */
2205
+	protected function noEventsErrorMessage($test_send = false)
2206
+	{
2207
+		$events_url = parent::add_query_args_and_nonce(
2208
+			array(
2209
+				'action' => 'default',
2210
+				'page'   => 'espresso_events',
2211
+			),
2212
+			admin_url('admin.php')
2213
+		);
2214
+		$message = $test_send
2215
+			? __(
2216
+				'A test message could not be sent for this message template because there are no events created yet. The preview system uses actual events for generating the test message. %1$sGo see your events%2$s!',
2217
+				'event_espresso'
2218
+			)
2219
+			: __(
2220
+				'There is no preview for this message template available because there are no events created yet. The preview system uses actual events for generating the preview. %1$sGo see your events%2$s!',
2221
+				'event_espresso'
2222
+			);
2223
+
2224
+		EE_Error::add_attention(
2225
+			sprintf(
2226
+				$message,
2227
+				"<a href='{$events_url}'>",
2228
+				'</a>'
2229
+			)
2230
+		);
2231
+	}
2232
+
2233
+
2234
+	/**
2235
+	 * The initial _preview_message is on a no headers route.  It will optionally call this if necessary otherwise it
2236
+	 * gets called automatically.
2237
+	 *
2238
+	 * @since 4.5.0
2239
+	 *
2240
+	 * @return string
2241
+	 */
2242
+	protected function _display_preview_message()
2243
+	{
2244
+		$this->display_admin_page_with_no_sidebar();
2245
+	}
2246
+
2247
+
2248
+	/**
2249
+	 * registers metaboxes that should show up on the "edit_message_template" page
2250
+	 *
2251
+	 * @access protected
2252
+	 * @return void
2253
+	 */
2254
+	protected function _register_edit_meta_boxes()
2255
+	{
2256
+		add_meta_box(
2257
+			'mtp_valid_shortcodes',
2258
+			esc_html__('Valid Shortcodes', 'event_espresso'),
2259
+			array($this, 'shortcode_meta_box'),
2260
+			$this->_current_screen->id,
2261
+			'side',
2262
+			'default'
2263
+		);
2264
+		add_meta_box(
2265
+			'mtp_extra_actions',
2266
+			esc_html__('Extra Actions', 'event_espresso'),
2267
+			array($this, 'extra_actions_meta_box'),
2268
+			$this->_current_screen->id,
2269
+			'side',
2270
+			'high'
2271
+		);
2272
+		add_meta_box(
2273
+			'mtp_templates',
2274
+			esc_html__('Template Styles', 'event_espresso'),
2275
+			array($this, 'template_pack_meta_box'),
2276
+			$this->_current_screen->id,
2277
+			'side',
2278
+			'high'
2279
+		);
2280
+	}
2281
+
2282
+
2283
+	/**
2284
+	 * metabox content for all template pack and variation selection.
2285
+	 *
2286
+	 * @since 4.5.0
2287
+	 * @return string
2288
+	 * @throws DomainException
2289
+	 * @throws EE_Error
2290
+	 * @throws InvalidArgumentException
2291
+	 * @throws ReflectionException
2292
+	 * @throws InvalidDataTypeException
2293
+	 * @throws InvalidInterfaceException
2294
+	 */
2295
+	public function template_pack_meta_box()
2296
+	{
2297
+		$this->_set_message_template_group();
2298
+
2299
+		$tp_collection = EEH_MSG_Template::get_template_pack_collection();
2300
+
2301
+		$tp_select_values = array();
2302
+
2303
+		foreach ($tp_collection as $tp) {
2304
+			// only include template packs that support this messenger and message type!
2305
+			$supports = $tp->get_supports();
2306
+			if (! isset($supports[ $this->_message_template_group->messenger() ])
2307
+				|| ! in_array(
2308
+					$this->_message_template_group->message_type(),
2309
+					$supports[ $this->_message_template_group->messenger() ],
2310
+					true
2311
+				)
2312
+			) {
2313
+				// not supported
2314
+				continue;
2315
+			}
2316
+
2317
+			$tp_select_values[] = array(
2318
+				'text' => $tp->label,
2319
+				'id'   => $tp->dbref,
2320
+			);
2321
+		}
2322
+
2323
+		// if empty $tp_select_values then we make sure default is set because EVERY message type should be supported by
2324
+		// the default template pack.  This still allows for the odd template pack to override.
2325
+		if (empty($tp_select_values)) {
2326
+			$tp_select_values[] = array(
2327
+				'text' => esc_html__('Default', 'event_espresso'),
2328
+				'id'   => 'default',
2329
+			);
2330
+		}
2331
+
2332
+		// setup variation select values for the currently selected template.
2333
+		$variations = $this->_message_template_group->get_template_pack()->get_variations(
2334
+			$this->_message_template_group->messenger(),
2335
+			$this->_message_template_group->message_type()
2336
+		);
2337
+		$variations_select_values = array();
2338
+		foreach ($variations as $variation => $label) {
2339
+			$variations_select_values[] = array(
2340
+				'text' => $label,
2341
+				'id'   => $variation,
2342
+			);
2343
+		}
2344
+
2345
+		$template_pack_labels = $this->_message_template_group->messenger_obj()->get_supports_labels();
2346
+
2347
+		$template_args['template_packs_selector'] = EEH_Form_Fields::select_input(
2348
+			'MTP_template_pack',
2349
+			$tp_select_values,
2350
+			$this->_message_template_group->get_template_pack_name()
2351
+		);
2352
+		$template_args['variations_selector'] = EEH_Form_Fields::select_input(
2353
+			'MTP_template_variation',
2354
+			$variations_select_values,
2355
+			$this->_message_template_group->get_template_pack_variation()
2356
+		);
2357
+		$template_args['template_pack_label'] = $template_pack_labels->template_pack;
2358
+		$template_args['template_variation_label'] = $template_pack_labels->template_variation;
2359
+		$template_args['template_pack_description'] = $template_pack_labels->template_pack_description;
2360
+		$template_args['template_variation_description'] = $template_pack_labels->template_variation_description;
2361
+
2362
+		$template = EE_MSG_TEMPLATE_PATH . 'template_pack_and_variations_metabox.template.php';
2363
+
2364
+		EEH_Template::display_template($template, $template_args);
2365
+	}
2366
+
2367
+
2368
+	/**
2369
+	 * This meta box holds any extra actions related to Message Templates
2370
+	 * For now, this includes Resetting templates to defaults and sending a test email.
2371
+	 *
2372
+	 * @access  public
2373
+	 * @return void
2374
+	 * @throws EE_Error
2375
+	 */
2376
+	public function extra_actions_meta_box()
2377
+	{
2378
+		$template_form_fields = array();
2379
+
2380
+		$extra_args = array(
2381
+			'msgr'   => $this->_message_template_group->messenger(),
2382
+			'mt'     => $this->_message_template_group->message_type(),
2383
+			'GRP_ID' => $this->_message_template_group->GRP_ID(),
2384
+		);
2385
+		// first we need to see if there are any fields
2386
+		$fields = $this->_message_template_group->messenger_obj()->get_test_settings_fields();
2387
+
2388
+		if (! empty($fields)) {
2389
+			// yup there be fields
2390
+			foreach ($fields as $field => $config) {
2391
+				$field_id = $this->_message_template_group->messenger() . '_' . $field;
2392
+				$existing = $this->_message_template_group->messenger_obj()->get_existing_test_settings();
2393
+				$default = isset($config['default']) ? $config['default'] : '';
2394
+				$default = isset($config['value']) ? $config['value'] : $default;
2395
+
2396
+				// if type is hidden and the value is empty
2397
+				// something may have gone wrong so let's correct with the defaults
2398
+				$fix = $config['input'] === 'hidden'
2399
+					   && isset($existing[ $field ])
2400
+					   && empty($existing[ $field ])
2401
+					? $default
2402
+					: '';
2403
+				$existing[ $field ] = isset($existing[ $field ]) && empty($fix)
2404
+					? $existing[ $field ]
2405
+					: $fix;
2406
+
2407
+				$template_form_fields[ $field_id ] = array(
2408
+					'name'       => 'test_settings_fld[' . $field . ']',
2409
+					'label'      => $config['label'],
2410
+					'input'      => $config['input'],
2411
+					'type'       => $config['type'],
2412
+					'required'   => $config['required'],
2413
+					'validation' => $config['validation'],
2414
+					'value'      => isset($existing[ $field ]) ? $existing[ $field ] : $default,
2415
+					'css_class'  => $config['css_class'],
2416
+					'options'    => isset($config['options']) ? $config['options'] : array(),
2417
+					'default'    => $default,
2418
+					'format'     => $config['format'],
2419
+				);
2420
+			}
2421
+		}
2422
+
2423
+		$test_settings_fields = ! empty($template_form_fields)
2424
+			? $this->_generate_admin_form_fields($template_form_fields, 'string', 'ee_tst_settings_flds')
2425
+			: '';
2426
+
2427
+		$test_settings_html = '';
2428
+		// print out $test_settings_fields
2429
+		if (! empty($test_settings_fields)) {
2430
+			echo $test_settings_fields;
2431
+			$test_settings_html = '<input type="submit" class="button-primary mtp-test-button alignright" ';
2432
+			$test_settings_html .= 'name="test_button" value="';
2433
+			$test_settings_html .= esc_html__('Test Send', 'event_espresso');
2434
+			$test_settings_html .= '" /><div style="clear:both"></div>';
2435
+		}
2436
+
2437
+		// and button
2438
+		$test_settings_html .= '<p>'
2439
+							   . esc_html__('Need to reset this message type and start over?', 'event_espresso')
2440
+							   . '</p>';
2441
+		$test_settings_html .= '<div class="publishing-action alignright resetbutton">';
2442
+		$test_settings_html .= $this->get_action_link_or_button(
2443
+			'reset_to_default',
2444
+			'reset',
2445
+			$extra_args,
2446
+			'button-primary reset-default-button'
2447
+		);
2448
+		$test_settings_html .= '</div><div style="clear:both"></div>';
2449
+		echo $test_settings_html;
2450
+	}
2451
+
2452
+
2453
+	/**
2454
+	 * This returns the shortcode selector skeleton for a given context and field.
2455
+	 *
2456
+	 * @since 4.9.rc.000
2457
+	 * @param string $field           The name of the field retrieving shortcodes for.
2458
+	 * @param string $linked_input_id The css id of the input that the shortcodes get added to.
2459
+	 * @return string
2460
+	 * @throws DomainException
2461
+	 * @throws EE_Error
2462
+	 * @throws InvalidArgumentException
2463
+	 * @throws ReflectionException
2464
+	 * @throws InvalidDataTypeException
2465
+	 * @throws InvalidInterfaceException
2466
+	 */
2467
+	protected function _get_shortcode_selector($field, $linked_input_id)
2468
+	{
2469
+		$template_args = array(
2470
+			'shortcodes'      => $this->_get_shortcodes(array($field), true),
2471
+			'fieldname'       => $field,
2472
+			'linked_input_id' => $linked_input_id,
2473
+		);
2474
+
2475
+		return EEH_Template::display_template(
2476
+			EE_MSG_TEMPLATE_PATH . 'shortcode_selector_skeleton.template.php',
2477
+			$template_args,
2478
+			true
2479
+		);
2480
+	}
2481
+
2482
+
2483
+	/**
2484
+	 * This just takes care of returning the meta box content for shortcodes (only used on the edit message template
2485
+	 * page)
2486
+	 *
2487
+	 * @access public
2488
+	 * @return void
2489
+	 * @throws EE_Error
2490
+	 * @throws InvalidArgumentException
2491
+	 * @throws ReflectionException
2492
+	 * @throws InvalidDataTypeException
2493
+	 * @throws InvalidInterfaceException
2494
+	 */
2495
+	public function shortcode_meta_box()
2496
+	{
2497
+		$shortcodes = $this->_get_shortcodes(array(), false); // just make sure shortcodes property is set
2498
+		// $messenger = $this->_message_template_group->messenger_obj();
2499
+		// now let's set the content depending on the status of the shortcodes array
2500
+		if (empty($shortcodes)) {
2501
+			$content = '<p>' . esc_html__('There are no valid shortcodes available', 'event_espresso') . '</p>';
2502
+			echo $content;
2503
+		} else {
2504
+			// $alt = 0;
2505
+			?>
2506 2506
             <div style="float:right; margin-top:10px"><?php
2507
-                            echo $this->_get_help_tab_link('message_template_shortcodes');
2508
-                            ?></div>
2507
+							echo $this->_get_help_tab_link('message_template_shortcodes');
2508
+							?></div>
2509 2509
             <p class="small-text"><?php
2510
-                                  printf(
2511
-                                      esc_html__(
2512
-                                          'You can view the shortcodes usable in your template by clicking the %s icon next to each field.',
2513
-                                          'event_espresso'
2514
-                                      ),
2515
-                                      '<span class="dashicons dashicons-menu"></span>'
2516
-                                  );
2517
-                                ?>
2510
+								  printf(
2511
+									  esc_html__(
2512
+										  'You can view the shortcodes usable in your template by clicking the %s icon next to each field.',
2513
+										  'event_espresso'
2514
+									  ),
2515
+									  '<span class="dashicons dashicons-menu"></span>'
2516
+								  );
2517
+								?>
2518 2518
             </p>
2519 2519
             <?php
2520
-        }
2521
-    }
2522
-
2523
-
2524
-    /**
2525
-     * used to set the $_shortcodes property for when its needed elsewhere.
2526
-     *
2527
-     * @access protected
2528
-     * @return void
2529
-     * @throws EE_Error
2530
-     * @throws InvalidArgumentException
2531
-     * @throws ReflectionException
2532
-     * @throws InvalidDataTypeException
2533
-     * @throws InvalidInterfaceException
2534
-     */
2535
-    protected function _set_shortcodes()
2536
-    {
2537
-
2538
-        // no need to run this if the property is already set
2539
-        if (! empty($this->_shortcodes)) {
2540
-            return;
2541
-        }
2542
-
2543
-        $this->_shortcodes = $this->_get_shortcodes();
2544
-    }
2545
-
2546
-
2547
-    /**
2548
-     * get's all shortcodes for a given template group. (typically used by _set_shortcodes to set the $_shortcodes
2549
-     * property)
2550
-     *
2551
-     * @access  protected
2552
-     * @param  array   $fields include an array of specific field names that you want to be used to get the shortcodes
2553
-     *                         for. Defaults to all (for the given context)
2554
-     * @param  boolean $merged Whether to merge all the shortcodes into one list of unique shortcodes
2555
-     * @return array Shortcodes indexed by fieldname and the an array of shortcode/label pairs OR if merged is
2556
-     *                         true just an array of shortcode/label pairs.
2557
-     * @throws EE_Error
2558
-     * @throws InvalidArgumentException
2559
-     * @throws ReflectionException
2560
-     * @throws InvalidDataTypeException
2561
-     * @throws InvalidInterfaceException
2562
-     */
2563
-    protected function _get_shortcodes($fields = array(), $merged = true)
2564
-    {
2565
-        $this->_set_message_template_group();
2566
-
2567
-        // we need the messenger and message template to retrieve the valid shortcodes array.
2568
-        $GRP_ID = isset($this->_req_data['id']) && ! empty($this->_req_data['id'])
2569
-            ? absint($this->_req_data['id'])
2570
-            : false;
2571
-        $context = isset($this->_req_data['context'])
2572
-            ? $this->_req_data['context']
2573
-            : key($this->_message_template_group->contexts_config());
2574
-
2575
-        return ! empty($GRP_ID) ? $this->_message_template_group->get_shortcodes($context, $fields, $merged) : array();
2576
-    }
2577
-
2578
-
2579
-    /**
2580
-     * This sets the _message_template property (containing the called message_template object)
2581
-     *
2582
-     * @access protected
2583
-     * @return void
2584
-     * @throws EE_Error
2585
-     * @throws InvalidArgumentException
2586
-     * @throws ReflectionException
2587
-     * @throws InvalidDataTypeException
2588
-     * @throws InvalidInterfaceException
2589
-     */
2590
-    protected function _set_message_template_group()
2591
-    {
2592
-
2593
-        if (! empty($this->_message_template_group)) {
2594
-            return;
2595
-        } //get out if this is already set.
2596
-
2597
-        $GRP_ID = ! empty($this->_req_data['GRP_ID']) ? absint($this->_req_data['GRP_ID']) : false;
2598
-        $GRP_ID = empty($GRP_ID) && ! empty($this->_req_data['id']) ? $this->_req_data['id'] : $GRP_ID;
2599
-
2600
-        // let's get the message templates
2601
-        $MTP = EEM_Message_Template_Group::instance();
2602
-
2603
-        if (empty($GRP_ID)) {
2604
-            $this->_message_template_group = $MTP->create_default_object();
2605
-        } else {
2606
-            $this->_message_template_group = $MTP->get_one_by_ID($GRP_ID);
2607
-        }
2608
-
2609
-        $this->_template_pack = $this->_message_template_group->get_template_pack();
2610
-        $this->_variation = $this->_message_template_group->get_template_pack_variation();
2611
-    }
2612
-
2613
-
2614
-    /**
2615
-     * sets up a context switcher for edit forms
2616
-     *
2617
-     * @access  protected
2618
-     * @param  EE_Message_Template_Group $template_group_object the template group object being displayed on the form
2619
-     * @param array                      $args                  various things the context switcher needs.
2620
-     * @throws EE_Error
2621
-     */
2622
-    protected function _set_context_switcher(EE_Message_Template_Group $template_group_object, $args)
2623
-    {
2624
-        $context_details = $template_group_object->contexts_config();
2625
-        $context_label = $template_group_object->context_label();
2626
-        ob_start();
2627
-        ?>
2520
+		}
2521
+	}
2522
+
2523
+
2524
+	/**
2525
+	 * used to set the $_shortcodes property for when its needed elsewhere.
2526
+	 *
2527
+	 * @access protected
2528
+	 * @return void
2529
+	 * @throws EE_Error
2530
+	 * @throws InvalidArgumentException
2531
+	 * @throws ReflectionException
2532
+	 * @throws InvalidDataTypeException
2533
+	 * @throws InvalidInterfaceException
2534
+	 */
2535
+	protected function _set_shortcodes()
2536
+	{
2537
+
2538
+		// no need to run this if the property is already set
2539
+		if (! empty($this->_shortcodes)) {
2540
+			return;
2541
+		}
2542
+
2543
+		$this->_shortcodes = $this->_get_shortcodes();
2544
+	}
2545
+
2546
+
2547
+	/**
2548
+	 * get's all shortcodes for a given template group. (typically used by _set_shortcodes to set the $_shortcodes
2549
+	 * property)
2550
+	 *
2551
+	 * @access  protected
2552
+	 * @param  array   $fields include an array of specific field names that you want to be used to get the shortcodes
2553
+	 *                         for. Defaults to all (for the given context)
2554
+	 * @param  boolean $merged Whether to merge all the shortcodes into one list of unique shortcodes
2555
+	 * @return array Shortcodes indexed by fieldname and the an array of shortcode/label pairs OR if merged is
2556
+	 *                         true just an array of shortcode/label pairs.
2557
+	 * @throws EE_Error
2558
+	 * @throws InvalidArgumentException
2559
+	 * @throws ReflectionException
2560
+	 * @throws InvalidDataTypeException
2561
+	 * @throws InvalidInterfaceException
2562
+	 */
2563
+	protected function _get_shortcodes($fields = array(), $merged = true)
2564
+	{
2565
+		$this->_set_message_template_group();
2566
+
2567
+		// we need the messenger and message template to retrieve the valid shortcodes array.
2568
+		$GRP_ID = isset($this->_req_data['id']) && ! empty($this->_req_data['id'])
2569
+			? absint($this->_req_data['id'])
2570
+			: false;
2571
+		$context = isset($this->_req_data['context'])
2572
+			? $this->_req_data['context']
2573
+			: key($this->_message_template_group->contexts_config());
2574
+
2575
+		return ! empty($GRP_ID) ? $this->_message_template_group->get_shortcodes($context, $fields, $merged) : array();
2576
+	}
2577
+
2578
+
2579
+	/**
2580
+	 * This sets the _message_template property (containing the called message_template object)
2581
+	 *
2582
+	 * @access protected
2583
+	 * @return void
2584
+	 * @throws EE_Error
2585
+	 * @throws InvalidArgumentException
2586
+	 * @throws ReflectionException
2587
+	 * @throws InvalidDataTypeException
2588
+	 * @throws InvalidInterfaceException
2589
+	 */
2590
+	protected function _set_message_template_group()
2591
+	{
2592
+
2593
+		if (! empty($this->_message_template_group)) {
2594
+			return;
2595
+		} //get out if this is already set.
2596
+
2597
+		$GRP_ID = ! empty($this->_req_data['GRP_ID']) ? absint($this->_req_data['GRP_ID']) : false;
2598
+		$GRP_ID = empty($GRP_ID) && ! empty($this->_req_data['id']) ? $this->_req_data['id'] : $GRP_ID;
2599
+
2600
+		// let's get the message templates
2601
+		$MTP = EEM_Message_Template_Group::instance();
2602
+
2603
+		if (empty($GRP_ID)) {
2604
+			$this->_message_template_group = $MTP->create_default_object();
2605
+		} else {
2606
+			$this->_message_template_group = $MTP->get_one_by_ID($GRP_ID);
2607
+		}
2608
+
2609
+		$this->_template_pack = $this->_message_template_group->get_template_pack();
2610
+		$this->_variation = $this->_message_template_group->get_template_pack_variation();
2611
+	}
2612
+
2613
+
2614
+	/**
2615
+	 * sets up a context switcher for edit forms
2616
+	 *
2617
+	 * @access  protected
2618
+	 * @param  EE_Message_Template_Group $template_group_object the template group object being displayed on the form
2619
+	 * @param array                      $args                  various things the context switcher needs.
2620
+	 * @throws EE_Error
2621
+	 */
2622
+	protected function _set_context_switcher(EE_Message_Template_Group $template_group_object, $args)
2623
+	{
2624
+		$context_details = $template_group_object->contexts_config();
2625
+		$context_label = $template_group_object->context_label();
2626
+		ob_start();
2627
+		?>
2628 2628
         <div class="ee-msg-switcher-container">
2629 2629
             <form method="get" action="<?php echo EE_MSG_ADMIN_URL; ?>" id="ee-msg-context-switcher-frm">
2630 2630
                 <?php
2631
-                foreach ($args as $name => $value) {
2632
-                    if ($name === 'context' || empty($value) || $name === 'extra') {
2633
-                        continue;
2634
-                    }
2635
-                    ?>
2631
+				foreach ($args as $name => $value) {
2632
+					if ($name === 'context' || empty($value) || $name === 'extra') {
2633
+						continue;
2634
+					}
2635
+					?>
2636 2636
                     <input type="hidden" name="<?php echo $name; ?>" value="<?php echo $value; ?>"/>
2637 2637
                     <?php
2638
-                }
2639
-                // setup nonce_url
2640
-                wp_nonce_field($args['action'] . '_nonce', $args['action'] . '_nonce', false);
2641
-                ?>
2638
+				}
2639
+				// setup nonce_url
2640
+				wp_nonce_field($args['action'] . '_nonce', $args['action'] . '_nonce', false);
2641
+				?>
2642 2642
                 <select name="context">
2643 2643
                     <?php
2644
-                    $context_templates = $template_group_object->context_templates();
2645
-                    if (is_array($context_templates)) :
2646
-                        foreach ($context_templates as $context => $template_fields) :
2647
-                            $checked = ($context === $args['context']) ? 'selected="selected"' : '';
2648
-                            ?>
2644
+					$context_templates = $template_group_object->context_templates();
2645
+					if (is_array($context_templates)) :
2646
+						foreach ($context_templates as $context => $template_fields) :
2647
+							$checked = ($context === $args['context']) ? 'selected="selected"' : '';
2648
+							?>
2649 2649
                             <option value="<?php echo $context; ?>" <?php echo $checked; ?>>
2650 2650
                                 <?php echo $context_details[ $context ]['label']; ?>
2651 2651
                             </option>
2652 2652
                         <?php endforeach;
2653
-                    endif; ?>
2653
+					endif; ?>
2654 2654
                 </select>
2655 2655
                 <?php $button_text = sprintf(__('Switch %s', 'event_espresso'), ucwords($context_label['label'])); ?>
2656 2656
                 <input id="submit-msg-context-switcher-sbmt" class="button-secondary" type="submit"
@@ -2659,1925 +2659,1925 @@  discard block
 block discarded – undo
2659 2659
             <?php echo $args['extra']; ?>
2660 2660
         </div> <!-- end .ee-msg-switcher-container -->
2661 2661
         <?php
2662
-        $output = ob_get_contents();
2663
-        ob_clean();
2664
-        $this->_context_switcher = $output;
2665
-    }
2666
-
2667
-
2668
-    /**
2669
-     * utility for sanitizing new values coming in.
2670
-     * Note: this is only used when updating a context.
2671
-     *
2672
-     * @access protected
2673
-     *
2674
-     * @param int $index This helps us know which template field to select from the request array.
2675
-     *
2676
-     * @return array
2677
-     */
2678
-    protected function _set_message_template_column_values($index)
2679
-    {
2680
-        if (is_array($this->_req_data['MTP_template_fields'][ $index ]['content'])) {
2681
-            foreach ($this->_req_data['MTP_template_fields'][ $index ]['content'] as $field => $value) {
2682
-                $this->_req_data['MTP_template_fields'][ $index ]['content'][ $field ] = $value;
2683
-            }
2684
-        }
2685
-
2686
-
2687
-        $set_column_values = array(
2688
-            'MTP_ID'             => absint($this->_req_data['MTP_template_fields'][ $index ]['MTP_ID']),
2689
-            'GRP_ID'             => absint($this->_req_data['GRP_ID']),
2690
-            'MTP_user_id'        => absint($this->_req_data['MTP_user_id']),
2691
-            'MTP_messenger'      => strtolower($this->_req_data['MTP_messenger']),
2692
-            'MTP_message_type'   => strtolower($this->_req_data['MTP_message_type']),
2693
-            'MTP_template_field' => strtolower($this->_req_data['MTP_template_fields'][ $index ]['name']),
2694
-            'MTP_context'        => strtolower($this->_req_data['MTP_context']),
2695
-            'MTP_content'        => $this->_req_data['MTP_template_fields'][ $index ]['content'],
2696
-            'MTP_is_global'      => isset($this->_req_data['MTP_is_global'])
2697
-                ? absint($this->_req_data['MTP_is_global'])
2698
-                : 0,
2699
-            'MTP_is_override'    => isset($this->_req_data['MTP_is_override'])
2700
-                ? absint($this->_req_data['MTP_is_override'])
2701
-                : 0,
2702
-            'MTP_deleted'        => absint($this->_req_data['MTP_deleted']),
2703
-            'MTP_is_active'      => absint($this->_req_data['MTP_is_active']),
2704
-        );
2705
-
2706
-
2707
-        return $set_column_values;
2708
-    }
2709
-
2710
-
2711
-    protected function _insert_or_update_message_template($new = false)
2712
-    {
2713
-
2714
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2715
-        $success = 0;
2716
-        $override = false;
2717
-
2718
-        // setup notices description
2719
-        $messenger_slug = ! empty($this->_req_data['MTP_messenger']) ? $this->_req_data['MTP_messenger'] : '';
2720
-
2721
-        // need the message type and messenger objects to be able to use the labels for the notices
2722
-        $messenger_object = $this->_message_resource_manager->get_messenger($messenger_slug);
2723
-        $messenger_label = $messenger_object instanceof EE_messenger
2724
-            ? ucwords($messenger_object->label['singular'])
2725
-            : '';
2726
-
2727
-        $message_type_slug = ! empty($this->_req_data['MTP_message_type'])
2728
-            ? $this->_req_data['MTP_message_type']
2729
-            : '';
2730
-        $message_type_object = $this->_message_resource_manager->get_message_type($message_type_slug);
2731
-
2732
-        $message_type_label = $message_type_object instanceof EE_message_type
2733
-            ? ucwords($message_type_object->label['singular'])
2734
-            : '';
2735
-
2736
-        $context_slug = ! empty($this->_req_data['MTP_context'])
2737
-            ? $this->_req_data['MTP_context']
2738
-            : '';
2739
-        $context = ucwords(str_replace('_', ' ', $context_slug));
2740
-
2741
-        $item_desc = $messenger_label && $message_type_label
2742
-            ? $messenger_label . ' ' . $message_type_label . ' ' . $context . ' '
2743
-            : '';
2744
-        $item_desc .= 'Message Template';
2745
-        $query_args = array();
2746
-        $edit_array = array();
2747
-        $action_desc = '';
2748
-
2749
-        // if this is "new" then we need to generate the default contexts for the selected messenger/message_type for
2750
-        // user to edit.
2751
-        if ($new) {
2752
-            $GRP_ID = ! empty($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : 0;
2753
-            if ($edit_array = $this->_generate_new_templates($messenger_slug, $message_type_slug, $GRP_ID)) {
2754
-                if (empty($edit_array)) {
2755
-                    $success = 0;
2756
-                } else {
2757
-                    $success = 1;
2758
-                    $edit_array = $edit_array[0];
2759
-                    $query_args = array(
2760
-                        'id'      => $edit_array['GRP_ID'],
2761
-                        'context' => $edit_array['MTP_context'],
2762
-                        'action'  => 'edit_message_template',
2763
-                    );
2764
-                }
2765
-            }
2766
-            $action_desc = 'created';
2767
-        } else {
2768
-            $MTPG = EEM_Message_Template_Group::instance();
2769
-            $MTP = EEM_Message_Template::instance();
2770
-
2771
-
2772
-            // run update for each template field in displayed context
2773
-            if (! isset($this->_req_data['MTP_template_fields']) && empty($this->_req_data['MTP_template_fields'])) {
2774
-                EE_Error::add_error(
2775
-                    esc_html__(
2776
-                        'There was a problem saving the template fields from the form because I didn\'t receive any actual template field data.',
2777
-                        'event_espresso'
2778
-                    ),
2779
-                    __FILE__,
2780
-                    __FUNCTION__,
2781
-                    __LINE__
2782
-                );
2783
-                $success = 0;
2784
-            } else {
2785
-                // first validate all fields!
2786
-                // this filter allows client code to add its own validation to the template fields as well.
2787
-                // returning an empty array means everything passed validation.
2788
-                // errors in validation should be represented in an array with the following shape:
2789
-                // array(
2790
-                //   'fieldname' => array(
2791
-                //          'msg' => 'error message'
2792
-                //          'value' => 'value for field producing error'
2793
-                // )
2794
-                $custom_validation = (array) apply_filters(
2795
-                    'FHEE__Messages_Admin_Page___insert_or_update_message_template__validates',
2796
-                    array(),
2797
-                    $this->_req_data['MTP_template_fields'],
2798
-                    $context_slug,
2799
-                    $messenger_slug,
2800
-                    $message_type_slug
2801
-                );
2802
-
2803
-                $system_validation = $MTPG->validate(
2804
-                    $this->_req_data['MTP_template_fields'],
2805
-                    $context_slug,
2806
-                    $messenger_slug,
2807
-                    $message_type_slug
2808
-                );
2809
-
2810
-                $system_validation = ! is_array($system_validation) && $system_validation ? array()
2811
-                    : $system_validation;
2812
-                $validates = array_merge($custom_validation, $system_validation);
2813
-
2814
-                // if $validate returned error messages (i.e. is_array()) then we need to process them and setup an
2815
-                // appropriate response. HMM, dang this isn't correct, $validates will ALWAYS be an array.
2816
-                //  WE need to make sure there is no actual error messages in validates.
2817
-                if (is_array($validates) && ! empty($validates)) {
2818
-                    // add the transient so when the form loads we know which fields to highlight
2819
-                    $this->_add_transient('edit_message_template', $validates);
2820
-
2821
-                    $success = 0;
2822
-
2823
-                    // setup notices
2824
-                    foreach ($validates as $field => $error) {
2825
-                        if (isset($error['msg'])) {
2826
-                            EE_Error::add_error($error['msg'], __FILE__, __FUNCTION__, __LINE__);
2827
-                        }
2828
-                    }
2829
-                } else {
2830
-                    $set_column_values = array();
2831
-                    foreach ($this->_req_data['MTP_template_fields'] as $template_field => $content) {
2832
-                        $set_column_values = $this->_set_message_template_column_values($template_field);
2833
-
2834
-                        $where_cols_n_values = array(
2835
-                            'MTP_ID' => $this->_req_data['MTP_template_fields'][ $template_field ]['MTP_ID'],
2836
-                        );
2837
-                        // if they aren't allowed to use all JS, restrict them to just posty-y tags
2838
-                        if (! current_user_can('unfiltered_html')) {
2839
-                            if (is_array($set_column_values['MTP_content'])) {
2840
-                                foreach ($set_column_values['MTP_content'] as $key => $value) {
2841
-                                    // remove slashes so wp_kses works properly (its wp_kses_stripslashes() function
2842
-                                    // only removes slashes from double-quotes, so attributes using single quotes always
2843
-                                    // appear invalid.) But currently the models expect slashed data, so after wp_kses
2844
-                                    // runs we need to re-slash the data. Sheesh. See
2845
-                                    // https://events.codebasehq.com/projects/event-espresso/tickets/11211#update-47321587
2846
-                                    $set_column_values['MTP_content'][ $key ] = addslashes(
2847
-                                        wp_kses(
2848
-                                            stripslashes($value),
2849
-                                            wp_kses_allowed_html('post')
2850
-                                        )
2851
-                                    );
2852
-                                }
2853
-                            } else {
2854
-                                $set_column_values['MTP_content'] = wp_kses(
2855
-                                    $set_column_values['MTP_content'],
2856
-                                    wp_kses_allowed_html('post')
2857
-                                );
2858
-                            }
2859
-                        }
2860
-                        $message_template_fields = array(
2861
-                            'GRP_ID'             => $set_column_values['GRP_ID'],
2862
-                            'MTP_template_field' => $set_column_values['MTP_template_field'],
2863
-                            'MTP_context'        => $set_column_values['MTP_context'],
2864
-                            'MTP_content'        => $set_column_values['MTP_content'],
2865
-                        );
2866
-                        if ($updated = $MTP->update($message_template_fields, array($where_cols_n_values))) {
2867
-                            if ($updated === false) {
2868
-                                EE_Error::add_error(
2869
-                                    sprintf(
2870
-                                        esc_html__('%s field was NOT updated for some reason', 'event_espresso'),
2871
-                                        $template_field
2872
-                                    ),
2873
-                                    __FILE__,
2874
-                                    __FUNCTION__,
2875
-                                    __LINE__
2876
-                                );
2877
-                            } else {
2878
-                                $success = 1;
2879
-                            }
2880
-                        } else {
2881
-                            // only do this logic if we don't have a MTP_ID for this field
2882
-                            if (empty($this->_req_data['MTP_template_fields'][ $template_field ]['MTP_ID'])) {
2883
-                                // this has already been through the template field validator and sanitized, so it will be
2884
-                                // safe to insert this field.  Why insert?  This typically happens when we introduce a new
2885
-                                // message template field in a messenger/message type and existing users don't have the
2886
-                                // default setup for it.
2887
-                                // @link https://events.codebasehq.com/projects/event-espresso/tickets/9465
2888
-                                $updated = $MTP->insert($message_template_fields);
2889
-                                if (! $updated || is_wp_error($updated)) {
2890
-                                    EE_Error::add_error(
2891
-                                        sprintf(
2892
-                                            esc_html__('%s field could not be updated.', 'event_espresso'),
2893
-                                            $template_field
2894
-                                        ),
2895
-                                        __FILE__,
2896
-                                        __FUNCTION__,
2897
-                                        __LINE__
2898
-                                    );
2899
-                                    $success = 0;
2900
-                                } else {
2901
-                                    $success = 1;
2902
-                                }
2903
-                            }
2904
-                        }
2905
-                        $action_desc = 'updated';
2906
-                    }
2907
-
2908
-                    // we can use the last set_column_values for the MTPG update (because its the same for all of these specific MTPs)
2909
-                    $mtpg_fields = array(
2910
-                        'MTP_user_id'      => $set_column_values['MTP_user_id'],
2911
-                        'MTP_messenger'    => $set_column_values['MTP_messenger'],
2912
-                        'MTP_message_type' => $set_column_values['MTP_message_type'],
2913
-                        'MTP_is_global'    => $set_column_values['MTP_is_global'],
2914
-                        'MTP_is_override'  => $set_column_values['MTP_is_override'],
2915
-                        'MTP_deleted'      => $set_column_values['MTP_deleted'],
2916
-                        'MTP_is_active'    => $set_column_values['MTP_is_active'],
2917
-                        'MTP_name'         => ! empty($this->_req_data['ee_msg_non_global_fields']['MTP_name'])
2918
-                            ? $this->_req_data['ee_msg_non_global_fields']['MTP_name']
2919
-                            : '',
2920
-                        'MTP_description'  => ! empty($this->_req_data['ee_msg_non_global_fields']['MTP_description'])
2921
-                            ? $this->_req_data['ee_msg_non_global_fields']['MTP_description']
2922
-                            : '',
2923
-                    );
2924
-
2925
-                    $mtpg_where = array('GRP_ID' => $set_column_values['GRP_ID']);
2926
-                    $updated = $MTPG->update($mtpg_fields, array($mtpg_where));
2927
-
2928
-                    if ($updated === false) {
2929
-                        EE_Error::add_error(
2930
-                            sprintf(
2931
-                                esc_html__(
2932
-                                    'The Message Template Group (%d) was NOT updated for some reason',
2933
-                                    'event_espresso'
2934
-                                ),
2935
-                                $set_column_values['GRP_ID']
2936
-                            ),
2937
-                            __FILE__,
2938
-                            __FUNCTION__,
2939
-                            __LINE__
2940
-                        );
2941
-                    } else {
2942
-                        // k now we need to ensure the template_pack and template_variation fields are set.
2943
-                        $template_pack = ! empty($this->_req_data['MTP_template_pack'])
2944
-                            ? $this->_req_data['MTP_template_pack']
2945
-                            : 'default';
2946
-
2947
-                        $template_variation = ! empty($this->_req_data['MTP_template_variation'])
2948
-                            ? $this->_req_data['MTP_template_variation']
2949
-                            : 'default';
2950
-
2951
-                        $mtpg_obj = $MTPG->get_one_by_ID($set_column_values['GRP_ID']);
2952
-                        if ($mtpg_obj instanceof EE_Message_Template_Group) {
2953
-                            $mtpg_obj->set_template_pack_name($template_pack);
2954
-                            $mtpg_obj->set_template_pack_variation($template_variation);
2955
-                        }
2956
-                        $success = 1;
2957
-                    }
2958
-                }
2959
-            }
2960
-        }
2961
-
2962
-        // we return things differently if doing ajax
2963
-        if (defined('DOING_AJAX') && DOING_AJAX) {
2964
-            $this->_template_args['success'] = $success;
2965
-            $this->_template_args['error'] = ! $success ? true : false;
2966
-            $this->_template_args['content'] = '';
2967
-            $this->_template_args['data'] = array(
2968
-                'grpID'        => $edit_array['GRP_ID'],
2969
-                'templateName' => $edit_array['template_name'],
2970
-            );
2971
-            if ($success) {
2972
-                EE_Error::overwrite_success();
2973
-                EE_Error::add_success(
2974
-                    esc_html__(
2975
-                        'The new template has been created and automatically selected for this event.  You can edit the new template by clicking the edit button.  Note before this template is assigned to this event, the event must be saved.',
2976
-                        'event_espresso'
2977
-                    )
2978
-                );
2979
-            }
2980
-
2981
-            $this->_return_json();
2982
-        }
2983
-
2984
-
2985
-        // was a test send triggered?
2986
-        if (isset($this->_req_data['test_button'])) {
2987
-            EE_Error::overwrite_success();
2988
-            $this->_do_test_send($context_slug, $messenger_slug, $message_type_slug);
2989
-            $override = true;
2990
-        }
2991
-
2992
-        if (empty($query_args)) {
2993
-            $query_args = array(
2994
-                'id'      => $this->_req_data['GRP_ID'],
2995
-                'context' => $context_slug,
2996
-                'action'  => 'edit_message_template',
2997
-            );
2998
-        }
2999
-
3000
-        $this->_redirect_after_action($success, $item_desc, $action_desc, $query_args, $override);
3001
-    }
3002
-
3003
-
3004
-    /**
3005
-     * processes a test send request to do an actual messenger delivery test for the given message template being tested
3006
-     *
3007
-     * @param  string $context      what context being tested
3008
-     * @param  string $messenger    messenger being tested
3009
-     * @param  string $message_type message type being tested
3010
-     * @throws EE_Error
3011
-     * @throws InvalidArgumentException
3012
-     * @throws InvalidDataTypeException
3013
-     * @throws InvalidInterfaceException
3014
-     */
3015
-    protected function _do_test_send($context, $messenger, $message_type)
3016
-    {
3017
-        // set things up for preview
3018
-        $this->_req_data['messenger'] = $messenger;
3019
-        $this->_req_data['message_type'] = $message_type;
3020
-        $this->_req_data['context'] = $context;
3021
-        $this->_req_data['GRP_ID'] = isset($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : '';
3022
-        $active_messenger = $this->_message_resource_manager->get_active_messenger($messenger);
3023
-
3024
-        // let's save any existing fields that might be required by the messenger
3025
-        if (isset($this->_req_data['test_settings_fld'])
3026
-            && $active_messenger instanceof EE_messenger
3027
-            && apply_filters(
3028
-                'FHEE__Messages_Admin_Page__do_test_send__set_existing_test_settings',
3029
-                true,
3030
-                $this->_req_data['test_settings_fld'],
3031
-                $active_messenger
3032
-            )
3033
-        ) {
3034
-            $active_messenger->set_existing_test_settings($this->_req_data['test_settings_fld']);
3035
-        }
3036
-
3037
-        /**
3038
-         * Use filter to add additional controls on whether message can send or not
3039
-         */
3040
-        if (apply_filters(
3041
-            'FHEE__Messages_Admin_Page__do_test_send__can_send',
3042
-            true,
3043
-            $context,
3044
-            $this->_req_data,
3045
-            $messenger,
3046
-            $message_type
3047
-        )) {
3048
-            if (EEM_Event::instance()->count() > 0) {
3049
-                $success = $this->_preview_message(true);
3050
-                if ($success) {
3051
-                    EE_Error::add_success(__('Test message sent', 'event_espresso'));
3052
-                } else {
3053
-                    EE_Error::add_error(
3054
-                        esc_html__('The test message was not sent', 'event_espresso'),
3055
-                        __FILE__,
3056
-                        __FUNCTION__,
3057
-                        __LINE__
3058
-                    );
3059
-                }
3060
-            } else {
3061
-                $this->noEventsErrorMessage(true);
3062
-            }
3063
-        }
3064
-    }
3065
-
3066
-
3067
-    /**
3068
-     * _generate_new_templates
3069
-     * This will handle the messenger, message_type selection when "adding a new custom template" for an event and will
3070
-     * automatically create the defaults for the event.  The user would then be redirected to edit the default context
3071
-     * for the event.
3072
-     *
3073
-     *
3074
-     * @param  string $messenger     the messenger we are generating templates for
3075
-     * @param array   $message_types array of message types that the templates are generated for.
3076
-     * @param int     $GRP_ID        If this is a custom template being generated then a GRP_ID needs to be included to
3077
-     *                               indicate the message_template_group being used as the base.
3078
-     *
3079
-     * @param bool    $global
3080
-     *
3081
-     * @return array|bool array of data required for the redirect to the correct edit page or bool if
3082
-     *                               encountering problems.
3083
-     * @throws EE_Error
3084
-     */
3085
-    protected function _generate_new_templates($messenger, $message_types, $GRP_ID = 0, $global = false)
3086
-    {
3087
-
3088
-        // if no $message_types are given then that's okay... this may be a messenger that just adds shortcodes, so we
3089
-        // just don't generate any templates.
3090
-        if (empty($message_types)) {
3091
-            return true;
3092
-        }
3093
-
3094
-        return EEH_MSG_Template::generate_new_templates($messenger, $message_types, $GRP_ID, $global);
3095
-    }
3096
-
3097
-
3098
-    /**
3099
-     * [_trash_or_restore_message_template]
3100
-     *
3101
-     * @param  boolean $trash whether to move an item to trash/restore (TRUE) or restore it (FALSE)
3102
-     * @param boolean  $all   whether this is going to trash/restore all contexts within a template group (TRUE) OR just
3103
-     *                        an individual context (FALSE).
3104
-     * @return void
3105
-     * @throws EE_Error
3106
-     * @throws InvalidArgumentException
3107
-     * @throws InvalidDataTypeException
3108
-     * @throws InvalidInterfaceException
3109
-     */
3110
-    protected function _trash_or_restore_message_template($trash = true, $all = false)
3111
-    {
3112
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3113
-        $MTP = EEM_Message_Template_Group::instance();
3114
-
3115
-        $success = 1;
3116
-
3117
-        // incoming GRP_IDs
3118
-        if ($all) {
3119
-            // Checkboxes
3120
-            if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3121
-                // if array has more than one element then success message should be plural.
3122
-                // todo: what about nonce?
3123
-                $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3124
-
3125
-                // cycle through checkboxes
3126
-                while (list($GRP_ID, $value) = each($this->_req_data['checkbox'])) {
3127
-                    $trashed_or_restored = $trash ? $MTP->delete_by_ID($GRP_ID) : $MTP->restore_by_ID($GRP_ID);
3128
-                    if (! $trashed_or_restored) {
3129
-                        $success = 0;
3130
-                    }
3131
-                }
3132
-            } else {
3133
-                // grab single GRP_ID and handle
3134
-                $GRP_ID = isset($this->_req_data['id']) ? absint($this->_req_data['id']) : 0;
3135
-                if (! empty($GRP_ID)) {
3136
-                    $trashed_or_restored = $trash ? $MTP->delete_by_ID($GRP_ID) : $MTP->restore_by_ID($GRP_ID);
3137
-                    if (! $trashed_or_restored) {
3138
-                        $success = 0;
3139
-                    }
3140
-                } else {
3141
-                    $success = 0;
3142
-                }
3143
-            }
3144
-        }
3145
-
3146
-        $action_desc = $trash
3147
-            ? esc_html__('moved to the trash', 'event_espresso')
3148
-            : esc_html__('restored', 'event_espresso');
3149
-
3150
-        $action_desc = ! empty($this->_req_data['template_switch']) ? esc_html__('switched', 'event_espresso') : $action_desc;
3151
-
3152
-        $item_desc = $all ? _n(
3153
-            'Message Template Group',
3154
-            'Message Template Groups',
3155
-            $success,
3156
-            'event_espresso'
3157
-        ) : _n('Message Template Context', 'Message Template Contexts', $success, 'event_espresso');
3158
-
3159
-        $item_desc = ! empty($this->_req_data['template_switch']) ? _n(
3160
-            'template',
3161
-            'templates',
3162
-            $success,
3163
-            'event_espresso'
3164
-        ) : $item_desc;
3165
-
3166
-        $this->_redirect_after_action($success, $item_desc, $action_desc, array());
3167
-    }
3168
-
3169
-
3170
-    /**
3171
-     * [_delete_message_template]
3172
-     * NOTE: this handles not only the deletion of the groups but also all the templates belonging to that group.
3173
-     *
3174
-     * @return void
3175
-     * @throws EE_Error
3176
-     * @throws InvalidArgumentException
3177
-     * @throws InvalidDataTypeException
3178
-     * @throws InvalidInterfaceException
3179
-     */
3180
-    protected function _delete_message_template()
3181
-    {
3182
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3183
-
3184
-        // checkboxes
3185
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3186
-            // if array has more than one element then success message should be plural
3187
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3188
-
3189
-            // cycle through bulk action checkboxes
3190
-            while (list($GRP_ID, $value) = each($this->_req_data['checkbox'])) {
3191
-                $success = $this->_delete_mtp_permanently($GRP_ID);
3192
-            }
3193
-        } else {
3194
-            // grab single grp_id and delete
3195
-            $GRP_ID = absint($this->_req_data['id']);
3196
-            $success = $this->_delete_mtp_permanently($GRP_ID);
3197
-        }
3198
-
3199
-        $this->_redirect_after_action($success, 'Message Templates', 'deleted', array());
3200
-    }
3201
-
3202
-
3203
-    /**
3204
-     * helper for permanently deleting a mtP group and all related message_templates
3205
-     *
3206
-     * @param  int  $GRP_ID        The group being deleted
3207
-     * @param  bool $include_group whether to delete the Message Template Group as well.
3208
-     * @return bool boolean to indicate the success of the deletes or not.
3209
-     * @throws EE_Error
3210
-     * @throws InvalidArgumentException
3211
-     * @throws InvalidDataTypeException
3212
-     * @throws InvalidInterfaceException
3213
-     */
3214
-    private function _delete_mtp_permanently($GRP_ID, $include_group = true)
3215
-    {
3216
-        $success = 1;
3217
-        $MTPG = EEM_Message_Template_Group::instance();
3218
-        // first let's GET this group
3219
-        $MTG = $MTPG->get_one_by_ID($GRP_ID);
3220
-        // then delete permanently all the related Message Templates
3221
-        $deleted = $MTG->delete_related_permanently('Message_Template');
3222
-
3223
-        if ($deleted === 0) {
3224
-            $success = 0;
3225
-        }
3226
-
3227
-        // now delete permanently this particular group
3228
-
3229
-        if ($include_group && ! $MTG->delete_permanently()) {
3230
-            $success = 0;
3231
-        }
3232
-
3233
-        return $success;
3234
-    }
3235
-
3236
-
3237
-    /**
3238
-     *    _learn_more_about_message_templates_link
3239
-     *
3240
-     * @access protected
3241
-     * @return string
3242
-     */
3243
-    protected function _learn_more_about_message_templates_link()
3244
-    {
3245
-        return '<a class="hidden" style="margin:0 20px; cursor:pointer; font-size:12px;" >'
3246
-               . esc_html__('learn more about how message templates works', 'event_espresso')
3247
-               . '</a>';
3248
-    }
3249
-
3250
-
3251
-    /**
3252
-     * Used for setting up messenger/message type activation.  This loads up the initial view.  The rest is handled by
3253
-     * ajax and other routes.
3254
-     *
3255
-     * @return void
3256
-     * @throws DomainException
3257
-     */
3258
-    protected function _settings()
3259
-    {
3260
-
3261
-
3262
-        $this->_set_m_mt_settings();
3263
-
3264
-        $selected_messenger = isset($this->_req_data['selected_messenger'])
3265
-            ? $this->_req_data['selected_messenger']
3266
-            : 'email';
3267
-
3268
-        // let's setup the messenger tabs
3269
-        $this->_template_args['admin_page_header'] = EEH_Tabbed_Content::tab_text_links(
3270
-            $this->_m_mt_settings['messenger_tabs'],
3271
-            'messenger_links',
3272
-            '|',
3273
-            $selected_messenger
3274
-        );
3275
-        $this->_template_args['before_admin_page_content'] = '<div class="ui-widget ui-helper-clearfix">';
3276
-        $this->_template_args['after_admin_page_content'] = '</div><!-- end .ui-widget -->';
3277
-
3278
-        $this->display_admin_page_with_sidebar();
3279
-    }
3280
-
3281
-
3282
-    /**
3283
-     * This sets the $_m_mt_settings property for when needed (used on the Messages settings page)
3284
-     *
3285
-     * @access protected
3286
-     * @return void
3287
-     * @throws DomainException
3288
-     */
3289
-    protected function _set_m_mt_settings()
3290
-    {
3291
-        // first if this is already set then lets get out no need to regenerate data.
3292
-        if (! empty($this->_m_mt_settings)) {
3293
-            return;
3294
-        }
3295
-
3296
-        // get all installed messengers and message_types
3297
-        /** @type EE_messenger[] $messengers */
3298
-        $messengers = $this->_message_resource_manager->installed_messengers();
3299
-        /** @type EE_message_type[] $message_types */
3300
-        $message_types = $this->_message_resource_manager->installed_message_types();
3301
-
3302
-
3303
-        // assemble the array for the _tab_text_links helper
3304
-
3305
-        foreach ($messengers as $messenger) {
3306
-            $this->_m_mt_settings['messenger_tabs'][ $messenger->name ] = array(
3307
-                'label' => ucwords($messenger->label['singular']),
3308
-                'class' => $this->_message_resource_manager->is_messenger_active($messenger->name)
3309
-                    ? 'messenger-active'
3310
-                    : '',
3311
-                'href'  => $messenger->name,
3312
-                'title' => esc_html__('Modify this Messenger', 'event_espresso'),
3313
-                'slug'  => $messenger->name,
3314
-                'obj'   => $messenger,
3315
-            );
3316
-
3317
-
3318
-            $message_types_for_messenger = $messenger->get_valid_message_types();
3319
-
3320
-            foreach ($message_types as $message_type) {
3321
-                // first we need to verify that this message type is valid with this messenger. Cause if it isn't then
3322
-                // it shouldn't show in either the inactive OR active metabox.
3323
-                if (! in_array($message_type->name, $message_types_for_messenger, true)) {
3324
-                    continue;
3325
-                }
3326
-
3327
-                $a_or_i = $this->_message_resource_manager->is_message_type_active_for_messenger(
3328
-                    $messenger->name,
3329
-                    $message_type->name
3330
-                )
3331
-                    ? 'active'
3332
-                    : 'inactive';
3333
-
3334
-                $this->_m_mt_settings['message_type_tabs'][ $messenger->name ][ $a_or_i ][ $message_type->name ] = array(
3335
-                    'label'    => ucwords($message_type->label['singular']),
3336
-                    'class'    => 'message-type-' . $a_or_i,
3337
-                    'slug_id'  => $message_type->name . '-messagetype-' . $messenger->name,
3338
-                    'mt_nonce' => wp_create_nonce($message_type->name . '_nonce'),
3339
-                    'href'     => 'espresso_' . $message_type->name . '_message_type_settings',
3340
-                    'title'    => $a_or_i === 'active'
3341
-                        ? esc_html__('Drag this message type to the Inactive window to deactivate', 'event_espresso')
3342
-                        : esc_html__('Drag this message type to the messenger to activate', 'event_espresso'),
3343
-                    'content'  => $a_or_i === 'active'
3344
-                        ? $this->_message_type_settings_content($message_type, $messenger, true)
3345
-                        : $this->_message_type_settings_content($message_type, $messenger),
3346
-                    'slug'     => $message_type->name,
3347
-                    'active'   => $a_or_i === 'active',
3348
-                    'obj'      => $message_type,
3349
-                );
3350
-            }
3351
-        }
3352
-    }
3353
-
3354
-
3355
-    /**
3356
-     * This just prepares the content for the message type settings
3357
-     *
3358
-     * @param  EE_message_type $message_type The message type object
3359
-     * @param  EE_messenger    $messenger    The messenger object
3360
-     * @param  boolean         $active       Whether the message type is active or not
3361
-     * @return string html output for the content
3362
-     * @throws DomainException
3363
-     */
3364
-    protected function _message_type_settings_content($message_type, $messenger, $active = false)
3365
-    {
3366
-        // get message type fields
3367
-        $fields = $message_type->get_admin_settings_fields();
3368
-        $settings_template_args['template_form_fields'] = '';
3369
-
3370
-        if (! empty($fields) && $active) {
3371
-            $existing_settings = $message_type->get_existing_admin_settings($messenger->name);
3372
-            foreach ($fields as $fldname => $fldprops) {
3373
-                $field_id = $messenger->name . '-' . $message_type->name . '-' . $fldname;
3374
-                $template_form_field[ $field_id ] = array(
3375
-                    'name'       => 'message_type_settings[' . $fldname . ']',
3376
-                    'label'      => $fldprops['label'],
3377
-                    'input'      => $fldprops['field_type'],
3378
-                    'type'       => $fldprops['value_type'],
3379
-                    'required'   => $fldprops['required'],
3380
-                    'validation' => $fldprops['validation'],
3381
-                    'value'      => isset($existing_settings[ $fldname ])
3382
-                        ? $existing_settings[ $fldname ]
3383
-                        : $fldprops['default'],
3384
-                    'options'    => isset($fldprops['options'])
3385
-                        ? $fldprops['options']
3386
-                        : array(),
3387
-                    'default'    => isset($existing_settings[ $fldname ])
3388
-                        ? $existing_settings[ $fldname ]
3389
-                        : $fldprops['default'],
3390
-                    'css_class'  => 'no-drag',
3391
-                    'format'     => $fldprops['format'],
3392
-                );
3393
-            }
3394
-
3395
-
3396
-            $settings_template_args['template_form_fields'] = ! empty($template_form_field)
3397
-                ? $this->_generate_admin_form_fields(
3398
-                    $template_form_field,
3399
-                    'string',
3400
-                    'ee_mt_activate_form'
3401
-                )
3402
-                : '';
3403
-        }
3404
-
3405
-        $settings_template_args['description'] = $message_type->description;
3406
-        // we also need some hidden fields
3407
-        $settings_template_args['hidden_fields'] = array(
3408
-            'message_type_settings[messenger]'    => array(
3409
-                'type'  => 'hidden',
3410
-                'value' => $messenger->name,
3411
-            ),
3412
-            'message_type_settings[message_type]' => array(
3413
-                'type'  => 'hidden',
3414
-                'value' => $message_type->name,
3415
-            ),
3416
-            'type'                                => array(
3417
-                'type'  => 'hidden',
3418
-                'value' => 'message_type',
3419
-            ),
3420
-        );
3421
-
3422
-        $settings_template_args['hidden_fields'] = $this->_generate_admin_form_fields(
3423
-            $settings_template_args['hidden_fields'],
3424
-            'array'
3425
-        );
3426
-        $settings_template_args['show_form'] = empty($settings_template_args['template_form_fields'])
3427
-            ? ' hidden'
3428
-            : '';
3429
-
3430
-
3431
-        $template = EE_MSG_TEMPLATE_PATH . 'ee_msg_mt_settings_content.template.php';
3432
-        $content = EEH_Template::display_template($template, $settings_template_args, true);
3433
-
3434
-        return $content;
3435
-    }
3436
-
3437
-
3438
-    /**
3439
-     * Generate all the metaboxes for the message types and register them for the messages settings page.
3440
-     *
3441
-     * @access protected
3442
-     * @return void
3443
-     * @throws DomainException
3444
-     */
3445
-    protected function _messages_settings_metaboxes()
3446
-    {
3447
-        $this->_set_m_mt_settings();
3448
-        $m_boxes = $mt_boxes = array();
3449
-        $m_template_args = $mt_template_args = array();
3450
-
3451
-        $selected_messenger = isset($this->_req_data['selected_messenger'])
3452
-            ? $this->_req_data['selected_messenger']
3453
-            : 'email';
3454
-
3455
-        if (isset($this->_m_mt_settings['messenger_tabs'])) {
3456
-            foreach ($this->_m_mt_settings['messenger_tabs'] as $messenger => $tab_array) {
3457
-                $hide_on_message = $this->_message_resource_manager->is_messenger_active($messenger) ? '' : 'hidden';
3458
-                $hide_off_message = $this->_message_resource_manager->is_messenger_active($messenger) ? 'hidden' : '';
3459
-                // messenger meta boxes
3460
-                $active = $selected_messenger === $messenger;
3461
-                $active_mt_tabs = isset(
3462
-                    $this->_m_mt_settings['message_type_tabs'][ $messenger ]['active']
3463
-                )
3464
-                    ? $this->_m_mt_settings['message_type_tabs'][ $messenger ]['active']
3465
-                    : '';
3466
-                $m_boxes[ $messenger . '_a_box' ] = sprintf(
3467
-                    esc_html__('%s Settings', 'event_espresso'),
3468
-                    $tab_array['label']
3469
-                );
3470
-                $m_template_args[ $messenger . '_a_box' ] = array(
3471
-                    'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3472
-                    'inactive_message_types' => isset(
3473
-                        $this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3474
-                    )
3475
-                        ? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3476
-                        : '',
3477
-                    'content'                => $this->_get_messenger_box_content($tab_array['obj']),
3478
-                    'hidden'                 => $active ? '' : ' hidden',
3479
-                    'hide_on_message'        => $hide_on_message,
3480
-                    'messenger'              => $messenger,
3481
-                    'active'                 => $active,
3482
-                );
3483
-                // message type meta boxes
3484
-                // (which is really just the inactive container for each messenger
3485
-                // showing inactive message types for that messenger)
3486
-                $mt_boxes[ $messenger . '_i_box' ] = esc_html__('Inactive Message Types', 'event_espresso');
3487
-                $mt_template_args[ $messenger . '_i_box' ] = array(
3488
-                    'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3489
-                    'inactive_message_types' => isset(
3490
-                        $this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3491
-                    )
3492
-                        ? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3493
-                        : '',
3494
-                    'hidden'                 => $active ? '' : ' hidden',
3495
-                    'hide_on_message'        => $hide_on_message,
3496
-                    'hide_off_message'       => $hide_off_message,
3497
-                    'messenger'              => $messenger,
3498
-                    'active'                 => $active,
3499
-                );
3500
-            }
3501
-        }
3502
-
3503
-
3504
-        // register messenger metaboxes
3505
-        $m_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_mt_meta_box.template.php';
3506
-        foreach ($m_boxes as $box => $label) {
3507
-            $callback_args = array('template_path' => $m_template_path, 'template_args' => $m_template_args[ $box ]);
3508
-            $msgr = str_replace('_a_box', '', $box);
3509
-            add_meta_box(
3510
-                'espresso_' . $msgr . '_settings',
3511
-                $label,
3512
-                function ($post, $metabox) {
3513
-                    echo EEH_Template::display_template(
3514
-                        $metabox["args"]["template_path"],
3515
-                        $metabox["args"]["template_args"],
3516
-                        true
3517
-                    );
3518
-                },
3519
-                $this->_current_screen->id,
3520
-                'normal',
3521
-                'high',
3522
-                $callback_args
3523
-            );
3524
-        }
3525
-
3526
-        // register message type metaboxes
3527
-        $mt_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_meta_box.template.php';
3528
-        foreach ($mt_boxes as $box => $label) {
3529
-            $callback_args = array(
3530
-                'template_path' => $mt_template_path,
3531
-                'template_args' => $mt_template_args[ $box ],
3532
-            );
3533
-            $mt = str_replace('_i_box', '', $box);
3534
-            add_meta_box(
3535
-                'espresso_' . $mt . '_inactive_mts',
3536
-                $label,
3537
-                function ($post, $metabox) {
3538
-                    echo EEH_Template::display_template(
3539
-                        $metabox["args"]["template_path"],
3540
-                        $metabox["args"]["template_args"],
3541
-                        true
3542
-                    );
3543
-                },
3544
-                $this->_current_screen->id,
3545
-                'side',
3546
-                'high',
3547
-                $callback_args
3548
-            );
3549
-        }
3550
-
3551
-        // register metabox for global messages settings but only when on the main site.  On single site installs this
3552
-        // will always result in the metabox showing, on multisite installs the metabox will only show on the main site.
3553
-        if (is_main_site()) {
3554
-            add_meta_box(
3555
-                'espresso_global_message_settings',
3556
-                esc_html__('Global Message Settings', 'event_espresso'),
3557
-                array($this, 'global_messages_settings_metabox_content'),
3558
-                $this->_current_screen->id,
3559
-                'normal',
3560
-                'low',
3561
-                array()
3562
-            );
3563
-        }
3564
-    }
3565
-
3566
-
3567
-    /**
3568
-     *  This generates the content for the global messages settings metabox.
3569
-     *
3570
-     * @return string
3571
-     * @throws EE_Error
3572
-     * @throws InvalidArgumentException
3573
-     * @throws ReflectionException
3574
-     * @throws InvalidDataTypeException
3575
-     * @throws InvalidInterfaceException
3576
-     */
3577
-    public function global_messages_settings_metabox_content()
3578
-    {
3579
-        $form = $this->_generate_global_settings_form();
3580
-        echo $form->form_open(
3581
-            $this->add_query_args_and_nonce(array('action' => 'update_global_settings'), EE_MSG_ADMIN_URL),
3582
-            'POST'
3583
-        )
3584
-             . $form->get_html()
3585
-             . $form->form_close();
3586
-    }
3587
-
3588
-
3589
-    /**
3590
-     * This generates and returns the form object for the global messages settings.
3591
-     *
3592
-     * @return EE_Form_Section_Proper
3593
-     * @throws EE_Error
3594
-     * @throws InvalidArgumentException
3595
-     * @throws ReflectionException
3596
-     * @throws InvalidDataTypeException
3597
-     * @throws InvalidInterfaceException
3598
-     */
3599
-    protected function _generate_global_settings_form()
3600
-    {
3601
-        EE_Registry::instance()->load_helper('HTML');
3602
-        /** @var EE_Network_Core_Config $network_config */
3603
-        $network_config = EE_Registry::instance()->NET_CFG->core;
3604
-
3605
-        return new EE_Form_Section_Proper(
3606
-            array(
3607
-                'name'            => 'global_messages_settings',
3608
-                'html_id'         => 'global_messages_settings',
3609
-                'html_class'      => 'form-table',
3610
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
3611
-                'subsections'     => apply_filters(
3612
-                    'FHEE__Messages_Admin_Page__global_messages_settings_metabox_content__form_subsections',
3613
-                    array(
3614
-                        'do_messages_on_same_request' => new EE_Select_Input(
3615
-                            array(
3616
-                                true  => esc_html__("On the same request", "event_espresso"),
3617
-                                false => esc_html__("On a separate request", "event_espresso"),
3618
-                            ),
3619
-                            array(
3620
-                                'default'         => $network_config->do_messages_on_same_request,
3621
-                                'html_label_text' => esc_html__(
3622
-                                    'Generate and send all messages:',
3623
-                                    'event_espresso'
3624
-                                ),
3625
-                                'html_help_text'  => esc_html__(
3626
-                                    'By default the messages system uses a more efficient means of processing messages on separate requests and utilizes the wp-cron scheduling system.  This makes things execute faster for people registering for your events.  However, if the wp-cron system is disabled on your site and there is no alternative in place, then you can change this so messages are always executed on the same request.',
3627
-                                    'event_espresso'
3628
-                                ),
3629
-                            )
3630
-                        ),
3631
-                        'delete_threshold'            => new EE_Select_Input(
3632
-                            array(
3633
-                                0  => esc_html__('Forever', 'event_espresso'),
3634
-                                3  => esc_html__('3 Months', 'event_espresso'),
3635
-                                6  => esc_html__('6 Months', 'event_espresso'),
3636
-                                9  => esc_html__('9 Months', 'event_espresso'),
3637
-                                12 => esc_html__('12 Months', 'event_espresso'),
3638
-                                24 => esc_html__('24 Months', 'event_espresso'),
3639
-                                36 => esc_html__('36 Months', 'event_espresso'),
3640
-                            ),
3641
-                            array(
3642
-                                'default'         => EE_Registry::instance()->CFG->messages->delete_threshold,
3643
-                                'html_label_text' => esc_html__('Cleanup of old messages:', 'event_espresso'),
3644
-                                'html_help_text'  => esc_html__(
3645
-                                    'You can control how long a record of processed messages is kept via this option.',
3646
-                                    'event_espresso'
3647
-                                ),
3648
-                            )
3649
-                        ),
3650
-                        'update_settings'             => new EE_Submit_Input(
3651
-                            array(
3652
-                                'default'         => esc_html__('Update', 'event_espresso'),
3653
-                                'html_label_text' => '&nbsp',
3654
-                            )
3655
-                        ),
3656
-                    )
3657
-                ),
3658
-            )
3659
-        );
3660
-    }
3661
-
3662
-
3663
-    /**
3664
-     * This handles updating the global settings set on the admin page.
3665
-     *
3666
-     * @throws EE_Error
3667
-     * @throws InvalidDataTypeException
3668
-     * @throws InvalidInterfaceException
3669
-     * @throws InvalidArgumentException
3670
-     * @throws ReflectionException
3671
-     */
3672
-    protected function _update_global_settings()
3673
-    {
3674
-        /** @var EE_Network_Core_Config $network_config */
3675
-        $network_config = EE_Registry::instance()->NET_CFG->core;
3676
-        $messages_config = EE_Registry::instance()->CFG->messages;
3677
-        $form = $this->_generate_global_settings_form();
3678
-        if ($form->was_submitted()) {
3679
-            $form->receive_form_submission();
3680
-            if ($form->is_valid()) {
3681
-                $valid_data = $form->valid_data();
3682
-                foreach ($valid_data as $property => $value) {
3683
-                    $setter = 'set_' . $property;
3684
-                    if (method_exists($network_config, $setter)) {
3685
-                        $network_config->{$setter}($value);
3686
-                    } elseif (property_exists($network_config, $property)
3687
-                        && $network_config->{$property} !== $value
3688
-                    ) {
3689
-                        $network_config->{$property} = $value;
3690
-                    } elseif (property_exists($messages_config, $property)
3691
-                        && $messages_config->{$property} !== $value
3692
-                    ) {
3693
-                        $messages_config->{$property} = $value;
3694
-                    }
3695
-                }
3696
-                // only update if the form submission was valid!
3697
-                EE_Registry::instance()->NET_CFG->update_config(true, false);
3698
-                EE_Registry::instance()->CFG->update_espresso_config();
3699
-                EE_Error::overwrite_success();
3700
-                EE_Error::add_success(__('Global message settings were updated', 'event_espresso'));
3701
-            }
3702
-        }
3703
-        $this->_redirect_after_action(0, '', '', array('action' => 'settings'), true);
3704
-    }
3705
-
3706
-
3707
-    /**
3708
-     * this prepares the messenger tabs that can be dragged in and out of messenger boxes to activate/deactivate
3709
-     *
3710
-     * @param  array $tab_array This is an array of message type tab details used to generate the tabs
3711
-     * @return string html formatted tabs
3712
-     * @throws DomainException
3713
-     */
3714
-    protected function _get_mt_tabs($tab_array)
3715
-    {
3716
-        $tab_array = (array) $tab_array;
3717
-        $template = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_mt_settings_tab_item.template.php';
3718
-        $tabs = '';
3719
-
3720
-        foreach ($tab_array as $tab) {
3721
-            $tabs .= EEH_Template::display_template($template, $tab, true);
3722
-        }
3723
-
3724
-        return $tabs;
3725
-    }
3726
-
3727
-
3728
-    /**
3729
-     * This prepares the content of the messenger meta box admin settings
3730
-     *
3731
-     * @param  EE_messenger $messenger The messenger we're setting up content for
3732
-     * @return string html formatted content
3733
-     * @throws DomainException
3734
-     */
3735
-    protected function _get_messenger_box_content(EE_messenger $messenger)
3736
-    {
3737
-
3738
-        $fields = $messenger->get_admin_settings_fields();
3739
-        $settings_template_args['template_form_fields'] = '';
3740
-
3741
-        // is $messenger active?
3742
-        $settings_template_args['active'] = $this->_message_resource_manager->is_messenger_active($messenger->name);
3743
-
3744
-
3745
-        if (! empty($fields)) {
3746
-            $existing_settings = $messenger->get_existing_admin_settings();
3747
-
3748
-            foreach ($fields as $fldname => $fldprops) {
3749
-                $field_id = $messenger->name . '-' . $fldname;
3750
-                $template_form_field[ $field_id ] = array(
3751
-                    'name'       => 'messenger_settings[' . $field_id . ']',
3752
-                    'label'      => $fldprops['label'],
3753
-                    'input'      => $fldprops['field_type'],
3754
-                    'type'       => $fldprops['value_type'],
3755
-                    'required'   => $fldprops['required'],
3756
-                    'validation' => $fldprops['validation'],
3757
-                    'value'      => isset($existing_settings[ $field_id ])
3758
-                        ? $existing_settings[ $field_id ]
3759
-                        : $fldprops['default'],
3760
-                    'css_class'  => '',
3761
-                    'format'     => $fldprops['format'],
3762
-                );
3763
-            }
3764
-
3765
-
3766
-            $settings_template_args['template_form_fields'] = ! empty($template_form_field)
3767
-                ? $this->_generate_admin_form_fields($template_form_field, 'string', 'ee_m_activate_form')
3768
-                : '';
3769
-        }
3770
-
3771
-        // we also need some hidden fields
3772
-        $settings_template_args['hidden_fields'] = array(
3773
-            'messenger_settings[messenger]' => array(
3774
-                'type'  => 'hidden',
3775
-                'value' => $messenger->name,
3776
-            ),
3777
-            'type'                          => array(
3778
-                'type'  => 'hidden',
3779
-                'value' => 'messenger',
3780
-            ),
3781
-        );
3782
-
3783
-        // make sure any active message types that are existing are included in the hidden fields
3784
-        if (isset($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'])) {
3785
-            foreach ($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'] as $mt => $values) {
3786
-                $settings_template_args['hidden_fields'][ 'messenger_settings[message_types][' . $mt . ']' ] = array(
3787
-                    'type'  => 'hidden',
3788
-                    'value' => $mt,
3789
-                );
3790
-            }
3791
-        }
3792
-        $settings_template_args['hidden_fields'] = $this->_generate_admin_form_fields(
3793
-            $settings_template_args['hidden_fields'],
3794
-            'array'
3795
-        );
3796
-        $active = $this->_message_resource_manager->is_messenger_active($messenger->name);
3797
-
3798
-        $settings_template_args['messenger'] = $messenger->name;
3799
-        $settings_template_args['description'] = $messenger->description;
3800
-        $settings_template_args['show_hide_edit_form'] = $active ? '' : ' hidden';
3801
-
3802
-
3803
-        $settings_template_args['show_hide_edit_form'] = $this->_message_resource_manager->is_messenger_active(
3804
-            $messenger->name
3805
-        )
3806
-            ? $settings_template_args['show_hide_edit_form']
3807
-            : ' hidden';
3808
-
3809
-        $settings_template_args['show_hide_edit_form'] = empty($settings_template_args['template_form_fields'])
3810
-            ? ' hidden'
3811
-            : $settings_template_args['show_hide_edit_form'];
3812
-
3813
-
3814
-        $settings_template_args['on_off_action'] = $active ? 'messenger-off' : 'messenger-on';
3815
-        $settings_template_args['nonce'] = wp_create_nonce('activate_' . $messenger->name . '_toggle_nonce');
3816
-        $settings_template_args['on_off_status'] = $active ? true : false;
3817
-        $template = EE_MSG_TEMPLATE_PATH . 'ee_msg_m_settings_content.template.php';
3818
-        $content = EEH_Template::display_template(
3819
-            $template,
3820
-            $settings_template_args,
3821
-            true
3822
-        );
3823
-
3824
-        return $content;
3825
-    }
3826
-
3827
-
3828
-    /**
3829
-     * used by ajax on the messages settings page to activate|deactivate the messenger
3830
-     *
3831
-     * @throws DomainException
3832
-     * @throws EE_Error
3833
-     * @throws InvalidDataTypeException
3834
-     * @throws InvalidInterfaceException
3835
-     * @throws InvalidArgumentException
3836
-     * @throws ReflectionException
3837
-     */
3838
-    public function activate_messenger_toggle()
3839
-    {
3840
-        $success = true;
3841
-        $this->_prep_default_response_for_messenger_or_message_type_toggle();
3842
-        // let's check that we have required data
3843
-        if (! isset($this->_req_data['messenger'])) {
3844
-            EE_Error::add_error(
3845
-                esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
3846
-                __FILE__,
3847
-                __FUNCTION__,
3848
-                __LINE__
3849
-            );
3850
-            $success = false;
3851
-        }
3852
-
3853
-        // do a nonce check here since we're not arriving via a normal route
3854
-        $nonce = isset($this->_req_data['activate_nonce'])
3855
-            ? sanitize_text_field($this->_req_data['activate_nonce'])
3856
-            : '';
3857
-        $nonce_ref = 'activate_' . $this->_req_data['messenger'] . '_toggle_nonce';
3858
-
3859
-        $this->_verify_nonce($nonce, $nonce_ref);
3860
-
3861
-
3862
-        if (! isset($this->_req_data['status'])) {
3863
-            EE_Error::add_error(
3864
-                esc_html__(
3865
-                    'Messenger status needed to know whether activation or deactivation is happening. No status is given',
3866
-                    'event_espresso'
3867
-                ),
3868
-                __FILE__,
3869
-                __FUNCTION__,
3870
-                __LINE__
3871
-            );
3872
-            $success = false;
3873
-        }
3874
-
3875
-        // do check to verify we have a valid status.
3876
-        $status = $this->_req_data['status'];
3877
-
3878
-        if ($status !== 'off' && $status !== 'on') {
3879
-            EE_Error::add_error(
3880
-                sprintf(
3881
-                    esc_html__('The given status (%s) is not valid. Must be "off" or "on"', 'event_espresso'),
3882
-                    $this->_req_data['status']
3883
-                ),
3884
-                __FILE__,
3885
-                __FUNCTION__,
3886
-                __LINE__
3887
-            );
3888
-            $success = false;
3889
-        }
3890
-
3891
-        if ($success) {
3892
-            // made it here?  Stop dawdling then!!
3893
-            $success = $status === 'off'
3894
-                ? $this->_deactivate_messenger($this->_req_data['messenger'])
3895
-                : $this->_activate_messenger($this->_req_data['messenger']);
3896
-        }
3897
-
3898
-        $this->_template_args['success'] = $success;
3899
-
3900
-        // no special instructions so let's just do the json return (which should automatically do all the special stuff).
3901
-        $this->_return_json();
3902
-    }
3903
-
3904
-
3905
-    /**
3906
-     * used by ajax from the messages settings page to activate|deactivate a message type
3907
-     *
3908
-     * @throws DomainException
3909
-     * @throws EE_Error
3910
-     * @throws ReflectionException
3911
-     * @throws InvalidDataTypeException
3912
-     * @throws InvalidInterfaceException
3913
-     * @throws InvalidArgumentException
3914
-     */
3915
-    public function activate_mt_toggle()
3916
-    {
3917
-        $success = true;
3918
-        $this->_prep_default_response_for_messenger_or_message_type_toggle();
3919
-
3920
-        // let's make sure we have the necessary data
3921
-        if (! isset($this->_req_data['message_type'])) {
3922
-            EE_Error::add_error(
3923
-                esc_html__('Message Type name needed to toggle activation. None given', 'event_espresso'),
3924
-                __FILE__,
3925
-                __FUNCTION__,
3926
-                __LINE__
3927
-            );
3928
-            $success = false;
3929
-        }
3930
-
3931
-        if (! isset($this->_req_data['messenger'])) {
3932
-            EE_Error::add_error(
3933
-                esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
3934
-                __FILE__,
3935
-                __FUNCTION__,
3936
-                __LINE__
3937
-            );
3938
-            $success = false;
3939
-        }
3940
-
3941
-        if (! isset($this->_req_data['status'])) {
3942
-            EE_Error::add_error(
3943
-                esc_html__(
3944
-                    'Messenger status needed to know whether activation or deactivation is happening. No status is given',
3945
-                    'event_espresso'
3946
-                ),
3947
-                __FILE__,
3948
-                __FUNCTION__,
3949
-                __LINE__
3950
-            );
3951
-            $success = false;
3952
-        }
3953
-
3954
-
3955
-        // do check to verify we have a valid status.
3956
-        $status = $this->_req_data['status'];
3957
-
3958
-        if ($status !== 'activate' && $status !== 'deactivate') {
3959
-            EE_Error::add_error(
3960
-                sprintf(
3961
-                    esc_html__('The given status (%s) is not valid. Must be "active" or "inactive"', 'event_espresso'),
3962
-                    $this->_req_data['status']
3963
-                ),
3964
-                __FILE__,
3965
-                __FUNCTION__,
3966
-                __LINE__
3967
-            );
3968
-            $success = false;
3969
-        }
3970
-
3971
-
3972
-        // do a nonce check here since we're not arriving via a normal route
3973
-        $nonce = isset($this->_req_data['mt_nonce']) ? sanitize_text_field($this->_req_data['mt_nonce']) : '';
3974
-        $nonce_ref = $this->_req_data['message_type'] . '_nonce';
3975
-
3976
-        $this->_verify_nonce($nonce, $nonce_ref);
3977
-
3978
-        if ($success) {
3979
-            // made it here? um, what are you waiting for then?
3980
-            $success = $status === 'deactivate'
3981
-                ? $this->_deactivate_message_type_for_messenger(
3982
-                    $this->_req_data['messenger'],
3983
-                    $this->_req_data['message_type']
3984
-                )
3985
-                : $this->_activate_message_type_for_messenger(
3986
-                    $this->_req_data['messenger'],
3987
-                    $this->_req_data['message_type']
3988
-                );
3989
-        }
3990
-
3991
-        $this->_template_args['success'] = $success;
3992
-        $this->_return_json();
3993
-    }
3994
-
3995
-
3996
-    /**
3997
-     * Takes care of processing activating a messenger and preparing the appropriate response.
3998
-     *
3999
-     * @param string $messenger_name The name of the messenger being activated
4000
-     * @return bool
4001
-     * @throws DomainException
4002
-     * @throws EE_Error
4003
-     * @throws InvalidArgumentException
4004
-     * @throws ReflectionException
4005
-     * @throws InvalidDataTypeException
4006
-     * @throws InvalidInterfaceException
4007
-     */
4008
-    protected function _activate_messenger($messenger_name)
4009
-    {
4010
-        /** @var EE_messenger $active_messenger This will be present because it can't be toggled if it isn't */
4011
-        $active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4012
-        $message_types_to_activate = $active_messenger instanceof EE_Messenger
4013
-            ? $active_messenger->get_default_message_types()
4014
-            : array();
4015
-
4016
-        // ensure is active
4017
-        $this->_message_resource_manager->activate_messenger($messenger_name, $message_types_to_activate);
4018
-
4019
-        // set response_data for reload
4020
-        foreach ($message_types_to_activate as $message_type_name) {
4021
-            /** @var EE_message_type $message_type */
4022
-            $message_type = $this->_message_resource_manager->get_message_type($message_type_name);
4023
-            if ($this->_message_resource_manager->is_message_type_active_for_messenger(
4024
-                $messenger_name,
4025
-                $message_type_name
4026
-            )
4027
-                && $message_type instanceof EE_message_type
4028
-            ) {
4029
-                $this->_template_args['data']['active_mts'][] = $message_type_name;
4030
-                if ($message_type->get_admin_settings_fields()) {
4031
-                    $this->_template_args['data']['mt_reload'][] = $message_type_name;
4032
-                }
4033
-            }
4034
-        }
4035
-
4036
-        // add success message for activating messenger
4037
-        return $this->_setup_response_message_for_activating_messenger_with_message_types($active_messenger);
4038
-    }
4039
-
4040
-
4041
-    /**
4042
-     * Takes care of processing deactivating a messenger and preparing the appropriate response.
4043
-     *
4044
-     * @param string $messenger_name The name of the messenger being activated
4045
-     * @return bool
4046
-     * @throws DomainException
4047
-     * @throws EE_Error
4048
-     * @throws InvalidArgumentException
4049
-     * @throws ReflectionException
4050
-     * @throws InvalidDataTypeException
4051
-     * @throws InvalidInterfaceException
4052
-     */
4053
-    protected function _deactivate_messenger($messenger_name)
4054
-    {
4055
-        /** @var EE_messenger $active_messenger This will be present because it can't be toggled if it isn't */
4056
-        $active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4057
-        $this->_message_resource_manager->deactivate_messenger($messenger_name);
4058
-
4059
-        return $this->_setup_response_message_for_deactivating_messenger_with_message_types($active_messenger);
4060
-    }
4061
-
4062
-
4063
-    /**
4064
-     * Takes care of processing activating a message type for a messenger and preparing the appropriate response.
4065
-     *
4066
-     * @param string $messenger_name    The name of the messenger the message type is being activated for.
4067
-     * @param string $message_type_name The name of the message type being activated for the messenger
4068
-     * @return bool
4069
-     * @throws DomainException
4070
-     * @throws EE_Error
4071
-     * @throws InvalidArgumentException
4072
-     * @throws ReflectionException
4073
-     * @throws InvalidDataTypeException
4074
-     * @throws InvalidInterfaceException
4075
-     */
4076
-    protected function _activate_message_type_for_messenger($messenger_name, $message_type_name)
4077
-    {
4078
-        /** @var EE_messenger $active_messenger This will be present because it can't be toggled if it isn't */
4079
-        $active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4080
-        /** @var EE_message_type $message_type_to_activate This will be present because it can't be toggled if it isn't */
4081
-        $message_type_to_activate = $this->_message_resource_manager->get_message_type($message_type_name);
4082
-
4083
-        // ensure is active
4084
-        $this->_message_resource_manager->activate_messenger($messenger_name, $message_type_name);
4085
-
4086
-        // set response for load
4087
-        if ($this->_message_resource_manager->is_message_type_active_for_messenger(
4088
-            $messenger_name,
4089
-            $message_type_name
4090
-        )
4091
-        ) {
4092
-            $this->_template_args['data']['active_mts'][] = $message_type_name;
4093
-            if ($message_type_to_activate->get_admin_settings_fields()) {
4094
-                $this->_template_args['data']['mt_reload'][] = $message_type_name;
4095
-            }
4096
-        }
4097
-
4098
-        return $this->_setup_response_message_for_activating_messenger_with_message_types(
4099
-            $active_messenger,
4100
-            $message_type_to_activate
4101
-        );
4102
-    }
4103
-
4104
-
4105
-    /**
4106
-     * Takes care of processing deactivating a message type for a messenger and preparing the appropriate response.
4107
-     *
4108
-     * @param string $messenger_name    The name of the messenger the message type is being deactivated for.
4109
-     * @param string $message_type_name The name of the message type being deactivated for the messenger
4110
-     * @return bool
4111
-     * @throws DomainException
4112
-     * @throws EE_Error
4113
-     * @throws InvalidArgumentException
4114
-     * @throws ReflectionException
4115
-     * @throws InvalidDataTypeException
4116
-     * @throws InvalidInterfaceException
4117
-     */
4118
-    protected function _deactivate_message_type_for_messenger($messenger_name, $message_type_name)
4119
-    {
4120
-        /** @var EE_messenger $active_messenger This will be present because it can't be toggled if it isn't */
4121
-        $active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4122
-        /** @var EE_message_type $message_type_to_activate This will be present because it can't be toggled if it isn't */
4123
-        $message_type_to_deactivate = $this->_message_resource_manager->get_message_type($message_type_name);
4124
-        $this->_message_resource_manager->deactivate_message_type_for_messenger($message_type_name, $messenger_name);
4125
-
4126
-        return $this->_setup_response_message_for_deactivating_messenger_with_message_types(
4127
-            $active_messenger,
4128
-            $message_type_to_deactivate
4129
-        );
4130
-    }
4131
-
4132
-
4133
-    /**
4134
-     * This just initializes the defaults for activating messenger and message type responses.
4135
-     */
4136
-    protected function _prep_default_response_for_messenger_or_message_type_toggle()
4137
-    {
4138
-        $this->_template_args['data']['active_mts'] = array();
4139
-        $this->_template_args['data']['mt_reload'] = array();
4140
-    }
4141
-
4142
-
4143
-    /**
4144
-     * Setup appropriate response for activating a messenger and/or message types
4145
-     *
4146
-     * @param EE_messenger         $messenger
4147
-     * @param EE_message_type|null $message_type
4148
-     * @return bool
4149
-     * @throws DomainException
4150
-     * @throws EE_Error
4151
-     * @throws InvalidArgumentException
4152
-     * @throws ReflectionException
4153
-     * @throws InvalidDataTypeException
4154
-     * @throws InvalidInterfaceException
4155
-     */
4156
-    protected function _setup_response_message_for_activating_messenger_with_message_types(
4157
-        $messenger,
4158
-        EE_Message_Type $message_type = null
4159
-    ) {
4160
-        // if $messenger isn't a valid messenger object then get out.
4161
-        if (! $messenger instanceof EE_Messenger) {
4162
-            EE_Error::add_error(
4163
-                esc_html__('The messenger being activated is not a valid messenger', 'event_espresso'),
4164
-                __FILE__,
4165
-                __FUNCTION__,
4166
-                __LINE__
4167
-            );
4168
-
4169
-            return false;
4170
-        }
4171
-        // activated
4172
-        if ($this->_template_args['data']['active_mts']) {
4173
-            EE_Error::overwrite_success();
4174
-            // activated a message type with the messenger
4175
-            if ($message_type instanceof EE_message_type) {
4176
-                EE_Error::add_success(
4177
-                    sprintf(
4178
-                        esc_html__(
4179
-                            '%s message type has been successfully activated with the %s messenger',
4180
-                            'event_espresso'
4181
-                        ),
4182
-                        ucwords($message_type->label['singular']),
4183
-                        ucwords($messenger->label['singular'])
4184
-                    )
4185
-                );
4186
-
4187
-                // if message type was invoice then let's make sure we activate the invoice payment method.
4188
-                if ($message_type->name === 'invoice') {
4189
-                    EE_Registry::instance()->load_lib('Payment_Method_Manager');
4190
-                    $pm = EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
4191
-                    if ($pm instanceof EE_Payment_Method) {
4192
-                        EE_Error::add_attention(
4193
-                            esc_html__(
4194
-                                'Activating the invoice message type also automatically activates the invoice payment method.  If you do not wish the invoice payment method to be active, or to change its settings, visit the payment method admin page.',
4195
-                                'event_espresso'
4196
-                            )
4197
-                        );
4198
-                    }
4199
-                }
4200
-                // just toggles the entire messenger
4201
-            } else {
4202
-                EE_Error::add_success(
4203
-                    sprintf(
4204
-                        esc_html__('%s messenger has been successfully activated', 'event_espresso'),
4205
-                        ucwords($messenger->label['singular'])
4206
-                    )
4207
-                );
4208
-            }
4209
-
4210
-            return true;
4211
-
4212
-            // possible error condition. This will happen when our active_mts data is empty because it is validated for actual active
4213
-            // message types after the activation process.  However its possible some messengers don't HAVE any default_message_types
4214
-            // in which case we just give a success message for the messenger being successfully activated.
4215
-        } else {
4216
-            if (! $messenger->get_default_message_types()) {
4217
-                // messenger doesn't have any default message types so still a success.
4218
-                EE_Error::add_success(
4219
-                    sprintf(
4220
-                        esc_html__('%s messenger was successfully activated.', 'event_espresso'),
4221
-                        ucwords($messenger->label['singular'])
4222
-                    )
4223
-                );
4224
-
4225
-                return true;
4226
-            } else {
4227
-                EE_Error::add_error(
4228
-                    $message_type instanceof EE_message_type
4229
-                        ? sprintf(
4230
-                            esc_html__(
4231
-                                '%s message type was not successfully activated with the %s messenger',
4232
-                                'event_espresso'
4233
-                            ),
4234
-                            ucwords($message_type->label['singular']),
4235
-                            ucwords($messenger->label['singular'])
4236
-                        )
4237
-                        : sprintf(
4238
-                            esc_html__('%s messenger was not successfully activated', 'event_espresso'),
4239
-                            ucwords($messenger->label['singular'])
4240
-                        ),
4241
-                    __FILE__,
4242
-                    __FUNCTION__,
4243
-                    __LINE__
4244
-                );
4245
-
4246
-                return false;
4247
-            }
4248
-        }
4249
-    }
4250
-
4251
-
4252
-    /**
4253
-     * This sets up the appropriate response for deactivating a messenger and/or message type.
4254
-     *
4255
-     * @param EE_messenger         $messenger
4256
-     * @param EE_message_type|null $message_type
4257
-     * @return bool
4258
-     * @throws DomainException
4259
-     * @throws EE_Error
4260
-     * @throws InvalidArgumentException
4261
-     * @throws ReflectionException
4262
-     * @throws InvalidDataTypeException
4263
-     * @throws InvalidInterfaceException
4264
-     */
4265
-    protected function _setup_response_message_for_deactivating_messenger_with_message_types(
4266
-        $messenger,
4267
-        EE_message_type $message_type = null
4268
-    ) {
4269
-        EE_Error::overwrite_success();
4270
-
4271
-        // if $messenger isn't a valid messenger object then get out.
4272
-        if (! $messenger instanceof EE_Messenger) {
4273
-            EE_Error::add_error(
4274
-                esc_html__('The messenger being deactivated is not a valid messenger', 'event_espresso'),
4275
-                __FILE__,
4276
-                __FUNCTION__,
4277
-                __LINE__
4278
-            );
4279
-
4280
-            return false;
4281
-        }
4282
-
4283
-        if ($message_type instanceof EE_message_type) {
4284
-            $message_type_name = $message_type->name;
4285
-            EE_Error::add_success(
4286
-                sprintf(
4287
-                    esc_html__(
4288
-                        '%s message type has been successfully deactivated for the %s messenger.',
4289
-                        'event_espresso'
4290
-                    ),
4291
-                    ucwords($message_type->label['singular']),
4292
-                    ucwords($messenger->label['singular'])
4293
-                )
4294
-            );
4295
-        } else {
4296
-            $message_type_name = '';
4297
-            EE_Error::add_success(
4298
-                sprintf(
4299
-                    esc_html__('%s messenger has been successfully deactivated.', 'event_espresso'),
4300
-                    ucwords($messenger->label['singular'])
4301
-                )
4302
-            );
4303
-        }
4304
-
4305
-        // if messenger was html or message type was invoice then let's make sure we deactivate invoice payment method.
4306
-        if ($messenger->name === 'html' || $message_type_name === 'invoice') {
4307
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
4308
-            $count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method('invoice');
4309
-            if ($count_updated > 0) {
4310
-                $msg = $message_type_name === 'invoice'
4311
-                    ? esc_html__(
4312
-                        'Deactivating the invoice message type also automatically deactivates the invoice payment method. In order for invoices to be generated the invoice message type must be active. If you completed this action by mistake, simply reactivate the invoice message type and then visit the payment methods admin page to reactivate the invoice payment method.',
4313
-                        'event_espresso'
4314
-                    )
4315
-                    : esc_html__(
4316
-                        'Deactivating the html messenger also automatically deactivates the invoice payment method.  In order for invoices to be generated the html messenger must be be active.  If you completed this action by mistake, simply reactivate the html messenger, then visit the payment methods admin page to reactivate the invoice payment method.',
4317
-                        'event_espresso'
4318
-                    );
4319
-                EE_Error::add_attention($msg);
4320
-            }
4321
-        }
4322
-
4323
-        return true;
4324
-    }
4325
-
4326
-
4327
-    /**
4328
-     * handles updating a message type form on messenger activation IF the message type has settings fields. (via ajax)
4329
-     *
4330
-     * @throws DomainException
4331
-     */
4332
-    public function update_mt_form()
4333
-    {
4334
-        if (! isset($this->_req_data['messenger']) || ! isset($this->_req_data['message_type'])) {
4335
-            EE_Error::add_error(
4336
-                esc_html__('Require message type or messenger to send an updated form', 'event_espresso'),
4337
-                __FILE__,
4338
-                __FUNCTION__,
4339
-                __LINE__
4340
-            );
4341
-            $this->_return_json();
4342
-        }
4343
-
4344
-        $message_types = $this->get_installed_message_types();
4345
-
4346
-        $message_type = $message_types[ $this->_req_data['message_type'] ];
4347
-        $messenger = $this->_message_resource_manager->get_active_messenger($this->_req_data['messenger']);
4348
-
4349
-        $content = $this->_message_type_settings_content(
4350
-            $message_type,
4351
-            $messenger,
4352
-            true
4353
-        );
4354
-        $this->_template_args['success'] = true;
4355
-        $this->_template_args['content'] = $content;
4356
-        $this->_return_json();
4357
-    }
4358
-
4359
-
4360
-    /**
4361
-     * this handles saving the settings for a messenger or message type
4362
-     *
4363
-     */
4364
-    public function save_settings()
4365
-    {
4366
-        if (! isset($this->_req_data['type'])) {
4367
-            EE_Error::add_error(
4368
-                esc_html__(
4369
-                    'Cannot save settings because type is unknown (messenger settings or messsage type settings?)',
4370
-                    'event_espresso'
4371
-                ),
4372
-                __FILE__,
4373
-                __FUNCTION__,
4374
-                __LINE__
4375
-            );
4376
-            $this->_template_args['error'] = true;
4377
-            $this->_return_json();
4378
-        }
4379
-
4380
-
4381
-        if ($this->_req_data['type'] === 'messenger') {
4382
-            // this should be an array.
4383
-            $settings = $this->_req_data['messenger_settings'];
4384
-            $messenger = $settings['messenger'];
4385
-            // let's setup the settings data
4386
-            foreach ($settings as $key => $value) {
4387
-                switch ($key) {
4388
-                    case 'messenger':
4389
-                        unset($settings['messenger']);
4390
-                        break;
4391
-                    case 'message_types':
4392
-                        unset($settings['message_types']);
4393
-                        break;
4394
-                    default:
4395
-                        $settings[ $key ] = $value;
4396
-                        break;
4397
-                }
4398
-            }
4399
-            $this->_message_resource_manager->add_settings_for_messenger($messenger, $settings);
4400
-        } elseif ($this->_req_data['type'] === 'message_type') {
4401
-            $settings = $this->_req_data['message_type_settings'];
4402
-            $messenger = $settings['messenger'];
4403
-            $message_type = $settings['message_type'];
4404
-
4405
-            foreach ($settings as $key => $value) {
4406
-                switch ($key) {
4407
-                    case 'messenger':
4408
-                        unset($settings['messenger']);
4409
-                        break;
4410
-                    case 'message_type':
4411
-                        unset($settings['message_type']);
4412
-                        break;
4413
-                    default:
4414
-                        $settings[ $key ] = $value;
4415
-                        break;
4416
-                }
4417
-            }
4418
-
4419
-            $this->_message_resource_manager->add_settings_for_message_type($messenger, $message_type, $settings);
4420
-        }
4421
-
4422
-        // okay we should have the data all setup.  Now we just update!
4423
-        $success = $this->_message_resource_manager->update_active_messengers_option();
4424
-
4425
-        if ($success) {
4426
-            EE_Error::add_success(__('Settings updated', 'event_espresso'));
4427
-        } else {
4428
-            EE_Error::add_error(
4429
-                esc_html__(
4430
-                    'Settings did not get updated',
4431
-                    'event_espresso'
4432
-                ),
4433
-                __FILE__,
4434
-                __FUNCTION__,
4435
-                __LINE__
4436
-            );
4437
-        }
4438
-
4439
-        $this->_template_args['success'] = $success;
4440
-        $this->_return_json();
4441
-    }
4442
-
4443
-
4444
-
4445
-
4446
-    /**  EE MESSAGE PROCESSING ACTIONS **/
4447
-
4448
-
4449
-    /**
4450
-     * This immediately generates any EE_Message ID's that are selected that are EEM_Message::status_incomplete
4451
-     * However, this does not send immediately, it just queues for sending.
4452
-     *
4453
-     * @since 4.9.0
4454
-     * @throws EE_Error
4455
-     * @throws InvalidDataTypeException
4456
-     * @throws InvalidInterfaceException
4457
-     * @throws InvalidArgumentException
4458
-     * @throws ReflectionException
4459
-     */
4460
-    protected function _generate_now()
4461
-    {
4462
-        EED_Messages::generate_now($this->_get_msg_ids_from_request());
4463
-        $this->_redirect_after_action(false, '', '', array(), true);
4464
-    }
4465
-
4466
-
4467
-    /**
4468
-     * This immediately generates AND sends any EE_Message's selected that are EEM_Message::status_incomplete or that
4469
-     * are EEM_Message::status_resend or EEM_Message::status_idle
4470
-     *
4471
-     * @since 4.9.0
4472
-     * @throws EE_Error
4473
-     * @throws InvalidDataTypeException
4474
-     * @throws InvalidInterfaceException
4475
-     * @throws InvalidArgumentException
4476
-     * @throws ReflectionException
4477
-     */
4478
-    protected function _generate_and_send_now()
4479
-    {
4480
-        EED_Messages::generate_and_send_now($this->_get_msg_ids_from_request());
4481
-        $this->_redirect_after_action(false, '', '', array(), true);
4482
-    }
4483
-
4484
-
4485
-    /**
4486
-     * This queues any EEM_Message::status_sent EE_Message ids in the request for resending.
4487
-     *
4488
-     * @since 4.9.0
4489
-     * @throws EE_Error
4490
-     * @throws InvalidDataTypeException
4491
-     * @throws InvalidInterfaceException
4492
-     * @throws InvalidArgumentException
4493
-     * @throws ReflectionException
4494
-     */
4495
-    protected function _queue_for_resending()
4496
-    {
4497
-        EED_Messages::queue_for_resending($this->_get_msg_ids_from_request());
4498
-        $this->_redirect_after_action(false, '', '', array(), true);
4499
-    }
4500
-
4501
-
4502
-    /**
4503
-     *  This sends immediately any EEM_Message::status_idle or EEM_Message::status_resend messages in the queue
4504
-     *
4505
-     * @since 4.9.0
4506
-     * @throws EE_Error
4507
-     * @throws InvalidDataTypeException
4508
-     * @throws InvalidInterfaceException
4509
-     * @throws InvalidArgumentException
4510
-     * @throws ReflectionException
4511
-     */
4512
-    protected function _send_now()
4513
-    {
4514
-        EED_Messages::send_now($this->_get_msg_ids_from_request());
4515
-        $this->_redirect_after_action(false, '', '', array(), true);
4516
-    }
4517
-
4518
-
4519
-    /**
4520
-     * Deletes EE_messages for IDs in the request.
4521
-     *
4522
-     * @since 4.9.0
4523
-     * @throws EE_Error
4524
-     * @throws InvalidDataTypeException
4525
-     * @throws InvalidInterfaceException
4526
-     * @throws InvalidArgumentException
4527
-     */
4528
-    protected function _delete_ee_messages()
4529
-    {
4530
-        $msg_ids = $this->_get_msg_ids_from_request();
4531
-        $deleted_count = 0;
4532
-        foreach ($msg_ids as $msg_id) {
4533
-            if (EEM_Message::instance()->delete_by_ID($msg_id)) {
4534
-                $deleted_count++;
4535
-            }
4536
-        }
4537
-        if ($deleted_count) {
4538
-            EE_Error::add_success(
4539
-                esc_html(
4540
-                    _n(
4541
-                        'Message successfully deleted',
4542
-                        'Messages successfully deleted',
4543
-                        $deleted_count,
4544
-                        'event_espresso'
4545
-                    )
4546
-                )
4547
-            );
4548
-            $this->_redirect_after_action(
4549
-                false,
4550
-                '',
4551
-                '',
4552
-                array(),
4553
-                true
4554
-            );
4555
-        } else {
4556
-            EE_Error::add_error(
4557
-                _n('The message was not deleted.', 'The messages were not deleted', count($msg_ids), 'event_espresso'),
4558
-                __FILE__,
4559
-                __FUNCTION__,
4560
-                __LINE__
4561
-            );
4562
-            $this->_redirect_after_action(false, '', '', array(), true);
4563
-        }
4564
-    }
4565
-
4566
-
4567
-    /**
4568
-     *  This looks for 'MSG_ID' key in the request and returns an array of MSG_ID's if present.
4569
-     *
4570
-     * @since 4.9.0
4571
-     * @return array
4572
-     */
4573
-    protected function _get_msg_ids_from_request()
4574
-    {
4575
-        if (! isset($this->_req_data['MSG_ID'])) {
4576
-            return array();
4577
-        }
4578
-
4579
-        return is_array($this->_req_data['MSG_ID'])
4580
-            ? array_keys($this->_req_data['MSG_ID'])
4581
-            : array($this->_req_data['MSG_ID']);
4582
-    }
2662
+		$output = ob_get_contents();
2663
+		ob_clean();
2664
+		$this->_context_switcher = $output;
2665
+	}
2666
+
2667
+
2668
+	/**
2669
+	 * utility for sanitizing new values coming in.
2670
+	 * Note: this is only used when updating a context.
2671
+	 *
2672
+	 * @access protected
2673
+	 *
2674
+	 * @param int $index This helps us know which template field to select from the request array.
2675
+	 *
2676
+	 * @return array
2677
+	 */
2678
+	protected function _set_message_template_column_values($index)
2679
+	{
2680
+		if (is_array($this->_req_data['MTP_template_fields'][ $index ]['content'])) {
2681
+			foreach ($this->_req_data['MTP_template_fields'][ $index ]['content'] as $field => $value) {
2682
+				$this->_req_data['MTP_template_fields'][ $index ]['content'][ $field ] = $value;
2683
+			}
2684
+		}
2685
+
2686
+
2687
+		$set_column_values = array(
2688
+			'MTP_ID'             => absint($this->_req_data['MTP_template_fields'][ $index ]['MTP_ID']),
2689
+			'GRP_ID'             => absint($this->_req_data['GRP_ID']),
2690
+			'MTP_user_id'        => absint($this->_req_data['MTP_user_id']),
2691
+			'MTP_messenger'      => strtolower($this->_req_data['MTP_messenger']),
2692
+			'MTP_message_type'   => strtolower($this->_req_data['MTP_message_type']),
2693
+			'MTP_template_field' => strtolower($this->_req_data['MTP_template_fields'][ $index ]['name']),
2694
+			'MTP_context'        => strtolower($this->_req_data['MTP_context']),
2695
+			'MTP_content'        => $this->_req_data['MTP_template_fields'][ $index ]['content'],
2696
+			'MTP_is_global'      => isset($this->_req_data['MTP_is_global'])
2697
+				? absint($this->_req_data['MTP_is_global'])
2698
+				: 0,
2699
+			'MTP_is_override'    => isset($this->_req_data['MTP_is_override'])
2700
+				? absint($this->_req_data['MTP_is_override'])
2701
+				: 0,
2702
+			'MTP_deleted'        => absint($this->_req_data['MTP_deleted']),
2703
+			'MTP_is_active'      => absint($this->_req_data['MTP_is_active']),
2704
+		);
2705
+
2706
+
2707
+		return $set_column_values;
2708
+	}
2709
+
2710
+
2711
+	protected function _insert_or_update_message_template($new = false)
2712
+	{
2713
+
2714
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2715
+		$success = 0;
2716
+		$override = false;
2717
+
2718
+		// setup notices description
2719
+		$messenger_slug = ! empty($this->_req_data['MTP_messenger']) ? $this->_req_data['MTP_messenger'] : '';
2720
+
2721
+		// need the message type and messenger objects to be able to use the labels for the notices
2722
+		$messenger_object = $this->_message_resource_manager->get_messenger($messenger_slug);
2723
+		$messenger_label = $messenger_object instanceof EE_messenger
2724
+			? ucwords($messenger_object->label['singular'])
2725
+			: '';
2726
+
2727
+		$message_type_slug = ! empty($this->_req_data['MTP_message_type'])
2728
+			? $this->_req_data['MTP_message_type']
2729
+			: '';
2730
+		$message_type_object = $this->_message_resource_manager->get_message_type($message_type_slug);
2731
+
2732
+		$message_type_label = $message_type_object instanceof EE_message_type
2733
+			? ucwords($message_type_object->label['singular'])
2734
+			: '';
2735
+
2736
+		$context_slug = ! empty($this->_req_data['MTP_context'])
2737
+			? $this->_req_data['MTP_context']
2738
+			: '';
2739
+		$context = ucwords(str_replace('_', ' ', $context_slug));
2740
+
2741
+		$item_desc = $messenger_label && $message_type_label
2742
+			? $messenger_label . ' ' . $message_type_label . ' ' . $context . ' '
2743
+			: '';
2744
+		$item_desc .= 'Message Template';
2745
+		$query_args = array();
2746
+		$edit_array = array();
2747
+		$action_desc = '';
2748
+
2749
+		// if this is "new" then we need to generate the default contexts for the selected messenger/message_type for
2750
+		// user to edit.
2751
+		if ($new) {
2752
+			$GRP_ID = ! empty($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : 0;
2753
+			if ($edit_array = $this->_generate_new_templates($messenger_slug, $message_type_slug, $GRP_ID)) {
2754
+				if (empty($edit_array)) {
2755
+					$success = 0;
2756
+				} else {
2757
+					$success = 1;
2758
+					$edit_array = $edit_array[0];
2759
+					$query_args = array(
2760
+						'id'      => $edit_array['GRP_ID'],
2761
+						'context' => $edit_array['MTP_context'],
2762
+						'action'  => 'edit_message_template',
2763
+					);
2764
+				}
2765
+			}
2766
+			$action_desc = 'created';
2767
+		} else {
2768
+			$MTPG = EEM_Message_Template_Group::instance();
2769
+			$MTP = EEM_Message_Template::instance();
2770
+
2771
+
2772
+			// run update for each template field in displayed context
2773
+			if (! isset($this->_req_data['MTP_template_fields']) && empty($this->_req_data['MTP_template_fields'])) {
2774
+				EE_Error::add_error(
2775
+					esc_html__(
2776
+						'There was a problem saving the template fields from the form because I didn\'t receive any actual template field data.',
2777
+						'event_espresso'
2778
+					),
2779
+					__FILE__,
2780
+					__FUNCTION__,
2781
+					__LINE__
2782
+				);
2783
+				$success = 0;
2784
+			} else {
2785
+				// first validate all fields!
2786
+				// this filter allows client code to add its own validation to the template fields as well.
2787
+				// returning an empty array means everything passed validation.
2788
+				// errors in validation should be represented in an array with the following shape:
2789
+				// array(
2790
+				//   'fieldname' => array(
2791
+				//          'msg' => 'error message'
2792
+				//          'value' => 'value for field producing error'
2793
+				// )
2794
+				$custom_validation = (array) apply_filters(
2795
+					'FHEE__Messages_Admin_Page___insert_or_update_message_template__validates',
2796
+					array(),
2797
+					$this->_req_data['MTP_template_fields'],
2798
+					$context_slug,
2799
+					$messenger_slug,
2800
+					$message_type_slug
2801
+				);
2802
+
2803
+				$system_validation = $MTPG->validate(
2804
+					$this->_req_data['MTP_template_fields'],
2805
+					$context_slug,
2806
+					$messenger_slug,
2807
+					$message_type_slug
2808
+				);
2809
+
2810
+				$system_validation = ! is_array($system_validation) && $system_validation ? array()
2811
+					: $system_validation;
2812
+				$validates = array_merge($custom_validation, $system_validation);
2813
+
2814
+				// if $validate returned error messages (i.e. is_array()) then we need to process them and setup an
2815
+				// appropriate response. HMM, dang this isn't correct, $validates will ALWAYS be an array.
2816
+				//  WE need to make sure there is no actual error messages in validates.
2817
+				if (is_array($validates) && ! empty($validates)) {
2818
+					// add the transient so when the form loads we know which fields to highlight
2819
+					$this->_add_transient('edit_message_template', $validates);
2820
+
2821
+					$success = 0;
2822
+
2823
+					// setup notices
2824
+					foreach ($validates as $field => $error) {
2825
+						if (isset($error['msg'])) {
2826
+							EE_Error::add_error($error['msg'], __FILE__, __FUNCTION__, __LINE__);
2827
+						}
2828
+					}
2829
+				} else {
2830
+					$set_column_values = array();
2831
+					foreach ($this->_req_data['MTP_template_fields'] as $template_field => $content) {
2832
+						$set_column_values = $this->_set_message_template_column_values($template_field);
2833
+
2834
+						$where_cols_n_values = array(
2835
+							'MTP_ID' => $this->_req_data['MTP_template_fields'][ $template_field ]['MTP_ID'],
2836
+						);
2837
+						// if they aren't allowed to use all JS, restrict them to just posty-y tags
2838
+						if (! current_user_can('unfiltered_html')) {
2839
+							if (is_array($set_column_values['MTP_content'])) {
2840
+								foreach ($set_column_values['MTP_content'] as $key => $value) {
2841
+									// remove slashes so wp_kses works properly (its wp_kses_stripslashes() function
2842
+									// only removes slashes from double-quotes, so attributes using single quotes always
2843
+									// appear invalid.) But currently the models expect slashed data, so after wp_kses
2844
+									// runs we need to re-slash the data. Sheesh. See
2845
+									// https://events.codebasehq.com/projects/event-espresso/tickets/11211#update-47321587
2846
+									$set_column_values['MTP_content'][ $key ] = addslashes(
2847
+										wp_kses(
2848
+											stripslashes($value),
2849
+											wp_kses_allowed_html('post')
2850
+										)
2851
+									);
2852
+								}
2853
+							} else {
2854
+								$set_column_values['MTP_content'] = wp_kses(
2855
+									$set_column_values['MTP_content'],
2856
+									wp_kses_allowed_html('post')
2857
+								);
2858
+							}
2859
+						}
2860
+						$message_template_fields = array(
2861
+							'GRP_ID'             => $set_column_values['GRP_ID'],
2862
+							'MTP_template_field' => $set_column_values['MTP_template_field'],
2863
+							'MTP_context'        => $set_column_values['MTP_context'],
2864
+							'MTP_content'        => $set_column_values['MTP_content'],
2865
+						);
2866
+						if ($updated = $MTP->update($message_template_fields, array($where_cols_n_values))) {
2867
+							if ($updated === false) {
2868
+								EE_Error::add_error(
2869
+									sprintf(
2870
+										esc_html__('%s field was NOT updated for some reason', 'event_espresso'),
2871
+										$template_field
2872
+									),
2873
+									__FILE__,
2874
+									__FUNCTION__,
2875
+									__LINE__
2876
+								);
2877
+							} else {
2878
+								$success = 1;
2879
+							}
2880
+						} else {
2881
+							// only do this logic if we don't have a MTP_ID for this field
2882
+							if (empty($this->_req_data['MTP_template_fields'][ $template_field ]['MTP_ID'])) {
2883
+								// this has already been through the template field validator and sanitized, so it will be
2884
+								// safe to insert this field.  Why insert?  This typically happens when we introduce a new
2885
+								// message template field in a messenger/message type and existing users don't have the
2886
+								// default setup for it.
2887
+								// @link https://events.codebasehq.com/projects/event-espresso/tickets/9465
2888
+								$updated = $MTP->insert($message_template_fields);
2889
+								if (! $updated || is_wp_error($updated)) {
2890
+									EE_Error::add_error(
2891
+										sprintf(
2892
+											esc_html__('%s field could not be updated.', 'event_espresso'),
2893
+											$template_field
2894
+										),
2895
+										__FILE__,
2896
+										__FUNCTION__,
2897
+										__LINE__
2898
+									);
2899
+									$success = 0;
2900
+								} else {
2901
+									$success = 1;
2902
+								}
2903
+							}
2904
+						}
2905
+						$action_desc = 'updated';
2906
+					}
2907
+
2908
+					// we can use the last set_column_values for the MTPG update (because its the same for all of these specific MTPs)
2909
+					$mtpg_fields = array(
2910
+						'MTP_user_id'      => $set_column_values['MTP_user_id'],
2911
+						'MTP_messenger'    => $set_column_values['MTP_messenger'],
2912
+						'MTP_message_type' => $set_column_values['MTP_message_type'],
2913
+						'MTP_is_global'    => $set_column_values['MTP_is_global'],
2914
+						'MTP_is_override'  => $set_column_values['MTP_is_override'],
2915
+						'MTP_deleted'      => $set_column_values['MTP_deleted'],
2916
+						'MTP_is_active'    => $set_column_values['MTP_is_active'],
2917
+						'MTP_name'         => ! empty($this->_req_data['ee_msg_non_global_fields']['MTP_name'])
2918
+							? $this->_req_data['ee_msg_non_global_fields']['MTP_name']
2919
+							: '',
2920
+						'MTP_description'  => ! empty($this->_req_data['ee_msg_non_global_fields']['MTP_description'])
2921
+							? $this->_req_data['ee_msg_non_global_fields']['MTP_description']
2922
+							: '',
2923
+					);
2924
+
2925
+					$mtpg_where = array('GRP_ID' => $set_column_values['GRP_ID']);
2926
+					$updated = $MTPG->update($mtpg_fields, array($mtpg_where));
2927
+
2928
+					if ($updated === false) {
2929
+						EE_Error::add_error(
2930
+							sprintf(
2931
+								esc_html__(
2932
+									'The Message Template Group (%d) was NOT updated for some reason',
2933
+									'event_espresso'
2934
+								),
2935
+								$set_column_values['GRP_ID']
2936
+							),
2937
+							__FILE__,
2938
+							__FUNCTION__,
2939
+							__LINE__
2940
+						);
2941
+					} else {
2942
+						// k now we need to ensure the template_pack and template_variation fields are set.
2943
+						$template_pack = ! empty($this->_req_data['MTP_template_pack'])
2944
+							? $this->_req_data['MTP_template_pack']
2945
+							: 'default';
2946
+
2947
+						$template_variation = ! empty($this->_req_data['MTP_template_variation'])
2948
+							? $this->_req_data['MTP_template_variation']
2949
+							: 'default';
2950
+
2951
+						$mtpg_obj = $MTPG->get_one_by_ID($set_column_values['GRP_ID']);
2952
+						if ($mtpg_obj instanceof EE_Message_Template_Group) {
2953
+							$mtpg_obj->set_template_pack_name($template_pack);
2954
+							$mtpg_obj->set_template_pack_variation($template_variation);
2955
+						}
2956
+						$success = 1;
2957
+					}
2958
+				}
2959
+			}
2960
+		}
2961
+
2962
+		// we return things differently if doing ajax
2963
+		if (defined('DOING_AJAX') && DOING_AJAX) {
2964
+			$this->_template_args['success'] = $success;
2965
+			$this->_template_args['error'] = ! $success ? true : false;
2966
+			$this->_template_args['content'] = '';
2967
+			$this->_template_args['data'] = array(
2968
+				'grpID'        => $edit_array['GRP_ID'],
2969
+				'templateName' => $edit_array['template_name'],
2970
+			);
2971
+			if ($success) {
2972
+				EE_Error::overwrite_success();
2973
+				EE_Error::add_success(
2974
+					esc_html__(
2975
+						'The new template has been created and automatically selected for this event.  You can edit the new template by clicking the edit button.  Note before this template is assigned to this event, the event must be saved.',
2976
+						'event_espresso'
2977
+					)
2978
+				);
2979
+			}
2980
+
2981
+			$this->_return_json();
2982
+		}
2983
+
2984
+
2985
+		// was a test send triggered?
2986
+		if (isset($this->_req_data['test_button'])) {
2987
+			EE_Error::overwrite_success();
2988
+			$this->_do_test_send($context_slug, $messenger_slug, $message_type_slug);
2989
+			$override = true;
2990
+		}
2991
+
2992
+		if (empty($query_args)) {
2993
+			$query_args = array(
2994
+				'id'      => $this->_req_data['GRP_ID'],
2995
+				'context' => $context_slug,
2996
+				'action'  => 'edit_message_template',
2997
+			);
2998
+		}
2999
+
3000
+		$this->_redirect_after_action($success, $item_desc, $action_desc, $query_args, $override);
3001
+	}
3002
+
3003
+
3004
+	/**
3005
+	 * processes a test send request to do an actual messenger delivery test for the given message template being tested
3006
+	 *
3007
+	 * @param  string $context      what context being tested
3008
+	 * @param  string $messenger    messenger being tested
3009
+	 * @param  string $message_type message type being tested
3010
+	 * @throws EE_Error
3011
+	 * @throws InvalidArgumentException
3012
+	 * @throws InvalidDataTypeException
3013
+	 * @throws InvalidInterfaceException
3014
+	 */
3015
+	protected function _do_test_send($context, $messenger, $message_type)
3016
+	{
3017
+		// set things up for preview
3018
+		$this->_req_data['messenger'] = $messenger;
3019
+		$this->_req_data['message_type'] = $message_type;
3020
+		$this->_req_data['context'] = $context;
3021
+		$this->_req_data['GRP_ID'] = isset($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : '';
3022
+		$active_messenger = $this->_message_resource_manager->get_active_messenger($messenger);
3023
+
3024
+		// let's save any existing fields that might be required by the messenger
3025
+		if (isset($this->_req_data['test_settings_fld'])
3026
+			&& $active_messenger instanceof EE_messenger
3027
+			&& apply_filters(
3028
+				'FHEE__Messages_Admin_Page__do_test_send__set_existing_test_settings',
3029
+				true,
3030
+				$this->_req_data['test_settings_fld'],
3031
+				$active_messenger
3032
+			)
3033
+		) {
3034
+			$active_messenger->set_existing_test_settings($this->_req_data['test_settings_fld']);
3035
+		}
3036
+
3037
+		/**
3038
+		 * Use filter to add additional controls on whether message can send or not
3039
+		 */
3040
+		if (apply_filters(
3041
+			'FHEE__Messages_Admin_Page__do_test_send__can_send',
3042
+			true,
3043
+			$context,
3044
+			$this->_req_data,
3045
+			$messenger,
3046
+			$message_type
3047
+		)) {
3048
+			if (EEM_Event::instance()->count() > 0) {
3049
+				$success = $this->_preview_message(true);
3050
+				if ($success) {
3051
+					EE_Error::add_success(__('Test message sent', 'event_espresso'));
3052
+				} else {
3053
+					EE_Error::add_error(
3054
+						esc_html__('The test message was not sent', 'event_espresso'),
3055
+						__FILE__,
3056
+						__FUNCTION__,
3057
+						__LINE__
3058
+					);
3059
+				}
3060
+			} else {
3061
+				$this->noEventsErrorMessage(true);
3062
+			}
3063
+		}
3064
+	}
3065
+
3066
+
3067
+	/**
3068
+	 * _generate_new_templates
3069
+	 * This will handle the messenger, message_type selection when "adding a new custom template" for an event and will
3070
+	 * automatically create the defaults for the event.  The user would then be redirected to edit the default context
3071
+	 * for the event.
3072
+	 *
3073
+	 *
3074
+	 * @param  string $messenger     the messenger we are generating templates for
3075
+	 * @param array   $message_types array of message types that the templates are generated for.
3076
+	 * @param int     $GRP_ID        If this is a custom template being generated then a GRP_ID needs to be included to
3077
+	 *                               indicate the message_template_group being used as the base.
3078
+	 *
3079
+	 * @param bool    $global
3080
+	 *
3081
+	 * @return array|bool array of data required for the redirect to the correct edit page or bool if
3082
+	 *                               encountering problems.
3083
+	 * @throws EE_Error
3084
+	 */
3085
+	protected function _generate_new_templates($messenger, $message_types, $GRP_ID = 0, $global = false)
3086
+	{
3087
+
3088
+		// if no $message_types are given then that's okay... this may be a messenger that just adds shortcodes, so we
3089
+		// just don't generate any templates.
3090
+		if (empty($message_types)) {
3091
+			return true;
3092
+		}
3093
+
3094
+		return EEH_MSG_Template::generate_new_templates($messenger, $message_types, $GRP_ID, $global);
3095
+	}
3096
+
3097
+
3098
+	/**
3099
+	 * [_trash_or_restore_message_template]
3100
+	 *
3101
+	 * @param  boolean $trash whether to move an item to trash/restore (TRUE) or restore it (FALSE)
3102
+	 * @param boolean  $all   whether this is going to trash/restore all contexts within a template group (TRUE) OR just
3103
+	 *                        an individual context (FALSE).
3104
+	 * @return void
3105
+	 * @throws EE_Error
3106
+	 * @throws InvalidArgumentException
3107
+	 * @throws InvalidDataTypeException
3108
+	 * @throws InvalidInterfaceException
3109
+	 */
3110
+	protected function _trash_or_restore_message_template($trash = true, $all = false)
3111
+	{
3112
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3113
+		$MTP = EEM_Message_Template_Group::instance();
3114
+
3115
+		$success = 1;
3116
+
3117
+		// incoming GRP_IDs
3118
+		if ($all) {
3119
+			// Checkboxes
3120
+			if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3121
+				// if array has more than one element then success message should be plural.
3122
+				// todo: what about nonce?
3123
+				$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3124
+
3125
+				// cycle through checkboxes
3126
+				while (list($GRP_ID, $value) = each($this->_req_data['checkbox'])) {
3127
+					$trashed_or_restored = $trash ? $MTP->delete_by_ID($GRP_ID) : $MTP->restore_by_ID($GRP_ID);
3128
+					if (! $trashed_or_restored) {
3129
+						$success = 0;
3130
+					}
3131
+				}
3132
+			} else {
3133
+				// grab single GRP_ID and handle
3134
+				$GRP_ID = isset($this->_req_data['id']) ? absint($this->_req_data['id']) : 0;
3135
+				if (! empty($GRP_ID)) {
3136
+					$trashed_or_restored = $trash ? $MTP->delete_by_ID($GRP_ID) : $MTP->restore_by_ID($GRP_ID);
3137
+					if (! $trashed_or_restored) {
3138
+						$success = 0;
3139
+					}
3140
+				} else {
3141
+					$success = 0;
3142
+				}
3143
+			}
3144
+		}
3145
+
3146
+		$action_desc = $trash
3147
+			? esc_html__('moved to the trash', 'event_espresso')
3148
+			: esc_html__('restored', 'event_espresso');
3149
+
3150
+		$action_desc = ! empty($this->_req_data['template_switch']) ? esc_html__('switched', 'event_espresso') : $action_desc;
3151
+
3152
+		$item_desc = $all ? _n(
3153
+			'Message Template Group',
3154
+			'Message Template Groups',
3155
+			$success,
3156
+			'event_espresso'
3157
+		) : _n('Message Template Context', 'Message Template Contexts', $success, 'event_espresso');
3158
+
3159
+		$item_desc = ! empty($this->_req_data['template_switch']) ? _n(
3160
+			'template',
3161
+			'templates',
3162
+			$success,
3163
+			'event_espresso'
3164
+		) : $item_desc;
3165
+
3166
+		$this->_redirect_after_action($success, $item_desc, $action_desc, array());
3167
+	}
3168
+
3169
+
3170
+	/**
3171
+	 * [_delete_message_template]
3172
+	 * NOTE: this handles not only the deletion of the groups but also all the templates belonging to that group.
3173
+	 *
3174
+	 * @return void
3175
+	 * @throws EE_Error
3176
+	 * @throws InvalidArgumentException
3177
+	 * @throws InvalidDataTypeException
3178
+	 * @throws InvalidInterfaceException
3179
+	 */
3180
+	protected function _delete_message_template()
3181
+	{
3182
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3183
+
3184
+		// checkboxes
3185
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3186
+			// if array has more than one element then success message should be plural
3187
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3188
+
3189
+			// cycle through bulk action checkboxes
3190
+			while (list($GRP_ID, $value) = each($this->_req_data['checkbox'])) {
3191
+				$success = $this->_delete_mtp_permanently($GRP_ID);
3192
+			}
3193
+		} else {
3194
+			// grab single grp_id and delete
3195
+			$GRP_ID = absint($this->_req_data['id']);
3196
+			$success = $this->_delete_mtp_permanently($GRP_ID);
3197
+		}
3198
+
3199
+		$this->_redirect_after_action($success, 'Message Templates', 'deleted', array());
3200
+	}
3201
+
3202
+
3203
+	/**
3204
+	 * helper for permanently deleting a mtP group and all related message_templates
3205
+	 *
3206
+	 * @param  int  $GRP_ID        The group being deleted
3207
+	 * @param  bool $include_group whether to delete the Message Template Group as well.
3208
+	 * @return bool boolean to indicate the success of the deletes or not.
3209
+	 * @throws EE_Error
3210
+	 * @throws InvalidArgumentException
3211
+	 * @throws InvalidDataTypeException
3212
+	 * @throws InvalidInterfaceException
3213
+	 */
3214
+	private function _delete_mtp_permanently($GRP_ID, $include_group = true)
3215
+	{
3216
+		$success = 1;
3217
+		$MTPG = EEM_Message_Template_Group::instance();
3218
+		// first let's GET this group
3219
+		$MTG = $MTPG->get_one_by_ID($GRP_ID);
3220
+		// then delete permanently all the related Message Templates
3221
+		$deleted = $MTG->delete_related_permanently('Message_Template');
3222
+
3223
+		if ($deleted === 0) {
3224
+			$success = 0;
3225
+		}
3226
+
3227
+		// now delete permanently this particular group
3228
+
3229
+		if ($include_group && ! $MTG->delete_permanently()) {
3230
+			$success = 0;
3231
+		}
3232
+
3233
+		return $success;
3234
+	}
3235
+
3236
+
3237
+	/**
3238
+	 *    _learn_more_about_message_templates_link
3239
+	 *
3240
+	 * @access protected
3241
+	 * @return string
3242
+	 */
3243
+	protected function _learn_more_about_message_templates_link()
3244
+	{
3245
+		return '<a class="hidden" style="margin:0 20px; cursor:pointer; font-size:12px;" >'
3246
+			   . esc_html__('learn more about how message templates works', 'event_espresso')
3247
+			   . '</a>';
3248
+	}
3249
+
3250
+
3251
+	/**
3252
+	 * Used for setting up messenger/message type activation.  This loads up the initial view.  The rest is handled by
3253
+	 * ajax and other routes.
3254
+	 *
3255
+	 * @return void
3256
+	 * @throws DomainException
3257
+	 */
3258
+	protected function _settings()
3259
+	{
3260
+
3261
+
3262
+		$this->_set_m_mt_settings();
3263
+
3264
+		$selected_messenger = isset($this->_req_data['selected_messenger'])
3265
+			? $this->_req_data['selected_messenger']
3266
+			: 'email';
3267
+
3268
+		// let's setup the messenger tabs
3269
+		$this->_template_args['admin_page_header'] = EEH_Tabbed_Content::tab_text_links(
3270
+			$this->_m_mt_settings['messenger_tabs'],
3271
+			'messenger_links',
3272
+			'|',
3273
+			$selected_messenger
3274
+		);
3275
+		$this->_template_args['before_admin_page_content'] = '<div class="ui-widget ui-helper-clearfix">';
3276
+		$this->_template_args['after_admin_page_content'] = '</div><!-- end .ui-widget -->';
3277
+
3278
+		$this->display_admin_page_with_sidebar();
3279
+	}
3280
+
3281
+
3282
+	/**
3283
+	 * This sets the $_m_mt_settings property for when needed (used on the Messages settings page)
3284
+	 *
3285
+	 * @access protected
3286
+	 * @return void
3287
+	 * @throws DomainException
3288
+	 */
3289
+	protected function _set_m_mt_settings()
3290
+	{
3291
+		// first if this is already set then lets get out no need to regenerate data.
3292
+		if (! empty($this->_m_mt_settings)) {
3293
+			return;
3294
+		}
3295
+
3296
+		// get all installed messengers and message_types
3297
+		/** @type EE_messenger[] $messengers */
3298
+		$messengers = $this->_message_resource_manager->installed_messengers();
3299
+		/** @type EE_message_type[] $message_types */
3300
+		$message_types = $this->_message_resource_manager->installed_message_types();
3301
+
3302
+
3303
+		// assemble the array for the _tab_text_links helper
3304
+
3305
+		foreach ($messengers as $messenger) {
3306
+			$this->_m_mt_settings['messenger_tabs'][ $messenger->name ] = array(
3307
+				'label' => ucwords($messenger->label['singular']),
3308
+				'class' => $this->_message_resource_manager->is_messenger_active($messenger->name)
3309
+					? 'messenger-active'
3310
+					: '',
3311
+				'href'  => $messenger->name,
3312
+				'title' => esc_html__('Modify this Messenger', 'event_espresso'),
3313
+				'slug'  => $messenger->name,
3314
+				'obj'   => $messenger,
3315
+			);
3316
+
3317
+
3318
+			$message_types_for_messenger = $messenger->get_valid_message_types();
3319
+
3320
+			foreach ($message_types as $message_type) {
3321
+				// first we need to verify that this message type is valid with this messenger. Cause if it isn't then
3322
+				// it shouldn't show in either the inactive OR active metabox.
3323
+				if (! in_array($message_type->name, $message_types_for_messenger, true)) {
3324
+					continue;
3325
+				}
3326
+
3327
+				$a_or_i = $this->_message_resource_manager->is_message_type_active_for_messenger(
3328
+					$messenger->name,
3329
+					$message_type->name
3330
+				)
3331
+					? 'active'
3332
+					: 'inactive';
3333
+
3334
+				$this->_m_mt_settings['message_type_tabs'][ $messenger->name ][ $a_or_i ][ $message_type->name ] = array(
3335
+					'label'    => ucwords($message_type->label['singular']),
3336
+					'class'    => 'message-type-' . $a_or_i,
3337
+					'slug_id'  => $message_type->name . '-messagetype-' . $messenger->name,
3338
+					'mt_nonce' => wp_create_nonce($message_type->name . '_nonce'),
3339
+					'href'     => 'espresso_' . $message_type->name . '_message_type_settings',
3340
+					'title'    => $a_or_i === 'active'
3341
+						? esc_html__('Drag this message type to the Inactive window to deactivate', 'event_espresso')
3342
+						: esc_html__('Drag this message type to the messenger to activate', 'event_espresso'),
3343
+					'content'  => $a_or_i === 'active'
3344
+						? $this->_message_type_settings_content($message_type, $messenger, true)
3345
+						: $this->_message_type_settings_content($message_type, $messenger),
3346
+					'slug'     => $message_type->name,
3347
+					'active'   => $a_or_i === 'active',
3348
+					'obj'      => $message_type,
3349
+				);
3350
+			}
3351
+		}
3352
+	}
3353
+
3354
+
3355
+	/**
3356
+	 * This just prepares the content for the message type settings
3357
+	 *
3358
+	 * @param  EE_message_type $message_type The message type object
3359
+	 * @param  EE_messenger    $messenger    The messenger object
3360
+	 * @param  boolean         $active       Whether the message type is active or not
3361
+	 * @return string html output for the content
3362
+	 * @throws DomainException
3363
+	 */
3364
+	protected function _message_type_settings_content($message_type, $messenger, $active = false)
3365
+	{
3366
+		// get message type fields
3367
+		$fields = $message_type->get_admin_settings_fields();
3368
+		$settings_template_args['template_form_fields'] = '';
3369
+
3370
+		if (! empty($fields) && $active) {
3371
+			$existing_settings = $message_type->get_existing_admin_settings($messenger->name);
3372
+			foreach ($fields as $fldname => $fldprops) {
3373
+				$field_id = $messenger->name . '-' . $message_type->name . '-' . $fldname;
3374
+				$template_form_field[ $field_id ] = array(
3375
+					'name'       => 'message_type_settings[' . $fldname . ']',
3376
+					'label'      => $fldprops['label'],
3377
+					'input'      => $fldprops['field_type'],
3378
+					'type'       => $fldprops['value_type'],
3379
+					'required'   => $fldprops['required'],
3380
+					'validation' => $fldprops['validation'],
3381
+					'value'      => isset($existing_settings[ $fldname ])
3382
+						? $existing_settings[ $fldname ]
3383
+						: $fldprops['default'],
3384
+					'options'    => isset($fldprops['options'])
3385
+						? $fldprops['options']
3386
+						: array(),
3387
+					'default'    => isset($existing_settings[ $fldname ])
3388
+						? $existing_settings[ $fldname ]
3389
+						: $fldprops['default'],
3390
+					'css_class'  => 'no-drag',
3391
+					'format'     => $fldprops['format'],
3392
+				);
3393
+			}
3394
+
3395
+
3396
+			$settings_template_args['template_form_fields'] = ! empty($template_form_field)
3397
+				? $this->_generate_admin_form_fields(
3398
+					$template_form_field,
3399
+					'string',
3400
+					'ee_mt_activate_form'
3401
+				)
3402
+				: '';
3403
+		}
3404
+
3405
+		$settings_template_args['description'] = $message_type->description;
3406
+		// we also need some hidden fields
3407
+		$settings_template_args['hidden_fields'] = array(
3408
+			'message_type_settings[messenger]'    => array(
3409
+				'type'  => 'hidden',
3410
+				'value' => $messenger->name,
3411
+			),
3412
+			'message_type_settings[message_type]' => array(
3413
+				'type'  => 'hidden',
3414
+				'value' => $message_type->name,
3415
+			),
3416
+			'type'                                => array(
3417
+				'type'  => 'hidden',
3418
+				'value' => 'message_type',
3419
+			),
3420
+		);
3421
+
3422
+		$settings_template_args['hidden_fields'] = $this->_generate_admin_form_fields(
3423
+			$settings_template_args['hidden_fields'],
3424
+			'array'
3425
+		);
3426
+		$settings_template_args['show_form'] = empty($settings_template_args['template_form_fields'])
3427
+			? ' hidden'
3428
+			: '';
3429
+
3430
+
3431
+		$template = EE_MSG_TEMPLATE_PATH . 'ee_msg_mt_settings_content.template.php';
3432
+		$content = EEH_Template::display_template($template, $settings_template_args, true);
3433
+
3434
+		return $content;
3435
+	}
3436
+
3437
+
3438
+	/**
3439
+	 * Generate all the metaboxes for the message types and register them for the messages settings page.
3440
+	 *
3441
+	 * @access protected
3442
+	 * @return void
3443
+	 * @throws DomainException
3444
+	 */
3445
+	protected function _messages_settings_metaboxes()
3446
+	{
3447
+		$this->_set_m_mt_settings();
3448
+		$m_boxes = $mt_boxes = array();
3449
+		$m_template_args = $mt_template_args = array();
3450
+
3451
+		$selected_messenger = isset($this->_req_data['selected_messenger'])
3452
+			? $this->_req_data['selected_messenger']
3453
+			: 'email';
3454
+
3455
+		if (isset($this->_m_mt_settings['messenger_tabs'])) {
3456
+			foreach ($this->_m_mt_settings['messenger_tabs'] as $messenger => $tab_array) {
3457
+				$hide_on_message = $this->_message_resource_manager->is_messenger_active($messenger) ? '' : 'hidden';
3458
+				$hide_off_message = $this->_message_resource_manager->is_messenger_active($messenger) ? 'hidden' : '';
3459
+				// messenger meta boxes
3460
+				$active = $selected_messenger === $messenger;
3461
+				$active_mt_tabs = isset(
3462
+					$this->_m_mt_settings['message_type_tabs'][ $messenger ]['active']
3463
+				)
3464
+					? $this->_m_mt_settings['message_type_tabs'][ $messenger ]['active']
3465
+					: '';
3466
+				$m_boxes[ $messenger . '_a_box' ] = sprintf(
3467
+					esc_html__('%s Settings', 'event_espresso'),
3468
+					$tab_array['label']
3469
+				);
3470
+				$m_template_args[ $messenger . '_a_box' ] = array(
3471
+					'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3472
+					'inactive_message_types' => isset(
3473
+						$this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3474
+					)
3475
+						? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3476
+						: '',
3477
+					'content'                => $this->_get_messenger_box_content($tab_array['obj']),
3478
+					'hidden'                 => $active ? '' : ' hidden',
3479
+					'hide_on_message'        => $hide_on_message,
3480
+					'messenger'              => $messenger,
3481
+					'active'                 => $active,
3482
+				);
3483
+				// message type meta boxes
3484
+				// (which is really just the inactive container for each messenger
3485
+				// showing inactive message types for that messenger)
3486
+				$mt_boxes[ $messenger . '_i_box' ] = esc_html__('Inactive Message Types', 'event_espresso');
3487
+				$mt_template_args[ $messenger . '_i_box' ] = array(
3488
+					'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3489
+					'inactive_message_types' => isset(
3490
+						$this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3491
+					)
3492
+						? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3493
+						: '',
3494
+					'hidden'                 => $active ? '' : ' hidden',
3495
+					'hide_on_message'        => $hide_on_message,
3496
+					'hide_off_message'       => $hide_off_message,
3497
+					'messenger'              => $messenger,
3498
+					'active'                 => $active,
3499
+				);
3500
+			}
3501
+		}
3502
+
3503
+
3504
+		// register messenger metaboxes
3505
+		$m_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_mt_meta_box.template.php';
3506
+		foreach ($m_boxes as $box => $label) {
3507
+			$callback_args = array('template_path' => $m_template_path, 'template_args' => $m_template_args[ $box ]);
3508
+			$msgr = str_replace('_a_box', '', $box);
3509
+			add_meta_box(
3510
+				'espresso_' . $msgr . '_settings',
3511
+				$label,
3512
+				function ($post, $metabox) {
3513
+					echo EEH_Template::display_template(
3514
+						$metabox["args"]["template_path"],
3515
+						$metabox["args"]["template_args"],
3516
+						true
3517
+					);
3518
+				},
3519
+				$this->_current_screen->id,
3520
+				'normal',
3521
+				'high',
3522
+				$callback_args
3523
+			);
3524
+		}
3525
+
3526
+		// register message type metaboxes
3527
+		$mt_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_meta_box.template.php';
3528
+		foreach ($mt_boxes as $box => $label) {
3529
+			$callback_args = array(
3530
+				'template_path' => $mt_template_path,
3531
+				'template_args' => $mt_template_args[ $box ],
3532
+			);
3533
+			$mt = str_replace('_i_box', '', $box);
3534
+			add_meta_box(
3535
+				'espresso_' . $mt . '_inactive_mts',
3536
+				$label,
3537
+				function ($post, $metabox) {
3538
+					echo EEH_Template::display_template(
3539
+						$metabox["args"]["template_path"],
3540
+						$metabox["args"]["template_args"],
3541
+						true
3542
+					);
3543
+				},
3544
+				$this->_current_screen->id,
3545
+				'side',
3546
+				'high',
3547
+				$callback_args
3548
+			);
3549
+		}
3550
+
3551
+		// register metabox for global messages settings but only when on the main site.  On single site installs this
3552
+		// will always result in the metabox showing, on multisite installs the metabox will only show on the main site.
3553
+		if (is_main_site()) {
3554
+			add_meta_box(
3555
+				'espresso_global_message_settings',
3556
+				esc_html__('Global Message Settings', 'event_espresso'),
3557
+				array($this, 'global_messages_settings_metabox_content'),
3558
+				$this->_current_screen->id,
3559
+				'normal',
3560
+				'low',
3561
+				array()
3562
+			);
3563
+		}
3564
+	}
3565
+
3566
+
3567
+	/**
3568
+	 *  This generates the content for the global messages settings metabox.
3569
+	 *
3570
+	 * @return string
3571
+	 * @throws EE_Error
3572
+	 * @throws InvalidArgumentException
3573
+	 * @throws ReflectionException
3574
+	 * @throws InvalidDataTypeException
3575
+	 * @throws InvalidInterfaceException
3576
+	 */
3577
+	public function global_messages_settings_metabox_content()
3578
+	{
3579
+		$form = $this->_generate_global_settings_form();
3580
+		echo $form->form_open(
3581
+			$this->add_query_args_and_nonce(array('action' => 'update_global_settings'), EE_MSG_ADMIN_URL),
3582
+			'POST'
3583
+		)
3584
+			 . $form->get_html()
3585
+			 . $form->form_close();
3586
+	}
3587
+
3588
+
3589
+	/**
3590
+	 * This generates and returns the form object for the global messages settings.
3591
+	 *
3592
+	 * @return EE_Form_Section_Proper
3593
+	 * @throws EE_Error
3594
+	 * @throws InvalidArgumentException
3595
+	 * @throws ReflectionException
3596
+	 * @throws InvalidDataTypeException
3597
+	 * @throws InvalidInterfaceException
3598
+	 */
3599
+	protected function _generate_global_settings_form()
3600
+	{
3601
+		EE_Registry::instance()->load_helper('HTML');
3602
+		/** @var EE_Network_Core_Config $network_config */
3603
+		$network_config = EE_Registry::instance()->NET_CFG->core;
3604
+
3605
+		return new EE_Form_Section_Proper(
3606
+			array(
3607
+				'name'            => 'global_messages_settings',
3608
+				'html_id'         => 'global_messages_settings',
3609
+				'html_class'      => 'form-table',
3610
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
3611
+				'subsections'     => apply_filters(
3612
+					'FHEE__Messages_Admin_Page__global_messages_settings_metabox_content__form_subsections',
3613
+					array(
3614
+						'do_messages_on_same_request' => new EE_Select_Input(
3615
+							array(
3616
+								true  => esc_html__("On the same request", "event_espresso"),
3617
+								false => esc_html__("On a separate request", "event_espresso"),
3618
+							),
3619
+							array(
3620
+								'default'         => $network_config->do_messages_on_same_request,
3621
+								'html_label_text' => esc_html__(
3622
+									'Generate and send all messages:',
3623
+									'event_espresso'
3624
+								),
3625
+								'html_help_text'  => esc_html__(
3626
+									'By default the messages system uses a more efficient means of processing messages on separate requests and utilizes the wp-cron scheduling system.  This makes things execute faster for people registering for your events.  However, if the wp-cron system is disabled on your site and there is no alternative in place, then you can change this so messages are always executed on the same request.',
3627
+									'event_espresso'
3628
+								),
3629
+							)
3630
+						),
3631
+						'delete_threshold'            => new EE_Select_Input(
3632
+							array(
3633
+								0  => esc_html__('Forever', 'event_espresso'),
3634
+								3  => esc_html__('3 Months', 'event_espresso'),
3635
+								6  => esc_html__('6 Months', 'event_espresso'),
3636
+								9  => esc_html__('9 Months', 'event_espresso'),
3637
+								12 => esc_html__('12 Months', 'event_espresso'),
3638
+								24 => esc_html__('24 Months', 'event_espresso'),
3639
+								36 => esc_html__('36 Months', 'event_espresso'),
3640
+							),
3641
+							array(
3642
+								'default'         => EE_Registry::instance()->CFG->messages->delete_threshold,
3643
+								'html_label_text' => esc_html__('Cleanup of old messages:', 'event_espresso'),
3644
+								'html_help_text'  => esc_html__(
3645
+									'You can control how long a record of processed messages is kept via this option.',
3646
+									'event_espresso'
3647
+								),
3648
+							)
3649
+						),
3650
+						'update_settings'             => new EE_Submit_Input(
3651
+							array(
3652
+								'default'         => esc_html__('Update', 'event_espresso'),
3653
+								'html_label_text' => '&nbsp',
3654
+							)
3655
+						),
3656
+					)
3657
+				),
3658
+			)
3659
+		);
3660
+	}
3661
+
3662
+
3663
+	/**
3664
+	 * This handles updating the global settings set on the admin page.
3665
+	 *
3666
+	 * @throws EE_Error
3667
+	 * @throws InvalidDataTypeException
3668
+	 * @throws InvalidInterfaceException
3669
+	 * @throws InvalidArgumentException
3670
+	 * @throws ReflectionException
3671
+	 */
3672
+	protected function _update_global_settings()
3673
+	{
3674
+		/** @var EE_Network_Core_Config $network_config */
3675
+		$network_config = EE_Registry::instance()->NET_CFG->core;
3676
+		$messages_config = EE_Registry::instance()->CFG->messages;
3677
+		$form = $this->_generate_global_settings_form();
3678
+		if ($form->was_submitted()) {
3679
+			$form->receive_form_submission();
3680
+			if ($form->is_valid()) {
3681
+				$valid_data = $form->valid_data();
3682
+				foreach ($valid_data as $property => $value) {
3683
+					$setter = 'set_' . $property;
3684
+					if (method_exists($network_config, $setter)) {
3685
+						$network_config->{$setter}($value);
3686
+					} elseif (property_exists($network_config, $property)
3687
+						&& $network_config->{$property} !== $value
3688
+					) {
3689
+						$network_config->{$property} = $value;
3690
+					} elseif (property_exists($messages_config, $property)
3691
+						&& $messages_config->{$property} !== $value
3692
+					) {
3693
+						$messages_config->{$property} = $value;
3694
+					}
3695
+				}
3696
+				// only update if the form submission was valid!
3697
+				EE_Registry::instance()->NET_CFG->update_config(true, false);
3698
+				EE_Registry::instance()->CFG->update_espresso_config();
3699
+				EE_Error::overwrite_success();
3700
+				EE_Error::add_success(__('Global message settings were updated', 'event_espresso'));
3701
+			}
3702
+		}
3703
+		$this->_redirect_after_action(0, '', '', array('action' => 'settings'), true);
3704
+	}
3705
+
3706
+
3707
+	/**
3708
+	 * this prepares the messenger tabs that can be dragged in and out of messenger boxes to activate/deactivate
3709
+	 *
3710
+	 * @param  array $tab_array This is an array of message type tab details used to generate the tabs
3711
+	 * @return string html formatted tabs
3712
+	 * @throws DomainException
3713
+	 */
3714
+	protected function _get_mt_tabs($tab_array)
3715
+	{
3716
+		$tab_array = (array) $tab_array;
3717
+		$template = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_mt_settings_tab_item.template.php';
3718
+		$tabs = '';
3719
+
3720
+		foreach ($tab_array as $tab) {
3721
+			$tabs .= EEH_Template::display_template($template, $tab, true);
3722
+		}
3723
+
3724
+		return $tabs;
3725
+	}
3726
+
3727
+
3728
+	/**
3729
+	 * This prepares the content of the messenger meta box admin settings
3730
+	 *
3731
+	 * @param  EE_messenger $messenger The messenger we're setting up content for
3732
+	 * @return string html formatted content
3733
+	 * @throws DomainException
3734
+	 */
3735
+	protected function _get_messenger_box_content(EE_messenger $messenger)
3736
+	{
3737
+
3738
+		$fields = $messenger->get_admin_settings_fields();
3739
+		$settings_template_args['template_form_fields'] = '';
3740
+
3741
+		// is $messenger active?
3742
+		$settings_template_args['active'] = $this->_message_resource_manager->is_messenger_active($messenger->name);
3743
+
3744
+
3745
+		if (! empty($fields)) {
3746
+			$existing_settings = $messenger->get_existing_admin_settings();
3747
+
3748
+			foreach ($fields as $fldname => $fldprops) {
3749
+				$field_id = $messenger->name . '-' . $fldname;
3750
+				$template_form_field[ $field_id ] = array(
3751
+					'name'       => 'messenger_settings[' . $field_id . ']',
3752
+					'label'      => $fldprops['label'],
3753
+					'input'      => $fldprops['field_type'],
3754
+					'type'       => $fldprops['value_type'],
3755
+					'required'   => $fldprops['required'],
3756
+					'validation' => $fldprops['validation'],
3757
+					'value'      => isset($existing_settings[ $field_id ])
3758
+						? $existing_settings[ $field_id ]
3759
+						: $fldprops['default'],
3760
+					'css_class'  => '',
3761
+					'format'     => $fldprops['format'],
3762
+				);
3763
+			}
3764
+
3765
+
3766
+			$settings_template_args['template_form_fields'] = ! empty($template_form_field)
3767
+				? $this->_generate_admin_form_fields($template_form_field, 'string', 'ee_m_activate_form')
3768
+				: '';
3769
+		}
3770
+
3771
+		// we also need some hidden fields
3772
+		$settings_template_args['hidden_fields'] = array(
3773
+			'messenger_settings[messenger]' => array(
3774
+				'type'  => 'hidden',
3775
+				'value' => $messenger->name,
3776
+			),
3777
+			'type'                          => array(
3778
+				'type'  => 'hidden',
3779
+				'value' => 'messenger',
3780
+			),
3781
+		);
3782
+
3783
+		// make sure any active message types that are existing are included in the hidden fields
3784
+		if (isset($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'])) {
3785
+			foreach ($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'] as $mt => $values) {
3786
+				$settings_template_args['hidden_fields'][ 'messenger_settings[message_types][' . $mt . ']' ] = array(
3787
+					'type'  => 'hidden',
3788
+					'value' => $mt,
3789
+				);
3790
+			}
3791
+		}
3792
+		$settings_template_args['hidden_fields'] = $this->_generate_admin_form_fields(
3793
+			$settings_template_args['hidden_fields'],
3794
+			'array'
3795
+		);
3796
+		$active = $this->_message_resource_manager->is_messenger_active($messenger->name);
3797
+
3798
+		$settings_template_args['messenger'] = $messenger->name;
3799
+		$settings_template_args['description'] = $messenger->description;
3800
+		$settings_template_args['show_hide_edit_form'] = $active ? '' : ' hidden';
3801
+
3802
+
3803
+		$settings_template_args['show_hide_edit_form'] = $this->_message_resource_manager->is_messenger_active(
3804
+			$messenger->name
3805
+		)
3806
+			? $settings_template_args['show_hide_edit_form']
3807
+			: ' hidden';
3808
+
3809
+		$settings_template_args['show_hide_edit_form'] = empty($settings_template_args['template_form_fields'])
3810
+			? ' hidden'
3811
+			: $settings_template_args['show_hide_edit_form'];
3812
+
3813
+
3814
+		$settings_template_args['on_off_action'] = $active ? 'messenger-off' : 'messenger-on';
3815
+		$settings_template_args['nonce'] = wp_create_nonce('activate_' . $messenger->name . '_toggle_nonce');
3816
+		$settings_template_args['on_off_status'] = $active ? true : false;
3817
+		$template = EE_MSG_TEMPLATE_PATH . 'ee_msg_m_settings_content.template.php';
3818
+		$content = EEH_Template::display_template(
3819
+			$template,
3820
+			$settings_template_args,
3821
+			true
3822
+		);
3823
+
3824
+		return $content;
3825
+	}
3826
+
3827
+
3828
+	/**
3829
+	 * used by ajax on the messages settings page to activate|deactivate the messenger
3830
+	 *
3831
+	 * @throws DomainException
3832
+	 * @throws EE_Error
3833
+	 * @throws InvalidDataTypeException
3834
+	 * @throws InvalidInterfaceException
3835
+	 * @throws InvalidArgumentException
3836
+	 * @throws ReflectionException
3837
+	 */
3838
+	public function activate_messenger_toggle()
3839
+	{
3840
+		$success = true;
3841
+		$this->_prep_default_response_for_messenger_or_message_type_toggle();
3842
+		// let's check that we have required data
3843
+		if (! isset($this->_req_data['messenger'])) {
3844
+			EE_Error::add_error(
3845
+				esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
3846
+				__FILE__,
3847
+				__FUNCTION__,
3848
+				__LINE__
3849
+			);
3850
+			$success = false;
3851
+		}
3852
+
3853
+		// do a nonce check here since we're not arriving via a normal route
3854
+		$nonce = isset($this->_req_data['activate_nonce'])
3855
+			? sanitize_text_field($this->_req_data['activate_nonce'])
3856
+			: '';
3857
+		$nonce_ref = 'activate_' . $this->_req_data['messenger'] . '_toggle_nonce';
3858
+
3859
+		$this->_verify_nonce($nonce, $nonce_ref);
3860
+
3861
+
3862
+		if (! isset($this->_req_data['status'])) {
3863
+			EE_Error::add_error(
3864
+				esc_html__(
3865
+					'Messenger status needed to know whether activation or deactivation is happening. No status is given',
3866
+					'event_espresso'
3867
+				),
3868
+				__FILE__,
3869
+				__FUNCTION__,
3870
+				__LINE__
3871
+			);
3872
+			$success = false;
3873
+		}
3874
+
3875
+		// do check to verify we have a valid status.
3876
+		$status = $this->_req_data['status'];
3877
+
3878
+		if ($status !== 'off' && $status !== 'on') {
3879
+			EE_Error::add_error(
3880
+				sprintf(
3881
+					esc_html__('The given status (%s) is not valid. Must be "off" or "on"', 'event_espresso'),
3882
+					$this->_req_data['status']
3883
+				),
3884
+				__FILE__,
3885
+				__FUNCTION__,
3886
+				__LINE__
3887
+			);
3888
+			$success = false;
3889
+		}
3890
+
3891
+		if ($success) {
3892
+			// made it here?  Stop dawdling then!!
3893
+			$success = $status === 'off'
3894
+				? $this->_deactivate_messenger($this->_req_data['messenger'])
3895
+				: $this->_activate_messenger($this->_req_data['messenger']);
3896
+		}
3897
+
3898
+		$this->_template_args['success'] = $success;
3899
+
3900
+		// no special instructions so let's just do the json return (which should automatically do all the special stuff).
3901
+		$this->_return_json();
3902
+	}
3903
+
3904
+
3905
+	/**
3906
+	 * used by ajax from the messages settings page to activate|deactivate a message type
3907
+	 *
3908
+	 * @throws DomainException
3909
+	 * @throws EE_Error
3910
+	 * @throws ReflectionException
3911
+	 * @throws InvalidDataTypeException
3912
+	 * @throws InvalidInterfaceException
3913
+	 * @throws InvalidArgumentException
3914
+	 */
3915
+	public function activate_mt_toggle()
3916
+	{
3917
+		$success = true;
3918
+		$this->_prep_default_response_for_messenger_or_message_type_toggle();
3919
+
3920
+		// let's make sure we have the necessary data
3921
+		if (! isset($this->_req_data['message_type'])) {
3922
+			EE_Error::add_error(
3923
+				esc_html__('Message Type name needed to toggle activation. None given', 'event_espresso'),
3924
+				__FILE__,
3925
+				__FUNCTION__,
3926
+				__LINE__
3927
+			);
3928
+			$success = false;
3929
+		}
3930
+
3931
+		if (! isset($this->_req_data['messenger'])) {
3932
+			EE_Error::add_error(
3933
+				esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
3934
+				__FILE__,
3935
+				__FUNCTION__,
3936
+				__LINE__
3937
+			);
3938
+			$success = false;
3939
+		}
3940
+
3941
+		if (! isset($this->_req_data['status'])) {
3942
+			EE_Error::add_error(
3943
+				esc_html__(
3944
+					'Messenger status needed to know whether activation or deactivation is happening. No status is given',
3945
+					'event_espresso'
3946
+				),
3947
+				__FILE__,
3948
+				__FUNCTION__,
3949
+				__LINE__
3950
+			);
3951
+			$success = false;
3952
+		}
3953
+
3954
+
3955
+		// do check to verify we have a valid status.
3956
+		$status = $this->_req_data['status'];
3957
+
3958
+		if ($status !== 'activate' && $status !== 'deactivate') {
3959
+			EE_Error::add_error(
3960
+				sprintf(
3961
+					esc_html__('The given status (%s) is not valid. Must be "active" or "inactive"', 'event_espresso'),
3962
+					$this->_req_data['status']
3963
+				),
3964
+				__FILE__,
3965
+				__FUNCTION__,
3966
+				__LINE__
3967
+			);
3968
+			$success = false;
3969
+		}
3970
+
3971
+
3972
+		// do a nonce check here since we're not arriving via a normal route
3973
+		$nonce = isset($this->_req_data['mt_nonce']) ? sanitize_text_field($this->_req_data['mt_nonce']) : '';
3974
+		$nonce_ref = $this->_req_data['message_type'] . '_nonce';
3975
+
3976
+		$this->_verify_nonce($nonce, $nonce_ref);
3977
+
3978
+		if ($success) {
3979
+			// made it here? um, what are you waiting for then?
3980
+			$success = $status === 'deactivate'
3981
+				? $this->_deactivate_message_type_for_messenger(
3982
+					$this->_req_data['messenger'],
3983
+					$this->_req_data['message_type']
3984
+				)
3985
+				: $this->_activate_message_type_for_messenger(
3986
+					$this->_req_data['messenger'],
3987
+					$this->_req_data['message_type']
3988
+				);
3989
+		}
3990
+
3991
+		$this->_template_args['success'] = $success;
3992
+		$this->_return_json();
3993
+	}
3994
+
3995
+
3996
+	/**
3997
+	 * Takes care of processing activating a messenger and preparing the appropriate response.
3998
+	 *
3999
+	 * @param string $messenger_name The name of the messenger being activated
4000
+	 * @return bool
4001
+	 * @throws DomainException
4002
+	 * @throws EE_Error
4003
+	 * @throws InvalidArgumentException
4004
+	 * @throws ReflectionException
4005
+	 * @throws InvalidDataTypeException
4006
+	 * @throws InvalidInterfaceException
4007
+	 */
4008
+	protected function _activate_messenger($messenger_name)
4009
+	{
4010
+		/** @var EE_messenger $active_messenger This will be present because it can't be toggled if it isn't */
4011
+		$active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4012
+		$message_types_to_activate = $active_messenger instanceof EE_Messenger
4013
+			? $active_messenger->get_default_message_types()
4014
+			: array();
4015
+
4016
+		// ensure is active
4017
+		$this->_message_resource_manager->activate_messenger($messenger_name, $message_types_to_activate);
4018
+
4019
+		// set response_data for reload
4020
+		foreach ($message_types_to_activate as $message_type_name) {
4021
+			/** @var EE_message_type $message_type */
4022
+			$message_type = $this->_message_resource_manager->get_message_type($message_type_name);
4023
+			if ($this->_message_resource_manager->is_message_type_active_for_messenger(
4024
+				$messenger_name,
4025
+				$message_type_name
4026
+			)
4027
+				&& $message_type instanceof EE_message_type
4028
+			) {
4029
+				$this->_template_args['data']['active_mts'][] = $message_type_name;
4030
+				if ($message_type->get_admin_settings_fields()) {
4031
+					$this->_template_args['data']['mt_reload'][] = $message_type_name;
4032
+				}
4033
+			}
4034
+		}
4035
+
4036
+		// add success message for activating messenger
4037
+		return $this->_setup_response_message_for_activating_messenger_with_message_types($active_messenger);
4038
+	}
4039
+
4040
+
4041
+	/**
4042
+	 * Takes care of processing deactivating a messenger and preparing the appropriate response.
4043
+	 *
4044
+	 * @param string $messenger_name The name of the messenger being activated
4045
+	 * @return bool
4046
+	 * @throws DomainException
4047
+	 * @throws EE_Error
4048
+	 * @throws InvalidArgumentException
4049
+	 * @throws ReflectionException
4050
+	 * @throws InvalidDataTypeException
4051
+	 * @throws InvalidInterfaceException
4052
+	 */
4053
+	protected function _deactivate_messenger($messenger_name)
4054
+	{
4055
+		/** @var EE_messenger $active_messenger This will be present because it can't be toggled if it isn't */
4056
+		$active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4057
+		$this->_message_resource_manager->deactivate_messenger($messenger_name);
4058
+
4059
+		return $this->_setup_response_message_for_deactivating_messenger_with_message_types($active_messenger);
4060
+	}
4061
+
4062
+
4063
+	/**
4064
+	 * Takes care of processing activating a message type for a messenger and preparing the appropriate response.
4065
+	 *
4066
+	 * @param string $messenger_name    The name of the messenger the message type is being activated for.
4067
+	 * @param string $message_type_name The name of the message type being activated for the messenger
4068
+	 * @return bool
4069
+	 * @throws DomainException
4070
+	 * @throws EE_Error
4071
+	 * @throws InvalidArgumentException
4072
+	 * @throws ReflectionException
4073
+	 * @throws InvalidDataTypeException
4074
+	 * @throws InvalidInterfaceException
4075
+	 */
4076
+	protected function _activate_message_type_for_messenger($messenger_name, $message_type_name)
4077
+	{
4078
+		/** @var EE_messenger $active_messenger This will be present because it can't be toggled if it isn't */
4079
+		$active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4080
+		/** @var EE_message_type $message_type_to_activate This will be present because it can't be toggled if it isn't */
4081
+		$message_type_to_activate = $this->_message_resource_manager->get_message_type($message_type_name);
4082
+
4083
+		// ensure is active
4084
+		$this->_message_resource_manager->activate_messenger($messenger_name, $message_type_name);
4085
+
4086
+		// set response for load
4087
+		if ($this->_message_resource_manager->is_message_type_active_for_messenger(
4088
+			$messenger_name,
4089
+			$message_type_name
4090
+		)
4091
+		) {
4092
+			$this->_template_args['data']['active_mts'][] = $message_type_name;
4093
+			if ($message_type_to_activate->get_admin_settings_fields()) {
4094
+				$this->_template_args['data']['mt_reload'][] = $message_type_name;
4095
+			}
4096
+		}
4097
+
4098
+		return $this->_setup_response_message_for_activating_messenger_with_message_types(
4099
+			$active_messenger,
4100
+			$message_type_to_activate
4101
+		);
4102
+	}
4103
+
4104
+
4105
+	/**
4106
+	 * Takes care of processing deactivating a message type for a messenger and preparing the appropriate response.
4107
+	 *
4108
+	 * @param string $messenger_name    The name of the messenger the message type is being deactivated for.
4109
+	 * @param string $message_type_name The name of the message type being deactivated for the messenger
4110
+	 * @return bool
4111
+	 * @throws DomainException
4112
+	 * @throws EE_Error
4113
+	 * @throws InvalidArgumentException
4114
+	 * @throws ReflectionException
4115
+	 * @throws InvalidDataTypeException
4116
+	 * @throws InvalidInterfaceException
4117
+	 */
4118
+	protected function _deactivate_message_type_for_messenger($messenger_name, $message_type_name)
4119
+	{
4120
+		/** @var EE_messenger $active_messenger This will be present because it can't be toggled if it isn't */
4121
+		$active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4122
+		/** @var EE_message_type $message_type_to_activate This will be present because it can't be toggled if it isn't */
4123
+		$message_type_to_deactivate = $this->_message_resource_manager->get_message_type($message_type_name);
4124
+		$this->_message_resource_manager->deactivate_message_type_for_messenger($message_type_name, $messenger_name);
4125
+
4126
+		return $this->_setup_response_message_for_deactivating_messenger_with_message_types(
4127
+			$active_messenger,
4128
+			$message_type_to_deactivate
4129
+		);
4130
+	}
4131
+
4132
+
4133
+	/**
4134
+	 * This just initializes the defaults for activating messenger and message type responses.
4135
+	 */
4136
+	protected function _prep_default_response_for_messenger_or_message_type_toggle()
4137
+	{
4138
+		$this->_template_args['data']['active_mts'] = array();
4139
+		$this->_template_args['data']['mt_reload'] = array();
4140
+	}
4141
+
4142
+
4143
+	/**
4144
+	 * Setup appropriate response for activating a messenger and/or message types
4145
+	 *
4146
+	 * @param EE_messenger         $messenger
4147
+	 * @param EE_message_type|null $message_type
4148
+	 * @return bool
4149
+	 * @throws DomainException
4150
+	 * @throws EE_Error
4151
+	 * @throws InvalidArgumentException
4152
+	 * @throws ReflectionException
4153
+	 * @throws InvalidDataTypeException
4154
+	 * @throws InvalidInterfaceException
4155
+	 */
4156
+	protected function _setup_response_message_for_activating_messenger_with_message_types(
4157
+		$messenger,
4158
+		EE_Message_Type $message_type = null
4159
+	) {
4160
+		// if $messenger isn't a valid messenger object then get out.
4161
+		if (! $messenger instanceof EE_Messenger) {
4162
+			EE_Error::add_error(
4163
+				esc_html__('The messenger being activated is not a valid messenger', 'event_espresso'),
4164
+				__FILE__,
4165
+				__FUNCTION__,
4166
+				__LINE__
4167
+			);
4168
+
4169
+			return false;
4170
+		}
4171
+		// activated
4172
+		if ($this->_template_args['data']['active_mts']) {
4173
+			EE_Error::overwrite_success();
4174
+			// activated a message type with the messenger
4175
+			if ($message_type instanceof EE_message_type) {
4176
+				EE_Error::add_success(
4177
+					sprintf(
4178
+						esc_html__(
4179
+							'%s message type has been successfully activated with the %s messenger',
4180
+							'event_espresso'
4181
+						),
4182
+						ucwords($message_type->label['singular']),
4183
+						ucwords($messenger->label['singular'])
4184
+					)
4185
+				);
4186
+
4187
+				// if message type was invoice then let's make sure we activate the invoice payment method.
4188
+				if ($message_type->name === 'invoice') {
4189
+					EE_Registry::instance()->load_lib('Payment_Method_Manager');
4190
+					$pm = EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
4191
+					if ($pm instanceof EE_Payment_Method) {
4192
+						EE_Error::add_attention(
4193
+							esc_html__(
4194
+								'Activating the invoice message type also automatically activates the invoice payment method.  If you do not wish the invoice payment method to be active, or to change its settings, visit the payment method admin page.',
4195
+								'event_espresso'
4196
+							)
4197
+						);
4198
+					}
4199
+				}
4200
+				// just toggles the entire messenger
4201
+			} else {
4202
+				EE_Error::add_success(
4203
+					sprintf(
4204
+						esc_html__('%s messenger has been successfully activated', 'event_espresso'),
4205
+						ucwords($messenger->label['singular'])
4206
+					)
4207
+				);
4208
+			}
4209
+
4210
+			return true;
4211
+
4212
+			// possible error condition. This will happen when our active_mts data is empty because it is validated for actual active
4213
+			// message types after the activation process.  However its possible some messengers don't HAVE any default_message_types
4214
+			// in which case we just give a success message for the messenger being successfully activated.
4215
+		} else {
4216
+			if (! $messenger->get_default_message_types()) {
4217
+				// messenger doesn't have any default message types so still a success.
4218
+				EE_Error::add_success(
4219
+					sprintf(
4220
+						esc_html__('%s messenger was successfully activated.', 'event_espresso'),
4221
+						ucwords($messenger->label['singular'])
4222
+					)
4223
+				);
4224
+
4225
+				return true;
4226
+			} else {
4227
+				EE_Error::add_error(
4228
+					$message_type instanceof EE_message_type
4229
+						? sprintf(
4230
+							esc_html__(
4231
+								'%s message type was not successfully activated with the %s messenger',
4232
+								'event_espresso'
4233
+							),
4234
+							ucwords($message_type->label['singular']),
4235
+							ucwords($messenger->label['singular'])
4236
+						)
4237
+						: sprintf(
4238
+							esc_html__('%s messenger was not successfully activated', 'event_espresso'),
4239
+							ucwords($messenger->label['singular'])
4240
+						),
4241
+					__FILE__,
4242
+					__FUNCTION__,
4243
+					__LINE__
4244
+				);
4245
+
4246
+				return false;
4247
+			}
4248
+		}
4249
+	}
4250
+
4251
+
4252
+	/**
4253
+	 * This sets up the appropriate response for deactivating a messenger and/or message type.
4254
+	 *
4255
+	 * @param EE_messenger         $messenger
4256
+	 * @param EE_message_type|null $message_type
4257
+	 * @return bool
4258
+	 * @throws DomainException
4259
+	 * @throws EE_Error
4260
+	 * @throws InvalidArgumentException
4261
+	 * @throws ReflectionException
4262
+	 * @throws InvalidDataTypeException
4263
+	 * @throws InvalidInterfaceException
4264
+	 */
4265
+	protected function _setup_response_message_for_deactivating_messenger_with_message_types(
4266
+		$messenger,
4267
+		EE_message_type $message_type = null
4268
+	) {
4269
+		EE_Error::overwrite_success();
4270
+
4271
+		// if $messenger isn't a valid messenger object then get out.
4272
+		if (! $messenger instanceof EE_Messenger) {
4273
+			EE_Error::add_error(
4274
+				esc_html__('The messenger being deactivated is not a valid messenger', 'event_espresso'),
4275
+				__FILE__,
4276
+				__FUNCTION__,
4277
+				__LINE__
4278
+			);
4279
+
4280
+			return false;
4281
+		}
4282
+
4283
+		if ($message_type instanceof EE_message_type) {
4284
+			$message_type_name = $message_type->name;
4285
+			EE_Error::add_success(
4286
+				sprintf(
4287
+					esc_html__(
4288
+						'%s message type has been successfully deactivated for the %s messenger.',
4289
+						'event_espresso'
4290
+					),
4291
+					ucwords($message_type->label['singular']),
4292
+					ucwords($messenger->label['singular'])
4293
+				)
4294
+			);
4295
+		} else {
4296
+			$message_type_name = '';
4297
+			EE_Error::add_success(
4298
+				sprintf(
4299
+					esc_html__('%s messenger has been successfully deactivated.', 'event_espresso'),
4300
+					ucwords($messenger->label['singular'])
4301
+				)
4302
+			);
4303
+		}
4304
+
4305
+		// if messenger was html or message type was invoice then let's make sure we deactivate invoice payment method.
4306
+		if ($messenger->name === 'html' || $message_type_name === 'invoice') {
4307
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
4308
+			$count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method('invoice');
4309
+			if ($count_updated > 0) {
4310
+				$msg = $message_type_name === 'invoice'
4311
+					? esc_html__(
4312
+						'Deactivating the invoice message type also automatically deactivates the invoice payment method. In order for invoices to be generated the invoice message type must be active. If you completed this action by mistake, simply reactivate the invoice message type and then visit the payment methods admin page to reactivate the invoice payment method.',
4313
+						'event_espresso'
4314
+					)
4315
+					: esc_html__(
4316
+						'Deactivating the html messenger also automatically deactivates the invoice payment method.  In order for invoices to be generated the html messenger must be be active.  If you completed this action by mistake, simply reactivate the html messenger, then visit the payment methods admin page to reactivate the invoice payment method.',
4317
+						'event_espresso'
4318
+					);
4319
+				EE_Error::add_attention($msg);
4320
+			}
4321
+		}
4322
+
4323
+		return true;
4324
+	}
4325
+
4326
+
4327
+	/**
4328
+	 * handles updating a message type form on messenger activation IF the message type has settings fields. (via ajax)
4329
+	 *
4330
+	 * @throws DomainException
4331
+	 */
4332
+	public function update_mt_form()
4333
+	{
4334
+		if (! isset($this->_req_data['messenger']) || ! isset($this->_req_data['message_type'])) {
4335
+			EE_Error::add_error(
4336
+				esc_html__('Require message type or messenger to send an updated form', 'event_espresso'),
4337
+				__FILE__,
4338
+				__FUNCTION__,
4339
+				__LINE__
4340
+			);
4341
+			$this->_return_json();
4342
+		}
4343
+
4344
+		$message_types = $this->get_installed_message_types();
4345
+
4346
+		$message_type = $message_types[ $this->_req_data['message_type'] ];
4347
+		$messenger = $this->_message_resource_manager->get_active_messenger($this->_req_data['messenger']);
4348
+
4349
+		$content = $this->_message_type_settings_content(
4350
+			$message_type,
4351
+			$messenger,
4352
+			true
4353
+		);
4354
+		$this->_template_args['success'] = true;
4355
+		$this->_template_args['content'] = $content;
4356
+		$this->_return_json();
4357
+	}
4358
+
4359
+
4360
+	/**
4361
+	 * this handles saving the settings for a messenger or message type
4362
+	 *
4363
+	 */
4364
+	public function save_settings()
4365
+	{
4366
+		if (! isset($this->_req_data['type'])) {
4367
+			EE_Error::add_error(
4368
+				esc_html__(
4369
+					'Cannot save settings because type is unknown (messenger settings or messsage type settings?)',
4370
+					'event_espresso'
4371
+				),
4372
+				__FILE__,
4373
+				__FUNCTION__,
4374
+				__LINE__
4375
+			);
4376
+			$this->_template_args['error'] = true;
4377
+			$this->_return_json();
4378
+		}
4379
+
4380
+
4381
+		if ($this->_req_data['type'] === 'messenger') {
4382
+			// this should be an array.
4383
+			$settings = $this->_req_data['messenger_settings'];
4384
+			$messenger = $settings['messenger'];
4385
+			// let's setup the settings data
4386
+			foreach ($settings as $key => $value) {
4387
+				switch ($key) {
4388
+					case 'messenger':
4389
+						unset($settings['messenger']);
4390
+						break;
4391
+					case 'message_types':
4392
+						unset($settings['message_types']);
4393
+						break;
4394
+					default:
4395
+						$settings[ $key ] = $value;
4396
+						break;
4397
+				}
4398
+			}
4399
+			$this->_message_resource_manager->add_settings_for_messenger($messenger, $settings);
4400
+		} elseif ($this->_req_data['type'] === 'message_type') {
4401
+			$settings = $this->_req_data['message_type_settings'];
4402
+			$messenger = $settings['messenger'];
4403
+			$message_type = $settings['message_type'];
4404
+
4405
+			foreach ($settings as $key => $value) {
4406
+				switch ($key) {
4407
+					case 'messenger':
4408
+						unset($settings['messenger']);
4409
+						break;
4410
+					case 'message_type':
4411
+						unset($settings['message_type']);
4412
+						break;
4413
+					default:
4414
+						$settings[ $key ] = $value;
4415
+						break;
4416
+				}
4417
+			}
4418
+
4419
+			$this->_message_resource_manager->add_settings_for_message_type($messenger, $message_type, $settings);
4420
+		}
4421
+
4422
+		// okay we should have the data all setup.  Now we just update!
4423
+		$success = $this->_message_resource_manager->update_active_messengers_option();
4424
+
4425
+		if ($success) {
4426
+			EE_Error::add_success(__('Settings updated', 'event_espresso'));
4427
+		} else {
4428
+			EE_Error::add_error(
4429
+				esc_html__(
4430
+					'Settings did not get updated',
4431
+					'event_espresso'
4432
+				),
4433
+				__FILE__,
4434
+				__FUNCTION__,
4435
+				__LINE__
4436
+			);
4437
+		}
4438
+
4439
+		$this->_template_args['success'] = $success;
4440
+		$this->_return_json();
4441
+	}
4442
+
4443
+
4444
+
4445
+
4446
+	/**  EE MESSAGE PROCESSING ACTIONS **/
4447
+
4448
+
4449
+	/**
4450
+	 * This immediately generates any EE_Message ID's that are selected that are EEM_Message::status_incomplete
4451
+	 * However, this does not send immediately, it just queues for sending.
4452
+	 *
4453
+	 * @since 4.9.0
4454
+	 * @throws EE_Error
4455
+	 * @throws InvalidDataTypeException
4456
+	 * @throws InvalidInterfaceException
4457
+	 * @throws InvalidArgumentException
4458
+	 * @throws ReflectionException
4459
+	 */
4460
+	protected function _generate_now()
4461
+	{
4462
+		EED_Messages::generate_now($this->_get_msg_ids_from_request());
4463
+		$this->_redirect_after_action(false, '', '', array(), true);
4464
+	}
4465
+
4466
+
4467
+	/**
4468
+	 * This immediately generates AND sends any EE_Message's selected that are EEM_Message::status_incomplete or that
4469
+	 * are EEM_Message::status_resend or EEM_Message::status_idle
4470
+	 *
4471
+	 * @since 4.9.0
4472
+	 * @throws EE_Error
4473
+	 * @throws InvalidDataTypeException
4474
+	 * @throws InvalidInterfaceException
4475
+	 * @throws InvalidArgumentException
4476
+	 * @throws ReflectionException
4477
+	 */
4478
+	protected function _generate_and_send_now()
4479
+	{
4480
+		EED_Messages::generate_and_send_now($this->_get_msg_ids_from_request());
4481
+		$this->_redirect_after_action(false, '', '', array(), true);
4482
+	}
4483
+
4484
+
4485
+	/**
4486
+	 * This queues any EEM_Message::status_sent EE_Message ids in the request for resending.
4487
+	 *
4488
+	 * @since 4.9.0
4489
+	 * @throws EE_Error
4490
+	 * @throws InvalidDataTypeException
4491
+	 * @throws InvalidInterfaceException
4492
+	 * @throws InvalidArgumentException
4493
+	 * @throws ReflectionException
4494
+	 */
4495
+	protected function _queue_for_resending()
4496
+	{
4497
+		EED_Messages::queue_for_resending($this->_get_msg_ids_from_request());
4498
+		$this->_redirect_after_action(false, '', '', array(), true);
4499
+	}
4500
+
4501
+
4502
+	/**
4503
+	 *  This sends immediately any EEM_Message::status_idle or EEM_Message::status_resend messages in the queue
4504
+	 *
4505
+	 * @since 4.9.0
4506
+	 * @throws EE_Error
4507
+	 * @throws InvalidDataTypeException
4508
+	 * @throws InvalidInterfaceException
4509
+	 * @throws InvalidArgumentException
4510
+	 * @throws ReflectionException
4511
+	 */
4512
+	protected function _send_now()
4513
+	{
4514
+		EED_Messages::send_now($this->_get_msg_ids_from_request());
4515
+		$this->_redirect_after_action(false, '', '', array(), true);
4516
+	}
4517
+
4518
+
4519
+	/**
4520
+	 * Deletes EE_messages for IDs in the request.
4521
+	 *
4522
+	 * @since 4.9.0
4523
+	 * @throws EE_Error
4524
+	 * @throws InvalidDataTypeException
4525
+	 * @throws InvalidInterfaceException
4526
+	 * @throws InvalidArgumentException
4527
+	 */
4528
+	protected function _delete_ee_messages()
4529
+	{
4530
+		$msg_ids = $this->_get_msg_ids_from_request();
4531
+		$deleted_count = 0;
4532
+		foreach ($msg_ids as $msg_id) {
4533
+			if (EEM_Message::instance()->delete_by_ID($msg_id)) {
4534
+				$deleted_count++;
4535
+			}
4536
+		}
4537
+		if ($deleted_count) {
4538
+			EE_Error::add_success(
4539
+				esc_html(
4540
+					_n(
4541
+						'Message successfully deleted',
4542
+						'Messages successfully deleted',
4543
+						$deleted_count,
4544
+						'event_espresso'
4545
+					)
4546
+				)
4547
+			);
4548
+			$this->_redirect_after_action(
4549
+				false,
4550
+				'',
4551
+				'',
4552
+				array(),
4553
+				true
4554
+			);
4555
+		} else {
4556
+			EE_Error::add_error(
4557
+				_n('The message was not deleted.', 'The messages were not deleted', count($msg_ids), 'event_espresso'),
4558
+				__FILE__,
4559
+				__FUNCTION__,
4560
+				__LINE__
4561
+			);
4562
+			$this->_redirect_after_action(false, '', '', array(), true);
4563
+		}
4564
+	}
4565
+
4566
+
4567
+	/**
4568
+	 *  This looks for 'MSG_ID' key in the request and returns an array of MSG_ID's if present.
4569
+	 *
4570
+	 * @since 4.9.0
4571
+	 * @return array
4572
+	 */
4573
+	protected function _get_msg_ids_from_request()
4574
+	{
4575
+		if (! isset($this->_req_data['MSG_ID'])) {
4576
+			return array();
4577
+		}
4578
+
4579
+		return is_array($this->_req_data['MSG_ID'])
4580
+			? array_keys($this->_req_data['MSG_ID'])
4581
+			: array($this->_req_data['MSG_ID']);
4582
+	}
4583 4583
 }
Please login to merge, or discard this patch.
core/libraries/messages/EE_messenger.lib.php 2 patches
Indentation   +733 added lines, -733 removed lines patch added patch discarded remove patch
@@ -18,182 +18,182 @@  discard block
 block discarded – undo
18 18
 
19 19
 
20 20
 
21
-    /**
22
-     * This property holds the default message types associated with this messenger when it is activated. The values of the array must match a valid message type.
23
-     * This property gets set by the _set_default_message_types() method.
24
-     *
25
-     * @var array
26
-     */
27
-    protected $_default_message_types = array();
21
+	/**
22
+	 * This property holds the default message types associated with this messenger when it is activated. The values of the array must match a valid message type.
23
+	 * This property gets set by the _set_default_message_types() method.
24
+	 *
25
+	 * @var array
26
+	 */
27
+	protected $_default_message_types = array();
28 28
 
29 29
 
30 30
 
31 31
 
32
-    /**
33
-     * This property holds the message types that are valid for use with this messenger.
34
-     * It gets set by the _set_valid_message_types() method.
35
-     *
36
-     * @var array
37
-     */
38
-    protected $_valid_message_types = array();
32
+	/**
33
+	 * This property holds the message types that are valid for use with this messenger.
34
+	 * It gets set by the _set_valid_message_types() method.
35
+	 *
36
+	 * @var array
37
+	 */
38
+	protected $_valid_message_types = array();
39 39
 
40 40
 
41 41
 
42
-    /**
43
-     * Holds the configuration for the EE_Messages_Validator class to know how to validated the different fields. Note that the Validator will match each field here with the allowed shortcodes set in the "valid_shortcodes" array for the matched message type context.  So message types don't need to set a $_validator_config property.
44
-     *
45
-     * Remember, ALL fields must be declared in this array.  However, an empty value for the field means that the field will accept all valid shortcodes set for the given context in the message type (by default).
46
-     *
47
-     * Array should be in this format:
48
-     *
49
-     * array(
50
-     *  'field_name(i.e.to)' => array(
51
-     *      'shortcodes' => array('email'), //an array of shortcode groups (correspond to EE_Shortcodes library class) that are allowed in the field. Typically you can just include $this->_valid_shortcodes['field_name'] as the value here (because they will match).
52
-     *      'specific_shortcodes' => array( array('[EVENT_AUTHOR_EMAIL]' => __('Admin Email', 'event_espresso')), //if this index is present you can further restrict the field to ONLY specific shortcodes if an entire group isn't sufficient. Specific shortcodes need to be listed as an array with the index the shortcode and the value = the label.
53
-     *      'type' => 'email' //this is the field type and should match one of the validator types (see EE_Messages_Validator::validator() for all the possible types).  If not required you can just leave empty.,
54
-     *      'required' => array'[SHORTCODE]') //this is used to indicate the shortcodes that MUST be in the assembled array of shortcodes by the validator in order for this field to be included in validation.  Otherwise the validator will always assign shortcodes for this field (regardless of whether the field settings for the given messenger/message_type/context use the field or not.).. please note, this does NOT mean that the shortcodes listed here MUST be in the given field.
55
-     *  )
56
-     * )
57
-     *
58
-     * @var array
59
-     */
60
-    protected $_validator_config = array();
42
+	/**
43
+	 * Holds the configuration for the EE_Messages_Validator class to know how to validated the different fields. Note that the Validator will match each field here with the allowed shortcodes set in the "valid_shortcodes" array for the matched message type context.  So message types don't need to set a $_validator_config property.
44
+	 *
45
+	 * Remember, ALL fields must be declared in this array.  However, an empty value for the field means that the field will accept all valid shortcodes set for the given context in the message type (by default).
46
+	 *
47
+	 * Array should be in this format:
48
+	 *
49
+	 * array(
50
+	 *  'field_name(i.e.to)' => array(
51
+	 *      'shortcodes' => array('email'), //an array of shortcode groups (correspond to EE_Shortcodes library class) that are allowed in the field. Typically you can just include $this->_valid_shortcodes['field_name'] as the value here (because they will match).
52
+	 *      'specific_shortcodes' => array( array('[EVENT_AUTHOR_EMAIL]' => __('Admin Email', 'event_espresso')), //if this index is present you can further restrict the field to ONLY specific shortcodes if an entire group isn't sufficient. Specific shortcodes need to be listed as an array with the index the shortcode and the value = the label.
53
+	 *      'type' => 'email' //this is the field type and should match one of the validator types (see EE_Messages_Validator::validator() for all the possible types).  If not required you can just leave empty.,
54
+	 *      'required' => array'[SHORTCODE]') //this is used to indicate the shortcodes that MUST be in the assembled array of shortcodes by the validator in order for this field to be included in validation.  Otherwise the validator will always assign shortcodes for this field (regardless of whether the field settings for the given messenger/message_type/context use the field or not.).. please note, this does NOT mean that the shortcodes listed here MUST be in the given field.
55
+	 *  )
56
+	 * )
57
+	 *
58
+	 * @var array
59
+	 */
60
+	protected $_validator_config = array();
61 61
 
62 62
 
63 63
 
64
-    /**
65
-     * This will hold the EEM_message_templates model for interacting with the database and retrieving active templates for the messenger
66
-     * @var object
67
-     */
68
-    protected $_EEM_data;
64
+	/**
65
+	 * This will hold the EEM_message_templates model for interacting with the database and retrieving active templates for the messenger
66
+	 * @var object
67
+	 */
68
+	protected $_EEM_data;
69 69
 
70 70
 
71 71
 
72
-    /**
73
-     * this property just holds an array of the various template refs.
74
-     * @var array
75
-     */
76
-    protected $_template_fields = array();
72
+	/**
73
+	 * this property just holds an array of the various template refs.
74
+	 * @var array
75
+	 */
76
+	protected $_template_fields = array();
77 77
 
78 78
 
79 79
 
80 80
 
81
-    /**
82
-     * This holds an array of the arguments used in parsing a template for the sender.
83
-     * @var array
84
-     */
85
-    protected $_template_args = array();
81
+	/**
82
+	 * This holds an array of the arguments used in parsing a template for the sender.
83
+	 * @var array
84
+	 */
85
+	protected $_template_args = array();
86 86
 
87 87
 
88 88
 
89 89
 
90 90
 
91 91
 
92
-    /**
93
-     * This property will hold the configuration for any test settings fields that are required for the "test" button that is used to trigger an actual test of this messenger
94
-     *
95
-     * @protected
96
-     * @var array
97
-     */
98
-    protected $_test_settings_fields = array();
92
+	/**
93
+	 * This property will hold the configuration for any test settings fields that are required for the "test" button that is used to trigger an actual test of this messenger
94
+	 *
95
+	 * @protected
96
+	 * @var array
97
+	 */
98
+	protected $_test_settings_fields = array();
99 99
 
100 100
 
101 101
 
102 102
 
103 103
 
104 104
 
105
-    /**
106
-     * This will hold the EE_Messages_Template_Pack object when set on the messenger.  This is set via the validate and setup method which grabs the template pack from the incoming messages object.
107
-     *
108
-     * @since 4.5.0
109
-     *
110
-     * @var EE_Messages_Template_Pack
111
-     */
112
-    protected $_tmp_pack;
105
+	/**
106
+	 * This will hold the EE_Messages_Template_Pack object when set on the messenger.  This is set via the validate and setup method which grabs the template pack from the incoming messages object.
107
+	 *
108
+	 * @since 4.5.0
109
+	 *
110
+	 * @var EE_Messages_Template_Pack
111
+	 */
112
+	protected $_tmp_pack;
113 113
 
114 114
 
115 115
 
116 116
 
117
-    /**
118
-     * This will hold the variation to use when performing a send.  It is set via the validate and setup method which grabs the variation from the incoming messages object on the send method.
119
-     *
120
-     * @since 4.5.0
121
-     *
122
-     * @var string
123
-     */
124
-    protected $_variation;
117
+	/**
118
+	 * This will hold the variation to use when performing a send.  It is set via the validate and setup method which grabs the variation from the incoming messages object on the send method.
119
+	 *
120
+	 * @since 4.5.0
121
+	 *
122
+	 * @var string
123
+	 */
124
+	protected $_variation;
125 125
 
126 126
 
127 127
 
128 128
 
129 129
 
130
-    /**
131
-     * This property is a stdClass that holds labels for all the various supporting properties for this messenger.  These labels are set via the _set_supports_labels() method in children classes. Initially this will include the label for:
132
-     *
133
-     *  - template pack
134
-     *  - template variation
135
-     *
136
-     * @since 4.5.0
137
-     *
138
-     * @var stdClass
139
-     */
140
-    protected $_supports_labels;
130
+	/**
131
+	 * This property is a stdClass that holds labels for all the various supporting properties for this messenger.  These labels are set via the _set_supports_labels() method in children classes. Initially this will include the label for:
132
+	 *
133
+	 *  - template pack
134
+	 *  - template variation
135
+	 *
136
+	 * @since 4.5.0
137
+	 *
138
+	 * @var stdClass
139
+	 */
140
+	protected $_supports_labels;
141 141
 
142 142
 
143 143
 
144 144
 
145 145
 
146
-    /**
147
-     * This property is set when the send_message() method is called and holds the Message Type used to generate templates with this messenger for the messages.
148
-     *
149
-     * @var EE_message_type
150
-     */
151
-    protected $_incoming_message_type;
146
+	/**
147
+	 * This property is set when the send_message() method is called and holds the Message Type used to generate templates with this messenger for the messages.
148
+	 *
149
+	 * @var EE_message_type
150
+	 */
151
+	protected $_incoming_message_type;
152 152
 
153 153
 
154 154
 
155
-    /**
156
-     * This flag sets whether a messenger is activated by default  on installation (or reactivation) of EE core or not.
157
-     *
158
-     * @var bool
159
-     */
160
-    public $activate_on_install = false;
155
+	/**
156
+	 * This flag sets whether a messenger is activated by default  on installation (or reactivation) of EE core or not.
157
+	 *
158
+	 * @var bool
159
+	 */
160
+	public $activate_on_install = false;
161 161
 
162 162
 
163 163
 
164 164
 
165 165
 
166
-    public function __construct()
167
-    {
168
-        $this->_EEM_data = EEM_Message_Template_Group::instance();
169
-        $this->_messages_item_type = 'messenger';
166
+	public function __construct()
167
+	{
168
+		$this->_EEM_data = EEM_Message_Template_Group::instance();
169
+		$this->_messages_item_type = 'messenger';
170 170
 
171
-        parent::__construct();
171
+		parent::__construct();
172 172
 
173
-        $this->_set_test_settings_fields();
174
-        $this->_set_template_fields();
175
-        $this->_set_default_message_types();
176
-        $this->_set_valid_message_types();
177
-        $this->_set_validator_config();
173
+		$this->_set_test_settings_fields();
174
+		$this->_set_template_fields();
175
+		$this->_set_default_message_types();
176
+		$this->_set_valid_message_types();
177
+		$this->_set_validator_config();
178 178
 
179 179
 
180
-        $this->_supports_labels = new stdClass();
181
-        $this->_set_supports_labels();
182
-    }
180
+		$this->_supports_labels = new stdClass();
181
+		$this->_set_supports_labels();
182
+	}
183 183
 
184 184
 
185 185
 
186 186
 
187 187
 
188
-    /**
189
-     * _set_template_fields
190
-     * This sets up the fields that a messenger requires for the message to go out.
191
-     *
192
-     * @abstract
193
-     * @access  protected
194
-     * @return void
195
-     */
196
-    abstract protected function _set_template_fields();
188
+	/**
189
+	 * _set_template_fields
190
+	 * This sets up the fields that a messenger requires for the message to go out.
191
+	 *
192
+	 * @abstract
193
+	 * @access  protected
194
+	 * @return void
195
+	 */
196
+	abstract protected function _set_template_fields();
197 197
 
198 198
 
199 199
 
@@ -203,14 +203,14 @@  discard block
 block discarded – undo
203 203
 
204 204
 
205 205
 
206
-    /**
207
-     * This method sets the _default_message_type property (see definition in docs attached to property)
208
-     *
209
-     * @abstract
210
-     * @access protected
211
-     * @return void
212
-     */
213
-    abstract protected function _set_default_message_types();
206
+	/**
207
+	 * This method sets the _default_message_type property (see definition in docs attached to property)
208
+	 *
209
+	 * @abstract
210
+	 * @access protected
211
+	 * @return void
212
+	 */
213
+	abstract protected function _set_default_message_types();
214 214
 
215 215
 
216 216
 
@@ -218,15 +218,15 @@  discard block
 block discarded – undo
218 218
 
219 219
 
220 220
 
221
-    /**
222
-     * Sets the _valid_message_types property (see definition in cods attached to property)
223
-     *
224
-     * @since 4.5.0
225
-     *
226
-     * @abstract
227
-     * @return void
228
-     */
229
-    abstract protected function _set_valid_message_types();
221
+	/**
222
+	 * Sets the _valid_message_types property (see definition in cods attached to property)
223
+	 *
224
+	 * @since 4.5.0
225
+	 *
226
+	 * @abstract
227
+	 * @return void
228
+	 */
229
+	abstract protected function _set_valid_message_types();
230 230
 
231 231
 
232 232
 
@@ -234,171 +234,171 @@  discard block
 block discarded – undo
234 234
 
235 235
 
236 236
 
237
-    /**
238
-     * Child classes must declare the $_validator_config property using this method.
239
-     * See comments for $_validator_config for details on what it is used for.
240
-     *
241
-     * NOTE:  messengers should set an array of valid shortcodes for ALL scenarios.  The corresponding validator class (validators/{messenger}) can be used to restrict only certain shortcodes per template so users cannot add certain shortcodes.
242
-     *
243
-     * @access protected
244
-     * @return void
245
-     */
246
-    abstract protected function _set_validator_config();
237
+	/**
238
+	 * Child classes must declare the $_validator_config property using this method.
239
+	 * See comments for $_validator_config for details on what it is used for.
240
+	 *
241
+	 * NOTE:  messengers should set an array of valid shortcodes for ALL scenarios.  The corresponding validator class (validators/{messenger}) can be used to restrict only certain shortcodes per template so users cannot add certain shortcodes.
242
+	 *
243
+	 * @access protected
244
+	 * @return void
245
+	 */
246
+	abstract protected function _set_validator_config();
247 247
 
248 248
 
249 249
 
250 250
 
251 251
 
252 252
 
253
-    /**
254
-     * We just deliver the messages don't kill us!!  This method will need to be modified by child classes for whatever action is taken to actually send a message.
255
-     *
256
-     * @return bool|WP_Error
257
-     * @throw \Exception
258
-     */
259
-    abstract protected function _send_message();
253
+	/**
254
+	 * We just deliver the messages don't kill us!!  This method will need to be modified by child classes for whatever action is taken to actually send a message.
255
+	 *
256
+	 * @return bool|WP_Error
257
+	 * @throw \Exception
258
+	 */
259
+	abstract protected function _send_message();
260 260
 
261 261
 
262 262
 
263 263
 
264
-    /**
265
-     * We give you pretty previews of the messages!
266
-     * @return string html body for message content.
267
-     */
268
-    abstract protected function _preview();
264
+	/**
265
+	 * We give you pretty previews of the messages!
266
+	 * @return string html body for message content.
267
+	 */
268
+	abstract protected function _preview();
269 269
 
270 270
 
271 271
 
272 272
 
273
-    /**
274
-     * Used by messengers (or preview) for enqueueing any scripts or styles need in message generation.
275
-     *
276
-     * @since 4.5.0
277
-     *
278
-     * @return void
279
-     */
280
-    public function enqueue_scripts_styles()
281
-    {
282
-        do_action('AHEE__EE_messenger__enqueue_scripts_styles');
283
-    }
273
+	/**
274
+	 * Used by messengers (or preview) for enqueueing any scripts or styles need in message generation.
275
+	 *
276
+	 * @since 4.5.0
277
+	 *
278
+	 * @return void
279
+	 */
280
+	public function enqueue_scripts_styles()
281
+	{
282
+		do_action('AHEE__EE_messenger__enqueue_scripts_styles');
283
+	}
284 284
 
285 285
 
286 286
 
287 287
 
288 288
 
289
-    /**
290
-     * This is used to indicate whether a messenger must be sent immediately or not.
291
-     * eg. The HTML messenger will override this to return true because it should be displayed in user's browser right
292
-     * away.  The PDF messenger is similar.
293
-     *
294
-     * This flag thus overrides any priorities that may be set on the message type used to generate the message.
295
-     *
296
-     * Default for this is false.  So children classes must override this if they want a message to be executed immediately.
297
-     *
298
-     * @since  4.9.0
299
-     * @return bool
300
-     */
301
-    public function send_now()
302
-    {
303
-        return false;
304
-    }
289
+	/**
290
+	 * This is used to indicate whether a messenger must be sent immediately or not.
291
+	 * eg. The HTML messenger will override this to return true because it should be displayed in user's browser right
292
+	 * away.  The PDF messenger is similar.
293
+	 *
294
+	 * This flag thus overrides any priorities that may be set on the message type used to generate the message.
295
+	 *
296
+	 * Default for this is false.  So children classes must override this if they want a message to be executed immediately.
297
+	 *
298
+	 * @since  4.9.0
299
+	 * @return bool
300
+	 */
301
+	public function send_now()
302
+	{
303
+		return false;
304
+	}
305 305
 
306 306
 
307 307
 
308 308
 
309 309
 
310
-    /**
311
-     * This is a way for a messenger to indicate whether it allows an empty to field or not.
312
-     * Note: If the generated message is a for a preview, this value is ignored.
313
-     * @since 4.9.0
314
-     * @return bool
315
-     */
316
-    public function allow_empty_to_field()
317
-    {
318
-        return false;
319
-    }
310
+	/**
311
+	 * This is a way for a messenger to indicate whether it allows an empty to field or not.
312
+	 * Note: If the generated message is a for a preview, this value is ignored.
313
+	 * @since 4.9.0
314
+	 * @return bool
315
+	 */
316
+	public function allow_empty_to_field()
317
+	{
318
+		return false;
319
+	}
320 320
 
321 321
 
322 322
 
323 323
 
324 324
 
325
-    /**
326
-     * Sets the defaults for the _supports_labels property.  Can be overridden by child classes.
327
-     * @see property definition for info on how its formatted.
328
-     *
329
-     * @since 4.5.0;
330
-     * @return void
331
-     */
332
-    protected function _set_supports_labels()
333
-    {
334
-        $this->_set_supports_labels_defaults();
335
-    }
325
+	/**
326
+	 * Sets the defaults for the _supports_labels property.  Can be overridden by child classes.
327
+	 * @see property definition for info on how its formatted.
328
+	 *
329
+	 * @since 4.5.0;
330
+	 * @return void
331
+	 */
332
+	protected function _set_supports_labels()
333
+	{
334
+		$this->_set_supports_labels_defaults();
335
+	}
336 336
 
337 337
 
338 338
 
339 339
 
340 340
 
341
-    /**
342
-     * Sets the defaults for the _supports_labels property.
343
-     *
344
-     * @since 4.5.0
345
-     *
346
-     * @return void
347
-     */
348
-    private function _set_supports_labels_defaults()
349
-    {
350
-        $this->_supports_labels->template_pack = __('Template Structure', 'event_espresso');
351
-        $this->_supports_labels->template_variation = __('Template Style', 'event_espresso');
352
-        $this->_supports_labels->template_pack_description = __('Template Structure options are bundled structural changes for templates.', 'event_espresso');
341
+	/**
342
+	 * Sets the defaults for the _supports_labels property.
343
+	 *
344
+	 * @since 4.5.0
345
+	 *
346
+	 * @return void
347
+	 */
348
+	private function _set_supports_labels_defaults()
349
+	{
350
+		$this->_supports_labels->template_pack = __('Template Structure', 'event_espresso');
351
+		$this->_supports_labels->template_variation = __('Template Style', 'event_espresso');
352
+		$this->_supports_labels->template_pack_description = __('Template Structure options are bundled structural changes for templates.', 'event_espresso');
353 353
 
354
-        $this->_supports_labels->template_variation_description = __('These are different styles to choose from for the selected template structure.  Usually these affect things like font style, color, borders etc.  In some cases the styles will also make minor layout changes.', 'event_espresso');
354
+		$this->_supports_labels->template_variation_description = __('These are different styles to choose from for the selected template structure.  Usually these affect things like font style, color, borders etc.  In some cases the styles will also make minor layout changes.', 'event_espresso');
355 355
 
356
-        $this->_supports_labels = apply_filters('FHEE__EE_messenger___set_supports_labels_defaults___supports_labels', $this->_supports_labels, $this);
357
-    }
356
+		$this->_supports_labels = apply_filters('FHEE__EE_messenger___set_supports_labels_defaults___supports_labels', $this->_supports_labels, $this);
357
+	}
358 358
 
359 359
 
360 360
 
361 361
 
362 362
 
363
-    /**
364
-     * This returns the _supports_labels property.
365
-     *
366
-     * @since 4.5.0
367
-     *
368
-     * @return stdClass
369
-     */
370
-    public function get_supports_labels()
371
-    {
372
-        if (empty($this->_supports_labels->template_pack) || empty($this->_supports_labels->template_variation)) {
373
-            $this->_set_supports_labels_defaults();
374
-        }
375
-        return apply_filters('FHEE__EE_messenger__get_supports_labels', $this->_supports_labels, $this);
376
-    }
363
+	/**
364
+	 * This returns the _supports_labels property.
365
+	 *
366
+	 * @since 4.5.0
367
+	 *
368
+	 * @return stdClass
369
+	 */
370
+	public function get_supports_labels()
371
+	{
372
+		if (empty($this->_supports_labels->template_pack) || empty($this->_supports_labels->template_variation)) {
373
+			$this->_set_supports_labels_defaults();
374
+		}
375
+		return apply_filters('FHEE__EE_messenger__get_supports_labels', $this->_supports_labels, $this);
376
+	}
377 377
 
378 378
 
379 379
 
380 380
 
381
-    /**
382
-     * Used to retrieve a variation (typically the path/url to a css file)
383
-     *
384
-     * @since 4.5.0
385
-     *
386
-     * @param EE_Messages_Template_Pack $pack   The template pack used for retrieving the variation.
387
-     * @param string                    $message_type_name The name property of the message type that we need the variation for.
388
-     * @param bool                      $url   Whether to return url (true) or path (false). Default is false.
389
-     * @param string                    $type What variation type to return. Default is 'main'.
390
-     * @param string               $variation What variation for the template pack
391
-     * @param bool             $skip_filters This allows messengers to add a filter for another messengers get_variation but call skip filters on the callback so there is no recursion on apply_filters.
392
-     *
393
-     * @return string                    path or url for the requested variation.
394
-     */
395
-    public function get_variation(EE_Messages_Template_Pack $pack, $message_type_name, $url = false, $type = 'main', $variation = 'default', $skip_filters = false)
396
-    {
397
-        $this->_tmp_pack = $pack;
398
-        $variation_path = apply_filters('EE_messenger__get_variation__variation', false, $pack, $this->name, $message_type_name, $url, $type, $variation, $skip_filters);
399
-        $variation_path = empty($variation_path) ? $this->_tmp_pack->get_variation($this->name, $message_type_name, $type, $variation, $url, '.css', $skip_filters) : $variation_path;
400
-        return $variation_path;
401
-    }
381
+	/**
382
+	 * Used to retrieve a variation (typically the path/url to a css file)
383
+	 *
384
+	 * @since 4.5.0
385
+	 *
386
+	 * @param EE_Messages_Template_Pack $pack   The template pack used for retrieving the variation.
387
+	 * @param string                    $message_type_name The name property of the message type that we need the variation for.
388
+	 * @param bool                      $url   Whether to return url (true) or path (false). Default is false.
389
+	 * @param string                    $type What variation type to return. Default is 'main'.
390
+	 * @param string               $variation What variation for the template pack
391
+	 * @param bool             $skip_filters This allows messengers to add a filter for another messengers get_variation but call skip filters on the callback so there is no recursion on apply_filters.
392
+	 *
393
+	 * @return string                    path or url for the requested variation.
394
+	 */
395
+	public function get_variation(EE_Messages_Template_Pack $pack, $message_type_name, $url = false, $type = 'main', $variation = 'default', $skip_filters = false)
396
+	{
397
+		$this->_tmp_pack = $pack;
398
+		$variation_path = apply_filters('EE_messenger__get_variation__variation', false, $pack, $this->name, $message_type_name, $url, $type, $variation, $skip_filters);
399
+		$variation_path = empty($variation_path) ? $this->_tmp_pack->get_variation($this->name, $message_type_name, $type, $variation, $url, '.css', $skip_filters) : $variation_path;
400
+		return $variation_path;
401
+	}
402 402
 
403 403
 
404 404
 
@@ -406,490 +406,490 @@  discard block
 block discarded – undo
406 406
 
407 407
 
408 408
 
409
-    /**
410
-     * This just returns the default message types associated with this messenger when it is first activated.
411
-     *
412
-     * @access public
413
-     * @return array
414
-     */
415
-    public function get_default_message_types()
416
-    {
417
-        $class = get_class($this);
409
+	/**
410
+	 * This just returns the default message types associated with this messenger when it is first activated.
411
+	 *
412
+	 * @access public
413
+	 * @return array
414
+	 */
415
+	public function get_default_message_types()
416
+	{
417
+		$class = get_class($this);
418 418
 
419
-        // messenger specific filter
420
-        $default_types = apply_filters('FHEE__' . $class . '__get_default_message_types__default_types', $this->_default_message_types, $this);
419
+		// messenger specific filter
420
+		$default_types = apply_filters('FHEE__' . $class . '__get_default_message_types__default_types', $this->_default_message_types, $this);
421 421
 
422
-        // all messengers filter
423
-        $default_types = apply_filters('FHEE__EE_messenger__get_default_message_types__default_types', $default_types, $this);
424
-        return $default_types;
425
-    }
422
+		// all messengers filter
423
+		$default_types = apply_filters('FHEE__EE_messenger__get_default_message_types__default_types', $default_types, $this);
424
+		return $default_types;
425
+	}
426 426
 
427 427
 
428 428
 
429 429
 
430
-    /**
431
-     * Returns the valid message types associated with this messenger.
432
-     *
433
-     * @since 4.5.0
434
-     *
435
-     * @return array
436
-     */
437
-    public function get_valid_message_types()
438
-    {
439
-        $class = get_class($this);
440
-
441
-        // messenger specific filter
442
-        // messenger specific filter
443
-        $valid_types = apply_filters('FHEE__' . $class . '__get_valid_message_types__valid_types', $this->_valid_message_types, $this);
444
-
445
-        // all messengers filter
446
-        $valid_types = apply_filters('FHEE__EE_messenger__get_valid_message_types__valid_types', $valid_types, $this);
447
-        return $valid_types;
448
-    }
449
-
450
-
451
-
452
-
453
-
454
-    /**
455
-     * this is just used by the custom validators (EE_Messages_Validator classes) to modify the _validator_config for certain message_type/messenger combos where a context may only use certain shortcodes etc.
456
-     *
457
-     * @access public
458
-     * @param array $new_config Whatever is put in here will reset the _validator_config property
459
-     */
460
-    public function set_validator_config($new_config)
461
-    {
462
-        $this->_validator_config = $new_config;
463
-    }
464
-
465
-
466
-
467
-
468
-    /**
469
-     * This returns the _validator_config property
470
-     *
471
-     * @access public
472
-     * @return array
473
-     */
474
-    public function get_validator_config()
475
-    {
476
-        $class = get_class($this);
477
-
478
-        $config = apply_filters('FHEE__' . $class . '__get_validator_config', $this->_validator_config, $this);
479
-        $config = apply_filters('FHEE__EE_messenger__get_validator_config', $config, $this);
480
-        return $config;
481
-    }
482
-
483
-
484
-
485
-
486
-    /**
487
-     * this public method accepts a page slug (for an EE_admin page) and will return the response from the child class callback function if that page is registered via the `_admin_registered_page` property set by the child class.
488
-     *
489
-     * @param string $page the slug of the EE admin page
490
-     * @param array $message_types an array of active message type objects
491
-     * @param string $action the page action (to allow for more specific handling - i.e. edit vs. add pages)
492
-     * @param array $extra  This is just an extra argument that can be used to pass additional data for setting up page content.
493
-     * @access public
494
-     * @return string content for page
495
-     */
496
-    public function get_messenger_admin_page_content($page, $action = null, $extra = array(), $message_types = array())
497
-    {
498
-        return $this->_get_admin_page_content($page, $action, $extra, $message_types);
499
-    }
500
-
501
-
502
-
503
-    /**
504
-     * @param $message_types
505
-     * @param array $extra
506
-     * @return mixed|string
507
-     */
508
-    protected function _get_admin_content_events_edit($message_types, $extra)
509
-    {
510
-        // defaults
511
-        $template_args = array();
512
-        $selector_rows = '';
513
-
514
-        // we don't need message types here so we're just going to ignore. we do, however, expect the event id here. The event id is needed to provide a link to setup a custom template for this event.
515
-        $event_id = isset($extra['event']) ? $extra['event'] : null;
516
-
517
-        $template_wrapper_path = EE_LIBRARIES . 'messages/messenger/admin_templates/event_switcher_wrapper.template.php';
518
-        $template_row_path = EE_LIBRARIES . 'messages/messenger/admin_templates/event_switcher_row.template.php';
519
-
520
-        // array of template objects for global and custom (non-trashed) (but remember just for this messenger!)
521
-        $global_templates = EEM_Message_Template_Group::instance()->get_all(
522
-            array( array( 'MTP_messenger' => $this->name, 'MTP_is_global' => true, 'MTP_is_active' => true ) )
523
-        );
524
-        $templates_for_event = EEM_Message_Template_Group::instance()->get_all_custom_templates_by_event(
525
-            $event_id,
526
-            array(
527
-                'MTP_messenger' => $this->name,
528
-                'MTP_is_active' => true
529
-            )
530
-        );
531
-        $templates_for_event = !empty($templates_for_event) ? $templates_for_event : array();
532
-
533
-        // so we need to setup the rows for the selectors and we use the global mtpgs (cause those will the active message template groups)
534
-        foreach ($global_templates as $mtpgID => $mtpg) {
535
-            if ($mtpg instanceof EE_Message_Template_Group) {
536
-                // verify this message type is supposed to show on this page
537
-                $mtp_obj = $mtpg->message_type_obj();
538
-                if (! $mtp_obj instanceof EE_message_type) {
539
-                    continue;
540
-                }
541
-                $mtp_obj->admin_registered_pages = (array) $mtp_obj->admin_registered_pages;
542
-                if (! in_array('events_edit', $mtp_obj->admin_registered_pages)) {
543
-                    continue;
544
-                }
545
-                $select_values = array();
546
-                $select_values[ $mtpgID ] = __('Global', 'event_espresso');
547
-                $default_value = array_key_exists($mtpgID, $templates_for_event) && ! $mtpg->get('MTP_is_override') ? $mtpgID : null;
548
-                // if the override has been set for the global template, then that means even if there are custom templates already created we ignore them because of the set override.
549
-                if (! $mtpg->get('MTP_is_override')) {
550
-                    // any custom templates for this message type?
551
-                    $custom_templates = EEM_Message_Template_Group::instance()->get_custom_message_template_by_m_and_mt($this->name, $mtpg->message_type());
552
-                    foreach ($custom_templates as $cmtpgID => $cmtpg) {
553
-                        $select_values[ $cmtpgID ] = $cmtpg->name();
554
-                        $default_value = array_key_exists($cmtpgID, $templates_for_event) ? $cmtpgID : $default_value;
555
-                    }
556
-                }
557
-                // if there is no $default_value then we set it as the global
558
-                $default_value = empty($default_value) ? $mtpgID : $default_value;
559
-                $edit_url_query_args = [
560
-                    'page' => 'espresso_messages',
561
-                    'action' => 'edit_message_template',
562
-                    'id' => $default_value,
563
-                    'evt_id' => $event_id
564
-                ];
565
-                $edit_url = EEH_URL::add_query_args_and_nonce($edit_url_query_args, admin_url('admin.php'));
566
-                $create_url_query_args = [
567
-                    'page' => 'espresso_messages',
568
-                    'action' => 'add_new_message_template',
569
-                    'GRP_ID' => $default_value
570
-                ];
571
-                $create_url = EEH_URL::add_query_args_and_nonce($create_url_query_args, admin_url('admin.php'));
572
-                $st_args['mt_name'] = ucwords($mtp_obj->label['singular']);
573
-                $st_args['mt_slug'] = $mtpg->message_type();
574
-                $st_args['messenger_slug'] = $this->name;
575
-                $st_args['selector'] = EEH_Form_Fields::select_input('event_message_templates_relation[' . $mtpgID . ']', $select_values, $default_value, 'data-messenger="' . $this->name . '" data-messagetype="' . $mtpg->message_type() . '"', 'message-template-selector');
576
-                // note that  message template group that has override_all_custom set will remove the ability to set a custom message template based off of the global (and that also in turn overrides any other custom templates).
577
-                $st_args['create_button'] = $mtpg->get('MTP_is_override') ? '' : '<a data-messenger="' . $this->name . '" data-messagetype="' . $mtpg->message_type() . '" data-grpid="' . $default_value . '" target="_blank" href="' . $create_url . '" class="button button-small create-mtpg-button">' . __('Create New Custom', 'event_espresso') . '</a>';
578
-                $st_args['create_button'] = EE_Registry::instance()->CAP->current_user_can('ee_edit_messages', 'espresso_messages_add_new_message_template') ? $st_args['create_button'] : '';
579
-                $st_args['edit_button'] = EE_Registry::instance()->CAP->current_user_can('ee_edit_message', 'espresso_messages_edit_message_template', $mtpgID) ? '<a data-messagetype="' . $mtpg->message_type() . '" data-grpid="' . $default_value . '" target="_blank" href="' . $edit_url . '" class="button button-small edit-mtpg-button">' . __('Edit', 'event_espresso') . '</a>' : '';
580
-                $selector_rows .= EEH_Template::display_template($template_row_path, $st_args, true);
581
-            }
582
-        }
583
-
584
-        // if no selectors present then get out.
585
-        if (empty($selector_rows)) {
586
-            return '';
587
-        }
588
-
589
-        $template_args['selector_rows'] = $selector_rows;
590
-        return EEH_Template::display_template($template_wrapper_path, $template_args, true);
591
-    }
592
-
593
-
594
-
595
-
596
-
597
-
598
-    /**
599
-     * get_template_fields
600
-     *
601
-     * @access public
602
-     * @return array $this->_template_fields
603
-     */
604
-    public function get_template_fields()
605
-    {
606
-        $template_fields = apply_filters('FHEE__' . get_class($this) . '__get_template_fields', $this->_template_fields, $this);
607
-        $template_fields = apply_filters('FHEE__EE_messenger__get_template_fields', $template_fields, $this);
608
-        return $template_fields;
609
-    }
610
-
611
-
612
-
613
-
614
-    /** SETUP METHODS **/
615
-    /**
616
-     * The following method doesn't NEED to be used by child classes but might be modified by the specific messenger
617
-     * @param string $item
618
-     * @param mixed $value
619
-     */
620
-    protected function _set_template_value($item, $value)
621
-    {
622
-        if (array_key_exists($item, $this->_template_fields)) {
623
-            $prop = '_' . $item;
624
-            $this->{$prop}= $value;
625
-        }
626
-    }
627
-
628
-    /**
629
-     * Sets up the message for sending.
630
-     *
631
-     * @param  EE_message $message the message object that contains details about the message.
632
-     * @param EE_message_type $message_type The message type object used in combination with this messenger to generate the provided message.
633
-     *
634
-     * @return bool Very important that all messengers return bool for successful send or not.  Error messages can be
635
-     *              added to EE_Error.
636
-     *              true = message sent successfully
637
-     *              false = message not sent but can be retried (i.e. the failure might be just due to communication issues at the time of send).
638
-     *              Throwing a SendMessageException means the message failed sending and cannot be retried.
639
-     *
640
-     * @throws SendMessageException
641
-     */
642
-    final public function send_message($message, EE_message_type $message_type)
643
-    {
644
-        try {
645
-            $this->_validate_and_setup($message);
646
-            $this->_incoming_message_type = $message_type;
647
-            $response = $this->_send_message();
648
-            if ($response instanceof WP_Error) {
649
-                EE_Error::add_error($response->get_error_message(), __FILE__, __FUNCTION__, __LINE__);
650
-                $response = false;
651
-            }
652
-        } catch (\Exception $e) {
653
-            // convert to an instance of SendMessageException
654
-            throw new SendMessageException($e->getMessage());
655
-        }
656
-        return $response;
657
-    }
658
-
659
-
660
-
661
-    /**
662
-     * Sets up and returns message preview
663
-     * @param  EE_Message $message incoming message object
664
-     * @param EE_message_type $message_type This is whatever message type was used in combination with this messenger to generate the message.
665
-     * @param  bool   $send    true we will actually use the _send method (for test sends). FALSE we just return preview
666
-     * @return string          return the message html content
667
-     */
668
-    public function get_preview(EE_Message $message, EE_message_type $message_type, $send = false)
669
-    {
670
-        $this->_validate_and_setup($message);
671
-
672
-        $this->_incoming_message_type = $message_type;
673
-
674
-        if ($send) {
675
-            // are we overriding any existing template fields?
676
-            $settings = apply_filters(
677
-                'FHEE__EE_messenger__get_preview__messenger_test_settings',
678
-                $this->get_existing_test_settings(),
679
-                $this,
680
-                $send,
681
-                $message,
682
-                $message_type
683
-            );
684
-            if (! empty($settings)) {
685
-                foreach ($settings as $field => $value) {
686
-                    $this->_set_template_value($field, $value);
687
-                }
688
-            }
689
-        }
690
-
691
-        // enqueue preview js so that any links/buttons on the page are disabled.
692
-        if (! $send) {
693
-            // the below may seem like duplication.  However, typically if a messenger enqueues scripts/styles,
694
-            // it deregisters all existing wp scripts and styles first.  So the second hook ensures our previewer still gets setup.
695
-            add_action('admin_enqueue_scripts', array( $this, 'add_preview_script' ), 10);
696
-            add_action('wp_enqueue_scripts', array( $this, 'add_preview_script' ), 10);
697
-            add_action('AHEE__EE_messenger__enqueue_scripts_styles', array( $this, 'add_preview_script' ), 10);
698
-        }
699
-
700
-        return $send ? $this->_send_message() : $this->_preview();
701
-    }
702
-
703
-
704
-
705
-
706
-    /**
707
-     * Callback for enqueue_scripts so that we setup the preview script for all previews.
708
-     *
709
-     * @since 4.5.0
710
-     *
711
-     * @return void
712
-     */
713
-    public function add_preview_script()
714
-    {
715
-        // error message
716
-        EE_Registry::$i18n_js_strings['links_disabled'] = __('All the links on this page have been disabled because this is a generated preview message for the purpose of ensuring layout, style, and content setup.  To test generated links, you must trigger an actual message notification.', 'event_espresso');
717
-        wp_register_script('ee-messages-preview-js', EE_LIBRARIES_URL . 'messages/messenger/assets/js/ee-messages-preview.js', array( 'jquery' ), EVENT_ESPRESSO_VERSION, true);
718
-        wp_localize_script('ee-messages-preview-js', 'eei18n', EE_Registry::$i18n_js_strings);
719
-        wp_enqueue_script('ee-messages-preview-js');
720
-    }
721
-
722
-
723
-
724
-
725
-    /**
726
-     * simply validates the incoming message object and then sets up the properties for the messenger
727
-     * @param  EE_Message $message
728
-     * @throws EE_Error
729
-     */
730
-    protected function _validate_and_setup(EE_Message $message)
731
-    {
732
-        $template_pack = $message->get_template_pack();
733
-        $variation = $message->get_template_pack_variation();
734
-
735
-        // verify we have the required template pack value on the $message object.
736
-        if (! $template_pack instanceof EE_Messages_Template_Pack) {
737
-            throw new EE_Error(__('Incoming $message object must have an EE_Messages_Template_Pack object available.', 'event_espresso'));
738
-        }
739
-
740
-        $this->_tmp_pack = $template_pack;
741
-
742
-        $this->_variation = $variation ? $variation : 'default';
743
-
744
-        $template_fields = $this->get_template_fields();
745
-
746
-        foreach ($template_fields as $template => $value) {
747
-            if ($template !== 'extra') {
748
-                $column_value = $message->get_field_or_extra_meta('MSG_' . $template);
749
-                $message_template_value = $column_value ? $column_value : null;
750
-                $this->_set_template_value($template, $message_template_value);
751
-            }
752
-        }
753
-    }
754
-
755
-
756
-
757
-    /**
758
-     * Utility method for child classes to get the contents of a template file and return
759
-     *
760
-     * We're assuming the child messenger class has already setup template args!
761
-     * @param  bool $preview if true we use the preview wrapper otherwise we use main wrapper.
762
-     * @return string
763
-     * @throws \EE_Error
764
-     */
765
-    protected function _get_main_template($preview = false)
766
-    {
767
-        $type = $preview ? 'preview' : 'main';
768
-
769
-        $wrapper_template = $this->_tmp_pack->get_wrapper($this->name, $type);
770
-
771
-        // check file exists and is readable
772
-        if (!is_readable($wrapper_template)) {
773
-            throw new EE_Error(sprintf(__('Unable to access the template file for the %s messenger main content wrapper.  The location being attempted is %s.', 'event_espresso'), ucwords($this->label['singular']), $wrapper_template));
774
-        }
775
-
776
-        // add message type to template args
777
-        $this->_template_args['message_type'] = $this->_incoming_message_type;
778
-
779
-        return EEH_Template::display_template($wrapper_template, $this->_template_args, true);
780
-    }
781
-
782
-
783
-
784
-    /**
785
-     * set the _test_settings_fields property
786
-     *
787
-     * @access protected
788
-     * @return void
789
-     */
790
-    protected function _set_test_settings_fields()
791
-    {
792
-        $this->_test_settings_fields = array();
793
-    }
794
-
795
-
796
-
797
-    /**
798
-     * return the _test_settings_fields property
799
-     * @return array
800
-     */
801
-    public function get_test_settings_fields()
802
-    {
803
-        return $this->_test_settings_fields;
804
-    }
805
-
806
-
807
-
808
-
809
-    /**
810
-     * This just returns any existing test settings that might be saved in the database
811
-     *
812
-     * @access public
813
-     * @return array
814
-     */
815
-    public function get_existing_test_settings()
816
-    {
817
-        /** @var EE_Message_Resource_Manager $Message_Resource_Manager */
818
-        $Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
819
-        $settings = $Message_Resource_Manager->get_active_messengers_option();
820
-        return isset($settings[ $this->name ]['test_settings']) ? $settings[ $this->name ]['test_settings'] : array();
821
-    }
822
-
823
-
824
-
825
-    /**
826
-     * All this does is set the existing test settings (in the db) for the messenger
827
-     *
828
-     * @access public
829
-     * @param $settings
830
-     * @return bool success/fail
831
-     */
832
-    public function set_existing_test_settings($settings)
833
-    {
834
-        /** @var EE_Message_Resource_Manager $Message_Resource_Manager */
835
-        $Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
836
-        $existing = $Message_Resource_Manager->get_active_messengers_option();
837
-        $existing[ $this->name ]['test_settings'] = $settings;
838
-        return $Message_Resource_Manager->update_active_messengers_option($existing);
839
-    }
840
-
841
-
842
-
843
-    /**
844
-     * This just returns the field label for a given field setup in the _template_fields property.
845
-     *
846
-     * @since   4.3.0
847
-     *
848
-     * @param string $field The field to retrieve the label for
849
-     * @return string             The label
850
-     */
851
-    public function get_field_label($field)
852
-    {
853
-        // first let's see if the field requests is in the top level array.
854
-        if (isset($this->_template_fields[ $field ]) && !empty($this->_template_fields[ $field ]['label'])) {
855
-            return $this->_template[ $field ]['label'];
856
-        }
857
-
858
-        // nope so let's look in the extra array to see if it's there HOWEVER if the field exists as a top level index in the extra array then we know the label is in the 'main' index.
859
-        if (isset($this->_template_fields['extra']) && !empty($this->_template_fields['extra'][ $field ]) && !empty($this->_template_fields['extra'][ $field ]['main']['label'])) {
860
-            return $this->_template_fields['extra'][ $field ]['main']['label'];
861
-        }
862
-
863
-        // now it's possible this field may just be existing in any of the extra array items.
864
-        if (!empty($this->_template_fields['extra']) && is_array($this->_template_fields['extra'])) {
865
-            foreach ($this->_template_fields['extra'] as $main_field => $subfields) {
866
-                if (!is_array($subfields)) {
867
-                    continue;
868
-                }
869
-                if (isset($subfields[ $field ]) && !empty($subfields[ $field ]['label'])) {
870
-                    return $subfields[ $field ]['label'];
871
-                }
872
-            }
873
-        }
874
-
875
-        // if we made it here then there's no label set so let's just return the $field.
876
-        return $field;
877
-    }
878
-
879
-
880
-
881
-
882
-    /**
883
-     * This is a method called from EE_messages when this messenger is a generating messenger and the sending messenger is a different messenger.  Child messengers can set hooks for the sending messenger to callback on if necessary (i.e. swap out css files or something else).
884
-     *
885
-     * @since 4.5.0
886
-     *
887
-     * @param string $sending_messenger_name the name of the sending messenger so we only set the hooks needed.
888
-     *
889
-     * @return void
890
-     */
891
-    public function do_secondary_messenger_hooks($sending_messenger_name)
892
-    {
893
-        return;
894
-    }
430
+	/**
431
+	 * Returns the valid message types associated with this messenger.
432
+	 *
433
+	 * @since 4.5.0
434
+	 *
435
+	 * @return array
436
+	 */
437
+	public function get_valid_message_types()
438
+	{
439
+		$class = get_class($this);
440
+
441
+		// messenger specific filter
442
+		// messenger specific filter
443
+		$valid_types = apply_filters('FHEE__' . $class . '__get_valid_message_types__valid_types', $this->_valid_message_types, $this);
444
+
445
+		// all messengers filter
446
+		$valid_types = apply_filters('FHEE__EE_messenger__get_valid_message_types__valid_types', $valid_types, $this);
447
+		return $valid_types;
448
+	}
449
+
450
+
451
+
452
+
453
+
454
+	/**
455
+	 * this is just used by the custom validators (EE_Messages_Validator classes) to modify the _validator_config for certain message_type/messenger combos where a context may only use certain shortcodes etc.
456
+	 *
457
+	 * @access public
458
+	 * @param array $new_config Whatever is put in here will reset the _validator_config property
459
+	 */
460
+	public function set_validator_config($new_config)
461
+	{
462
+		$this->_validator_config = $new_config;
463
+	}
464
+
465
+
466
+
467
+
468
+	/**
469
+	 * This returns the _validator_config property
470
+	 *
471
+	 * @access public
472
+	 * @return array
473
+	 */
474
+	public function get_validator_config()
475
+	{
476
+		$class = get_class($this);
477
+
478
+		$config = apply_filters('FHEE__' . $class . '__get_validator_config', $this->_validator_config, $this);
479
+		$config = apply_filters('FHEE__EE_messenger__get_validator_config', $config, $this);
480
+		return $config;
481
+	}
482
+
483
+
484
+
485
+
486
+	/**
487
+	 * this public method accepts a page slug (for an EE_admin page) and will return the response from the child class callback function if that page is registered via the `_admin_registered_page` property set by the child class.
488
+	 *
489
+	 * @param string $page the slug of the EE admin page
490
+	 * @param array $message_types an array of active message type objects
491
+	 * @param string $action the page action (to allow for more specific handling - i.e. edit vs. add pages)
492
+	 * @param array $extra  This is just an extra argument that can be used to pass additional data for setting up page content.
493
+	 * @access public
494
+	 * @return string content for page
495
+	 */
496
+	public function get_messenger_admin_page_content($page, $action = null, $extra = array(), $message_types = array())
497
+	{
498
+		return $this->_get_admin_page_content($page, $action, $extra, $message_types);
499
+	}
500
+
501
+
502
+
503
+	/**
504
+	 * @param $message_types
505
+	 * @param array $extra
506
+	 * @return mixed|string
507
+	 */
508
+	protected function _get_admin_content_events_edit($message_types, $extra)
509
+	{
510
+		// defaults
511
+		$template_args = array();
512
+		$selector_rows = '';
513
+
514
+		// we don't need message types here so we're just going to ignore. we do, however, expect the event id here. The event id is needed to provide a link to setup a custom template for this event.
515
+		$event_id = isset($extra['event']) ? $extra['event'] : null;
516
+
517
+		$template_wrapper_path = EE_LIBRARIES . 'messages/messenger/admin_templates/event_switcher_wrapper.template.php';
518
+		$template_row_path = EE_LIBRARIES . 'messages/messenger/admin_templates/event_switcher_row.template.php';
519
+
520
+		// array of template objects for global and custom (non-trashed) (but remember just for this messenger!)
521
+		$global_templates = EEM_Message_Template_Group::instance()->get_all(
522
+			array( array( 'MTP_messenger' => $this->name, 'MTP_is_global' => true, 'MTP_is_active' => true ) )
523
+		);
524
+		$templates_for_event = EEM_Message_Template_Group::instance()->get_all_custom_templates_by_event(
525
+			$event_id,
526
+			array(
527
+				'MTP_messenger' => $this->name,
528
+				'MTP_is_active' => true
529
+			)
530
+		);
531
+		$templates_for_event = !empty($templates_for_event) ? $templates_for_event : array();
532
+
533
+		// so we need to setup the rows for the selectors and we use the global mtpgs (cause those will the active message template groups)
534
+		foreach ($global_templates as $mtpgID => $mtpg) {
535
+			if ($mtpg instanceof EE_Message_Template_Group) {
536
+				// verify this message type is supposed to show on this page
537
+				$mtp_obj = $mtpg->message_type_obj();
538
+				if (! $mtp_obj instanceof EE_message_type) {
539
+					continue;
540
+				}
541
+				$mtp_obj->admin_registered_pages = (array) $mtp_obj->admin_registered_pages;
542
+				if (! in_array('events_edit', $mtp_obj->admin_registered_pages)) {
543
+					continue;
544
+				}
545
+				$select_values = array();
546
+				$select_values[ $mtpgID ] = __('Global', 'event_espresso');
547
+				$default_value = array_key_exists($mtpgID, $templates_for_event) && ! $mtpg->get('MTP_is_override') ? $mtpgID : null;
548
+				// if the override has been set for the global template, then that means even if there are custom templates already created we ignore them because of the set override.
549
+				if (! $mtpg->get('MTP_is_override')) {
550
+					// any custom templates for this message type?
551
+					$custom_templates = EEM_Message_Template_Group::instance()->get_custom_message_template_by_m_and_mt($this->name, $mtpg->message_type());
552
+					foreach ($custom_templates as $cmtpgID => $cmtpg) {
553
+						$select_values[ $cmtpgID ] = $cmtpg->name();
554
+						$default_value = array_key_exists($cmtpgID, $templates_for_event) ? $cmtpgID : $default_value;
555
+					}
556
+				}
557
+				// if there is no $default_value then we set it as the global
558
+				$default_value = empty($default_value) ? $mtpgID : $default_value;
559
+				$edit_url_query_args = [
560
+					'page' => 'espresso_messages',
561
+					'action' => 'edit_message_template',
562
+					'id' => $default_value,
563
+					'evt_id' => $event_id
564
+				];
565
+				$edit_url = EEH_URL::add_query_args_and_nonce($edit_url_query_args, admin_url('admin.php'));
566
+				$create_url_query_args = [
567
+					'page' => 'espresso_messages',
568
+					'action' => 'add_new_message_template',
569
+					'GRP_ID' => $default_value
570
+				];
571
+				$create_url = EEH_URL::add_query_args_and_nonce($create_url_query_args, admin_url('admin.php'));
572
+				$st_args['mt_name'] = ucwords($mtp_obj->label['singular']);
573
+				$st_args['mt_slug'] = $mtpg->message_type();
574
+				$st_args['messenger_slug'] = $this->name;
575
+				$st_args['selector'] = EEH_Form_Fields::select_input('event_message_templates_relation[' . $mtpgID . ']', $select_values, $default_value, 'data-messenger="' . $this->name . '" data-messagetype="' . $mtpg->message_type() . '"', 'message-template-selector');
576
+				// note that  message template group that has override_all_custom set will remove the ability to set a custom message template based off of the global (and that also in turn overrides any other custom templates).
577
+				$st_args['create_button'] = $mtpg->get('MTP_is_override') ? '' : '<a data-messenger="' . $this->name . '" data-messagetype="' . $mtpg->message_type() . '" data-grpid="' . $default_value . '" target="_blank" href="' . $create_url . '" class="button button-small create-mtpg-button">' . __('Create New Custom', 'event_espresso') . '</a>';
578
+				$st_args['create_button'] = EE_Registry::instance()->CAP->current_user_can('ee_edit_messages', 'espresso_messages_add_new_message_template') ? $st_args['create_button'] : '';
579
+				$st_args['edit_button'] = EE_Registry::instance()->CAP->current_user_can('ee_edit_message', 'espresso_messages_edit_message_template', $mtpgID) ? '<a data-messagetype="' . $mtpg->message_type() . '" data-grpid="' . $default_value . '" target="_blank" href="' . $edit_url . '" class="button button-small edit-mtpg-button">' . __('Edit', 'event_espresso') . '</a>' : '';
580
+				$selector_rows .= EEH_Template::display_template($template_row_path, $st_args, true);
581
+			}
582
+		}
583
+
584
+		// if no selectors present then get out.
585
+		if (empty($selector_rows)) {
586
+			return '';
587
+		}
588
+
589
+		$template_args['selector_rows'] = $selector_rows;
590
+		return EEH_Template::display_template($template_wrapper_path, $template_args, true);
591
+	}
592
+
593
+
594
+
595
+
596
+
597
+
598
+	/**
599
+	 * get_template_fields
600
+	 *
601
+	 * @access public
602
+	 * @return array $this->_template_fields
603
+	 */
604
+	public function get_template_fields()
605
+	{
606
+		$template_fields = apply_filters('FHEE__' . get_class($this) . '__get_template_fields', $this->_template_fields, $this);
607
+		$template_fields = apply_filters('FHEE__EE_messenger__get_template_fields', $template_fields, $this);
608
+		return $template_fields;
609
+	}
610
+
611
+
612
+
613
+
614
+	/** SETUP METHODS **/
615
+	/**
616
+	 * The following method doesn't NEED to be used by child classes but might be modified by the specific messenger
617
+	 * @param string $item
618
+	 * @param mixed $value
619
+	 */
620
+	protected function _set_template_value($item, $value)
621
+	{
622
+		if (array_key_exists($item, $this->_template_fields)) {
623
+			$prop = '_' . $item;
624
+			$this->{$prop}= $value;
625
+		}
626
+	}
627
+
628
+	/**
629
+	 * Sets up the message for sending.
630
+	 *
631
+	 * @param  EE_message $message the message object that contains details about the message.
632
+	 * @param EE_message_type $message_type The message type object used in combination with this messenger to generate the provided message.
633
+	 *
634
+	 * @return bool Very important that all messengers return bool for successful send or not.  Error messages can be
635
+	 *              added to EE_Error.
636
+	 *              true = message sent successfully
637
+	 *              false = message not sent but can be retried (i.e. the failure might be just due to communication issues at the time of send).
638
+	 *              Throwing a SendMessageException means the message failed sending and cannot be retried.
639
+	 *
640
+	 * @throws SendMessageException
641
+	 */
642
+	final public function send_message($message, EE_message_type $message_type)
643
+	{
644
+		try {
645
+			$this->_validate_and_setup($message);
646
+			$this->_incoming_message_type = $message_type;
647
+			$response = $this->_send_message();
648
+			if ($response instanceof WP_Error) {
649
+				EE_Error::add_error($response->get_error_message(), __FILE__, __FUNCTION__, __LINE__);
650
+				$response = false;
651
+			}
652
+		} catch (\Exception $e) {
653
+			// convert to an instance of SendMessageException
654
+			throw new SendMessageException($e->getMessage());
655
+		}
656
+		return $response;
657
+	}
658
+
659
+
660
+
661
+	/**
662
+	 * Sets up and returns message preview
663
+	 * @param  EE_Message $message incoming message object
664
+	 * @param EE_message_type $message_type This is whatever message type was used in combination with this messenger to generate the message.
665
+	 * @param  bool   $send    true we will actually use the _send method (for test sends). FALSE we just return preview
666
+	 * @return string          return the message html content
667
+	 */
668
+	public function get_preview(EE_Message $message, EE_message_type $message_type, $send = false)
669
+	{
670
+		$this->_validate_and_setup($message);
671
+
672
+		$this->_incoming_message_type = $message_type;
673
+
674
+		if ($send) {
675
+			// are we overriding any existing template fields?
676
+			$settings = apply_filters(
677
+				'FHEE__EE_messenger__get_preview__messenger_test_settings',
678
+				$this->get_existing_test_settings(),
679
+				$this,
680
+				$send,
681
+				$message,
682
+				$message_type
683
+			);
684
+			if (! empty($settings)) {
685
+				foreach ($settings as $field => $value) {
686
+					$this->_set_template_value($field, $value);
687
+				}
688
+			}
689
+		}
690
+
691
+		// enqueue preview js so that any links/buttons on the page are disabled.
692
+		if (! $send) {
693
+			// the below may seem like duplication.  However, typically if a messenger enqueues scripts/styles,
694
+			// it deregisters all existing wp scripts and styles first.  So the second hook ensures our previewer still gets setup.
695
+			add_action('admin_enqueue_scripts', array( $this, 'add_preview_script' ), 10);
696
+			add_action('wp_enqueue_scripts', array( $this, 'add_preview_script' ), 10);
697
+			add_action('AHEE__EE_messenger__enqueue_scripts_styles', array( $this, 'add_preview_script' ), 10);
698
+		}
699
+
700
+		return $send ? $this->_send_message() : $this->_preview();
701
+	}
702
+
703
+
704
+
705
+
706
+	/**
707
+	 * Callback for enqueue_scripts so that we setup the preview script for all previews.
708
+	 *
709
+	 * @since 4.5.0
710
+	 *
711
+	 * @return void
712
+	 */
713
+	public function add_preview_script()
714
+	{
715
+		// error message
716
+		EE_Registry::$i18n_js_strings['links_disabled'] = __('All the links on this page have been disabled because this is a generated preview message for the purpose of ensuring layout, style, and content setup.  To test generated links, you must trigger an actual message notification.', 'event_espresso');
717
+		wp_register_script('ee-messages-preview-js', EE_LIBRARIES_URL . 'messages/messenger/assets/js/ee-messages-preview.js', array( 'jquery' ), EVENT_ESPRESSO_VERSION, true);
718
+		wp_localize_script('ee-messages-preview-js', 'eei18n', EE_Registry::$i18n_js_strings);
719
+		wp_enqueue_script('ee-messages-preview-js');
720
+	}
721
+
722
+
723
+
724
+
725
+	/**
726
+	 * simply validates the incoming message object and then sets up the properties for the messenger
727
+	 * @param  EE_Message $message
728
+	 * @throws EE_Error
729
+	 */
730
+	protected function _validate_and_setup(EE_Message $message)
731
+	{
732
+		$template_pack = $message->get_template_pack();
733
+		$variation = $message->get_template_pack_variation();
734
+
735
+		// verify we have the required template pack value on the $message object.
736
+		if (! $template_pack instanceof EE_Messages_Template_Pack) {
737
+			throw new EE_Error(__('Incoming $message object must have an EE_Messages_Template_Pack object available.', 'event_espresso'));
738
+		}
739
+
740
+		$this->_tmp_pack = $template_pack;
741
+
742
+		$this->_variation = $variation ? $variation : 'default';
743
+
744
+		$template_fields = $this->get_template_fields();
745
+
746
+		foreach ($template_fields as $template => $value) {
747
+			if ($template !== 'extra') {
748
+				$column_value = $message->get_field_or_extra_meta('MSG_' . $template);
749
+				$message_template_value = $column_value ? $column_value : null;
750
+				$this->_set_template_value($template, $message_template_value);
751
+			}
752
+		}
753
+	}
754
+
755
+
756
+
757
+	/**
758
+	 * Utility method for child classes to get the contents of a template file and return
759
+	 *
760
+	 * We're assuming the child messenger class has already setup template args!
761
+	 * @param  bool $preview if true we use the preview wrapper otherwise we use main wrapper.
762
+	 * @return string
763
+	 * @throws \EE_Error
764
+	 */
765
+	protected function _get_main_template($preview = false)
766
+	{
767
+		$type = $preview ? 'preview' : 'main';
768
+
769
+		$wrapper_template = $this->_tmp_pack->get_wrapper($this->name, $type);
770
+
771
+		// check file exists and is readable
772
+		if (!is_readable($wrapper_template)) {
773
+			throw new EE_Error(sprintf(__('Unable to access the template file for the %s messenger main content wrapper.  The location being attempted is %s.', 'event_espresso'), ucwords($this->label['singular']), $wrapper_template));
774
+		}
775
+
776
+		// add message type to template args
777
+		$this->_template_args['message_type'] = $this->_incoming_message_type;
778
+
779
+		return EEH_Template::display_template($wrapper_template, $this->_template_args, true);
780
+	}
781
+
782
+
783
+
784
+	/**
785
+	 * set the _test_settings_fields property
786
+	 *
787
+	 * @access protected
788
+	 * @return void
789
+	 */
790
+	protected function _set_test_settings_fields()
791
+	{
792
+		$this->_test_settings_fields = array();
793
+	}
794
+
795
+
796
+
797
+	/**
798
+	 * return the _test_settings_fields property
799
+	 * @return array
800
+	 */
801
+	public function get_test_settings_fields()
802
+	{
803
+		return $this->_test_settings_fields;
804
+	}
805
+
806
+
807
+
808
+
809
+	/**
810
+	 * This just returns any existing test settings that might be saved in the database
811
+	 *
812
+	 * @access public
813
+	 * @return array
814
+	 */
815
+	public function get_existing_test_settings()
816
+	{
817
+		/** @var EE_Message_Resource_Manager $Message_Resource_Manager */
818
+		$Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
819
+		$settings = $Message_Resource_Manager->get_active_messengers_option();
820
+		return isset($settings[ $this->name ]['test_settings']) ? $settings[ $this->name ]['test_settings'] : array();
821
+	}
822
+
823
+
824
+
825
+	/**
826
+	 * All this does is set the existing test settings (in the db) for the messenger
827
+	 *
828
+	 * @access public
829
+	 * @param $settings
830
+	 * @return bool success/fail
831
+	 */
832
+	public function set_existing_test_settings($settings)
833
+	{
834
+		/** @var EE_Message_Resource_Manager $Message_Resource_Manager */
835
+		$Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
836
+		$existing = $Message_Resource_Manager->get_active_messengers_option();
837
+		$existing[ $this->name ]['test_settings'] = $settings;
838
+		return $Message_Resource_Manager->update_active_messengers_option($existing);
839
+	}
840
+
841
+
842
+
843
+	/**
844
+	 * This just returns the field label for a given field setup in the _template_fields property.
845
+	 *
846
+	 * @since   4.3.0
847
+	 *
848
+	 * @param string $field The field to retrieve the label for
849
+	 * @return string             The label
850
+	 */
851
+	public function get_field_label($field)
852
+	{
853
+		// first let's see if the field requests is in the top level array.
854
+		if (isset($this->_template_fields[ $field ]) && !empty($this->_template_fields[ $field ]['label'])) {
855
+			return $this->_template[ $field ]['label'];
856
+		}
857
+
858
+		// nope so let's look in the extra array to see if it's there HOWEVER if the field exists as a top level index in the extra array then we know the label is in the 'main' index.
859
+		if (isset($this->_template_fields['extra']) && !empty($this->_template_fields['extra'][ $field ]) && !empty($this->_template_fields['extra'][ $field ]['main']['label'])) {
860
+			return $this->_template_fields['extra'][ $field ]['main']['label'];
861
+		}
862
+
863
+		// now it's possible this field may just be existing in any of the extra array items.
864
+		if (!empty($this->_template_fields['extra']) && is_array($this->_template_fields['extra'])) {
865
+			foreach ($this->_template_fields['extra'] as $main_field => $subfields) {
866
+				if (!is_array($subfields)) {
867
+					continue;
868
+				}
869
+				if (isset($subfields[ $field ]) && !empty($subfields[ $field ]['label'])) {
870
+					return $subfields[ $field ]['label'];
871
+				}
872
+			}
873
+		}
874
+
875
+		// if we made it here then there's no label set so let's just return the $field.
876
+		return $field;
877
+	}
878
+
879
+
880
+
881
+
882
+	/**
883
+	 * This is a method called from EE_messages when this messenger is a generating messenger and the sending messenger is a different messenger.  Child messengers can set hooks for the sending messenger to callback on if necessary (i.e. swap out css files or something else).
884
+	 *
885
+	 * @since 4.5.0
886
+	 *
887
+	 * @param string $sending_messenger_name the name of the sending messenger so we only set the hooks needed.
888
+	 *
889
+	 * @return void
890
+	 */
891
+	public function do_secondary_messenger_hooks($sending_messenger_name)
892
+	{
893
+		return;
894
+	}
895 895
 }
Please login to merge, or discard this patch.
Spacing   +37 added lines, -37 removed lines patch added patch discarded remove patch
@@ -417,7 +417,7 @@  discard block
 block discarded – undo
417 417
         $class = get_class($this);
418 418
 
419 419
         // messenger specific filter
420
-        $default_types = apply_filters('FHEE__' . $class . '__get_default_message_types__default_types', $this->_default_message_types, $this);
420
+        $default_types = apply_filters('FHEE__'.$class.'__get_default_message_types__default_types', $this->_default_message_types, $this);
421 421
 
422 422
         // all messengers filter
423 423
         $default_types = apply_filters('FHEE__EE_messenger__get_default_message_types__default_types', $default_types, $this);
@@ -440,7 +440,7 @@  discard block
 block discarded – undo
440 440
 
441 441
         // messenger specific filter
442 442
         // messenger specific filter
443
-        $valid_types = apply_filters('FHEE__' . $class . '__get_valid_message_types__valid_types', $this->_valid_message_types, $this);
443
+        $valid_types = apply_filters('FHEE__'.$class.'__get_valid_message_types__valid_types', $this->_valid_message_types, $this);
444 444
 
445 445
         // all messengers filter
446 446
         $valid_types = apply_filters('FHEE__EE_messenger__get_valid_message_types__valid_types', $valid_types, $this);
@@ -475,7 +475,7 @@  discard block
 block discarded – undo
475 475
     {
476 476
         $class = get_class($this);
477 477
 
478
-        $config = apply_filters('FHEE__' . $class . '__get_validator_config', $this->_validator_config, $this);
478
+        $config = apply_filters('FHEE__'.$class.'__get_validator_config', $this->_validator_config, $this);
479 479
         $config = apply_filters('FHEE__EE_messenger__get_validator_config', $config, $this);
480 480
         return $config;
481 481
     }
@@ -514,12 +514,12 @@  discard block
 block discarded – undo
514 514
         // we don't need message types here so we're just going to ignore. we do, however, expect the event id here. The event id is needed to provide a link to setup a custom template for this event.
515 515
         $event_id = isset($extra['event']) ? $extra['event'] : null;
516 516
 
517
-        $template_wrapper_path = EE_LIBRARIES . 'messages/messenger/admin_templates/event_switcher_wrapper.template.php';
518
-        $template_row_path = EE_LIBRARIES . 'messages/messenger/admin_templates/event_switcher_row.template.php';
517
+        $template_wrapper_path = EE_LIBRARIES.'messages/messenger/admin_templates/event_switcher_wrapper.template.php';
518
+        $template_row_path = EE_LIBRARIES.'messages/messenger/admin_templates/event_switcher_row.template.php';
519 519
 
520 520
         // array of template objects for global and custom (non-trashed) (but remember just for this messenger!)
521 521
         $global_templates = EEM_Message_Template_Group::instance()->get_all(
522
-            array( array( 'MTP_messenger' => $this->name, 'MTP_is_global' => true, 'MTP_is_active' => true ) )
522
+            array(array('MTP_messenger' => $this->name, 'MTP_is_global' => true, 'MTP_is_active' => true))
523 523
         );
524 524
         $templates_for_event = EEM_Message_Template_Group::instance()->get_all_custom_templates_by_event(
525 525
             $event_id,
@@ -528,29 +528,29 @@  discard block
 block discarded – undo
528 528
                 'MTP_is_active' => true
529 529
             )
530 530
         );
531
-        $templates_for_event = !empty($templates_for_event) ? $templates_for_event : array();
531
+        $templates_for_event = ! empty($templates_for_event) ? $templates_for_event : array();
532 532
 
533 533
         // so we need to setup the rows for the selectors and we use the global mtpgs (cause those will the active message template groups)
534 534
         foreach ($global_templates as $mtpgID => $mtpg) {
535 535
             if ($mtpg instanceof EE_Message_Template_Group) {
536 536
                 // verify this message type is supposed to show on this page
537 537
                 $mtp_obj = $mtpg->message_type_obj();
538
-                if (! $mtp_obj instanceof EE_message_type) {
538
+                if ( ! $mtp_obj instanceof EE_message_type) {
539 539
                     continue;
540 540
                 }
541 541
                 $mtp_obj->admin_registered_pages = (array) $mtp_obj->admin_registered_pages;
542
-                if (! in_array('events_edit', $mtp_obj->admin_registered_pages)) {
542
+                if ( ! in_array('events_edit', $mtp_obj->admin_registered_pages)) {
543 543
                     continue;
544 544
                 }
545 545
                 $select_values = array();
546
-                $select_values[ $mtpgID ] = __('Global', 'event_espresso');
546
+                $select_values[$mtpgID] = __('Global', 'event_espresso');
547 547
                 $default_value = array_key_exists($mtpgID, $templates_for_event) && ! $mtpg->get('MTP_is_override') ? $mtpgID : null;
548 548
                 // if the override has been set for the global template, then that means even if there are custom templates already created we ignore them because of the set override.
549
-                if (! $mtpg->get('MTP_is_override')) {
549
+                if ( ! $mtpg->get('MTP_is_override')) {
550 550
                     // any custom templates for this message type?
551 551
                     $custom_templates = EEM_Message_Template_Group::instance()->get_custom_message_template_by_m_and_mt($this->name, $mtpg->message_type());
552 552
                     foreach ($custom_templates as $cmtpgID => $cmtpg) {
553
-                        $select_values[ $cmtpgID ] = $cmtpg->name();
553
+                        $select_values[$cmtpgID] = $cmtpg->name();
554 554
                         $default_value = array_key_exists($cmtpgID, $templates_for_event) ? $cmtpgID : $default_value;
555 555
                     }
556 556
                 }
@@ -572,11 +572,11 @@  discard block
 block discarded – undo
572 572
                 $st_args['mt_name'] = ucwords($mtp_obj->label['singular']);
573 573
                 $st_args['mt_slug'] = $mtpg->message_type();
574 574
                 $st_args['messenger_slug'] = $this->name;
575
-                $st_args['selector'] = EEH_Form_Fields::select_input('event_message_templates_relation[' . $mtpgID . ']', $select_values, $default_value, 'data-messenger="' . $this->name . '" data-messagetype="' . $mtpg->message_type() . '"', 'message-template-selector');
575
+                $st_args['selector'] = EEH_Form_Fields::select_input('event_message_templates_relation['.$mtpgID.']', $select_values, $default_value, 'data-messenger="'.$this->name.'" data-messagetype="'.$mtpg->message_type().'"', 'message-template-selector');
576 576
                 // note that  message template group that has override_all_custom set will remove the ability to set a custom message template based off of the global (and that also in turn overrides any other custom templates).
577
-                $st_args['create_button'] = $mtpg->get('MTP_is_override') ? '' : '<a data-messenger="' . $this->name . '" data-messagetype="' . $mtpg->message_type() . '" data-grpid="' . $default_value . '" target="_blank" href="' . $create_url . '" class="button button-small create-mtpg-button">' . __('Create New Custom', 'event_espresso') . '</a>';
577
+                $st_args['create_button'] = $mtpg->get('MTP_is_override') ? '' : '<a data-messenger="'.$this->name.'" data-messagetype="'.$mtpg->message_type().'" data-grpid="'.$default_value.'" target="_blank" href="'.$create_url.'" class="button button-small create-mtpg-button">'.__('Create New Custom', 'event_espresso').'</a>';
578 578
                 $st_args['create_button'] = EE_Registry::instance()->CAP->current_user_can('ee_edit_messages', 'espresso_messages_add_new_message_template') ? $st_args['create_button'] : '';
579
-                $st_args['edit_button'] = EE_Registry::instance()->CAP->current_user_can('ee_edit_message', 'espresso_messages_edit_message_template', $mtpgID) ? '<a data-messagetype="' . $mtpg->message_type() . '" data-grpid="' . $default_value . '" target="_blank" href="' . $edit_url . '" class="button button-small edit-mtpg-button">' . __('Edit', 'event_espresso') . '</a>' : '';
579
+                $st_args['edit_button'] = EE_Registry::instance()->CAP->current_user_can('ee_edit_message', 'espresso_messages_edit_message_template', $mtpgID) ? '<a data-messagetype="'.$mtpg->message_type().'" data-grpid="'.$default_value.'" target="_blank" href="'.$edit_url.'" class="button button-small edit-mtpg-button">'.__('Edit', 'event_espresso').'</a>' : '';
580 580
                 $selector_rows .= EEH_Template::display_template($template_row_path, $st_args, true);
581 581
             }
582 582
         }
@@ -603,7 +603,7 @@  discard block
 block discarded – undo
603 603
      */
604 604
     public function get_template_fields()
605 605
     {
606
-        $template_fields = apply_filters('FHEE__' . get_class($this) . '__get_template_fields', $this->_template_fields, $this);
606
+        $template_fields = apply_filters('FHEE__'.get_class($this).'__get_template_fields', $this->_template_fields, $this);
607 607
         $template_fields = apply_filters('FHEE__EE_messenger__get_template_fields', $template_fields, $this);
608 608
         return $template_fields;
609 609
     }
@@ -620,8 +620,8 @@  discard block
 block discarded – undo
620 620
     protected function _set_template_value($item, $value)
621 621
     {
622 622
         if (array_key_exists($item, $this->_template_fields)) {
623
-            $prop = '_' . $item;
624
-            $this->{$prop}= $value;
623
+            $prop = '_'.$item;
624
+            $this->{$prop} = $value;
625 625
         }
626 626
     }
627 627
 
@@ -681,7 +681,7 @@  discard block
 block discarded – undo
681 681
                 $message,
682 682
                 $message_type
683 683
             );
684
-            if (! empty($settings)) {
684
+            if ( ! empty($settings)) {
685 685
                 foreach ($settings as $field => $value) {
686 686
                     $this->_set_template_value($field, $value);
687 687
                 }
@@ -689,12 +689,12 @@  discard block
 block discarded – undo
689 689
         }
690 690
 
691 691
         // enqueue preview js so that any links/buttons on the page are disabled.
692
-        if (! $send) {
692
+        if ( ! $send) {
693 693
             // the below may seem like duplication.  However, typically if a messenger enqueues scripts/styles,
694 694
             // it deregisters all existing wp scripts and styles first.  So the second hook ensures our previewer still gets setup.
695
-            add_action('admin_enqueue_scripts', array( $this, 'add_preview_script' ), 10);
696
-            add_action('wp_enqueue_scripts', array( $this, 'add_preview_script' ), 10);
697
-            add_action('AHEE__EE_messenger__enqueue_scripts_styles', array( $this, 'add_preview_script' ), 10);
695
+            add_action('admin_enqueue_scripts', array($this, 'add_preview_script'), 10);
696
+            add_action('wp_enqueue_scripts', array($this, 'add_preview_script'), 10);
697
+            add_action('AHEE__EE_messenger__enqueue_scripts_styles', array($this, 'add_preview_script'), 10);
698 698
         }
699 699
 
700 700
         return $send ? $this->_send_message() : $this->_preview();
@@ -714,7 +714,7 @@  discard block
 block discarded – undo
714 714
     {
715 715
         // error message
716 716
         EE_Registry::$i18n_js_strings['links_disabled'] = __('All the links on this page have been disabled because this is a generated preview message for the purpose of ensuring layout, style, and content setup.  To test generated links, you must trigger an actual message notification.', 'event_espresso');
717
-        wp_register_script('ee-messages-preview-js', EE_LIBRARIES_URL . 'messages/messenger/assets/js/ee-messages-preview.js', array( 'jquery' ), EVENT_ESPRESSO_VERSION, true);
717
+        wp_register_script('ee-messages-preview-js', EE_LIBRARIES_URL.'messages/messenger/assets/js/ee-messages-preview.js', array('jquery'), EVENT_ESPRESSO_VERSION, true);
718 718
         wp_localize_script('ee-messages-preview-js', 'eei18n', EE_Registry::$i18n_js_strings);
719 719
         wp_enqueue_script('ee-messages-preview-js');
720 720
     }
@@ -733,7 +733,7 @@  discard block
 block discarded – undo
733 733
         $variation = $message->get_template_pack_variation();
734 734
 
735 735
         // verify we have the required template pack value on the $message object.
736
-        if (! $template_pack instanceof EE_Messages_Template_Pack) {
736
+        if ( ! $template_pack instanceof EE_Messages_Template_Pack) {
737 737
             throw new EE_Error(__('Incoming $message object must have an EE_Messages_Template_Pack object available.', 'event_espresso'));
738 738
         }
739 739
 
@@ -745,7 +745,7 @@  discard block
 block discarded – undo
745 745
 
746 746
         foreach ($template_fields as $template => $value) {
747 747
             if ($template !== 'extra') {
748
-                $column_value = $message->get_field_or_extra_meta('MSG_' . $template);
748
+                $column_value = $message->get_field_or_extra_meta('MSG_'.$template);
749 749
                 $message_template_value = $column_value ? $column_value : null;
750 750
                 $this->_set_template_value($template, $message_template_value);
751 751
             }
@@ -769,7 +769,7 @@  discard block
 block discarded – undo
769 769
         $wrapper_template = $this->_tmp_pack->get_wrapper($this->name, $type);
770 770
 
771 771
         // check file exists and is readable
772
-        if (!is_readable($wrapper_template)) {
772
+        if ( ! is_readable($wrapper_template)) {
773 773
             throw new EE_Error(sprintf(__('Unable to access the template file for the %s messenger main content wrapper.  The location being attempted is %s.', 'event_espresso'), ucwords($this->label['singular']), $wrapper_template));
774 774
         }
775 775
 
@@ -817,7 +817,7 @@  discard block
 block discarded – undo
817 817
         /** @var EE_Message_Resource_Manager $Message_Resource_Manager */
818 818
         $Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
819 819
         $settings = $Message_Resource_Manager->get_active_messengers_option();
820
-        return isset($settings[ $this->name ]['test_settings']) ? $settings[ $this->name ]['test_settings'] : array();
820
+        return isset($settings[$this->name]['test_settings']) ? $settings[$this->name]['test_settings'] : array();
821 821
     }
822 822
 
823 823
 
@@ -834,7 +834,7 @@  discard block
 block discarded – undo
834 834
         /** @var EE_Message_Resource_Manager $Message_Resource_Manager */
835 835
         $Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
836 836
         $existing = $Message_Resource_Manager->get_active_messengers_option();
837
-        $existing[ $this->name ]['test_settings'] = $settings;
837
+        $existing[$this->name]['test_settings'] = $settings;
838 838
         return $Message_Resource_Manager->update_active_messengers_option($existing);
839 839
     }
840 840
 
@@ -851,23 +851,23 @@  discard block
 block discarded – undo
851 851
     public function get_field_label($field)
852 852
     {
853 853
         // first let's see if the field requests is in the top level array.
854
-        if (isset($this->_template_fields[ $field ]) && !empty($this->_template_fields[ $field ]['label'])) {
855
-            return $this->_template[ $field ]['label'];
854
+        if (isset($this->_template_fields[$field]) && ! empty($this->_template_fields[$field]['label'])) {
855
+            return $this->_template[$field]['label'];
856 856
         }
857 857
 
858 858
         // nope so let's look in the extra array to see if it's there HOWEVER if the field exists as a top level index in the extra array then we know the label is in the 'main' index.
859
-        if (isset($this->_template_fields['extra']) && !empty($this->_template_fields['extra'][ $field ]) && !empty($this->_template_fields['extra'][ $field ]['main']['label'])) {
860
-            return $this->_template_fields['extra'][ $field ]['main']['label'];
859
+        if (isset($this->_template_fields['extra']) && ! empty($this->_template_fields['extra'][$field]) && ! empty($this->_template_fields['extra'][$field]['main']['label'])) {
860
+            return $this->_template_fields['extra'][$field]['main']['label'];
861 861
         }
862 862
 
863 863
         // now it's possible this field may just be existing in any of the extra array items.
864
-        if (!empty($this->_template_fields['extra']) && is_array($this->_template_fields['extra'])) {
864
+        if ( ! empty($this->_template_fields['extra']) && is_array($this->_template_fields['extra'])) {
865 865
             foreach ($this->_template_fields['extra'] as $main_field => $subfields) {
866
-                if (!is_array($subfields)) {
866
+                if ( ! is_array($subfields)) {
867 867
                     continue;
868 868
                 }
869
-                if (isset($subfields[ $field ]) && !empty($subfields[ $field ]['label'])) {
870
-                    return $subfields[ $field ]['label'];
869
+                if (isset($subfields[$field]) && ! empty($subfields[$field]['label'])) {
870
+                    return $subfields[$field]['label'];
871 871
                 }
872 872
             }
873 873
         }
Please login to merge, or discard this patch.
core/admin/templates/espresso_ratings_request_content.template.php 1 patch
Indentation   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -1,9 +1,9 @@  discard block
 block discarded – undo
1 1
 <div class="padding">
2 2
     <p><?php
3
-        _e(
4
-            'We need your help to continue maintaining and providing this plugin for free. You can help by leaving a positive review in the WordPress plugin directory. 5 star ratings bring Event Espresso Decaf to the attention of more users which increases our support and features for this version of Event Espresso.',
5
-            'event_espresso'
6
-        ); ?></p>
3
+		_e(
4
+			'We need your help to continue maintaining and providing this plugin for free. You can help by leaving a positive review in the WordPress plugin directory. 5 star ratings bring Event Espresso Decaf to the attention of more users which increases our support and features for this version of Event Espresso.',
5
+			'event_espresso'
6
+		); ?></p>
7 7
     <p><?php _e('Rate it five stars today!', 'event_espresso'); ?></p><span
8 8
         class="ee-wp-blue dashicons dashicons-star-filled"></span><span
9 9
         class="ee-wp-blue dashicons dashicons-star-filled"></span><span
@@ -12,8 +12,8 @@  discard block
 block discarded – undo
12 12
         class="ee-wp-blue dashicons dashicons-star-filled"></span>
13 13
     <p><a class="button button-primary"
14 14
           href="https://login.wordpress.org/?redirect_to=https%3A%2F%2Fwordpress.org%2Fsupport%2Fview%2Fplugin-reviews%2Fevent-espresso-decaf%3Frate%3D5%23postform"><?php
15
-            _e(
16
-                'Rate It!',
17
-                'event_espresso'
18
-            ); ?></a></p>
15
+			_e(
16
+				'Rate It!',
17
+				'event_espresso'
18
+			); ?></a></p>
19 19
 </div>
20 20
\ No newline at end of file
Please login to merge, or discard this patch.
EE_Admin_Table_Registration_Line_Item_Display_Strategy.strategy.php 1 patch
Indentation   +186 added lines, -186 removed lines patch added patch discarded remove patch
@@ -13,191 +13,191 @@
 block discarded – undo
13 13
 class EE_Admin_Table_Registration_Line_Item_Display_Strategy extends EE_Admin_Table_Line_Item_Display_Strategy
14 14
 {
15 15
 
16
-    /**
17
-     * Table header for display.
18
-     * @since   4.8
19
-     * @param array $options
20
-     * @return string
21
-     */
22
-    protected function _table_header($options)
23
-    {
24
-        $html = EEH_HTML::table('', '', $options['table_css_class']);
25
-        $html .= EEH_HTML::thead();
26
-        $html .= EEH_HTML::tr();
27
-        $html .= EEH_HTML::th(__('Name', 'event_espresso'), '', 'jst-left');
28
-        $html .= EEH_HTML::th(__('Type', 'event_espresso'), '', 'jst-left');
29
-        $html .= EEH_HTML::th(__('Date(s)', 'event_espresso'), '', 'jst-left');
30
-        $html .= EEH_HTML::th(__('Amount', 'event_espresso'), '', 'jst-cntr');
31
-        $html .= EEH_HTML::tbody();
32
-        return $html;
33
-    }
34
-
35
-
36
-
37
-
38
-
39
-    /**
40
-     *    _item_row
41
-     *
42
-     * @param EE_Line_Item $line_item
43
-     * @param array        $options
44
-     * @return mixed
45
-     */
46
-    protected function _item_row(EE_Line_Item $line_item, $options = array())
47
-    {
48
-        $line_item_related_object = $line_item->get_object();
49
-        $parent_line_item_related_object = $line_item->parent() instanceof EE_Line_Item
50
-            ? $line_item->parent()->get_object()
51
-            : null;
52
-        // start of row
53
-        $row_class = $options['odd'] ? 'item odd' : 'item';
54
-        $html = EEH_HTML::tr('', '', $row_class);
55
-
56
-
57
-        // Name Column
58
-        $name_link = $line_item_related_object instanceof EEI_Admin_Links ? $line_item_related_object->get_admin_details_link() : '';
59
-
60
-        // related object scope.
61
-        $parent_related_object_name = $parent_line_item_related_object instanceof EEI_Line_Item_Object
62
-            ? $parent_line_item_related_object->name()
63
-            : '';
64
-        $parent_related_object_name = empty($parent_related_object_name) && $line_item->parent() instanceof EE_Line_Item
65
-            ? $line_item->parent()->name()
66
-            : $parent_related_object_name;
67
-        $parent_related_object_link = $parent_line_item_related_object instanceof EEI_Admin_Links
68
-            ? $parent_line_item_related_object->get_admin_details_link()
69
-            : '';
70
-
71
-
72
-        $name_html = $line_item_related_object instanceof EEI_Line_Item_Object
73
-            ? $line_item_related_object->name() : $line_item->name();
74
-        $name_html = $name_link ? '<a href="' . $name_link . '">' . $name_html . '</a>'
75
-            : $name_html;
76
-        $name_html .= $line_item->is_taxable() ? ' *' : '';
77
-        // maybe preface with icon?
78
-        $name_html = $line_item_related_object instanceof EEI_Has_Icon
79
-            ? $line_item_related_object->get_icon() . $name_html
80
-            : $name_html;
81
-        $name_html = '<span class="ee-line-item-name linked">' . $name_html . '</span><br>';
82
-        $name_html .=  sprintf(
83
-            _x('%1$sfor the %2$s: %3$s%4$s', 'eg. "for the Event: My Cool Event"', 'event_espresso'),
84
-            '<span class="ee-line-item-related-parent-object">',
85
-            $line_item->parent() instanceof EE_Line_Item
86
-                ? $line_item->parent()->OBJ_type_i18n()
87
-                : __('Item:', 'event_espresso'),
88
-            $parent_related_object_link
89
-                ? '<a href="' . $parent_related_object_link . '">' . $parent_related_object_name . '</a>'
90
-                : $parent_related_object_name,
91
-            '</span>'
92
-        );
93
-
94
-        $name_html = apply_filters(
95
-            'FHEE__EE_Admin_Table_Registration_Line_Item_Display_Strategy___item_row__name_html',
96
-            $name_html,
97
-            $line_item,
98
-            $options
99
-        );
16
+	/**
17
+	 * Table header for display.
18
+	 * @since   4.8
19
+	 * @param array $options
20
+	 * @return string
21
+	 */
22
+	protected function _table_header($options)
23
+	{
24
+		$html = EEH_HTML::table('', '', $options['table_css_class']);
25
+		$html .= EEH_HTML::thead();
26
+		$html .= EEH_HTML::tr();
27
+		$html .= EEH_HTML::th(__('Name', 'event_espresso'), '', 'jst-left');
28
+		$html .= EEH_HTML::th(__('Type', 'event_espresso'), '', 'jst-left');
29
+		$html .= EEH_HTML::th(__('Date(s)', 'event_espresso'), '', 'jst-left');
30
+		$html .= EEH_HTML::th(__('Amount', 'event_espresso'), '', 'jst-cntr');
31
+		$html .= EEH_HTML::tbody();
32
+		return $html;
33
+	}
34
+
35
+
36
+
37
+
38
+
39
+	/**
40
+	 *    _item_row
41
+	 *
42
+	 * @param EE_Line_Item $line_item
43
+	 * @param array        $options
44
+	 * @return mixed
45
+	 */
46
+	protected function _item_row(EE_Line_Item $line_item, $options = array())
47
+	{
48
+		$line_item_related_object = $line_item->get_object();
49
+		$parent_line_item_related_object = $line_item->parent() instanceof EE_Line_Item
50
+			? $line_item->parent()->get_object()
51
+			: null;
52
+		// start of row
53
+		$row_class = $options['odd'] ? 'item odd' : 'item';
54
+		$html = EEH_HTML::tr('', '', $row_class);
55
+
56
+
57
+		// Name Column
58
+		$name_link = $line_item_related_object instanceof EEI_Admin_Links ? $line_item_related_object->get_admin_details_link() : '';
59
+
60
+		// related object scope.
61
+		$parent_related_object_name = $parent_line_item_related_object instanceof EEI_Line_Item_Object
62
+			? $parent_line_item_related_object->name()
63
+			: '';
64
+		$parent_related_object_name = empty($parent_related_object_name) && $line_item->parent() instanceof EE_Line_Item
65
+			? $line_item->parent()->name()
66
+			: $parent_related_object_name;
67
+		$parent_related_object_link = $parent_line_item_related_object instanceof EEI_Admin_Links
68
+			? $parent_line_item_related_object->get_admin_details_link()
69
+			: '';
70
+
71
+
72
+		$name_html = $line_item_related_object instanceof EEI_Line_Item_Object
73
+			? $line_item_related_object->name() : $line_item->name();
74
+		$name_html = $name_link ? '<a href="' . $name_link . '">' . $name_html . '</a>'
75
+			: $name_html;
76
+		$name_html .= $line_item->is_taxable() ? ' *' : '';
77
+		// maybe preface with icon?
78
+		$name_html = $line_item_related_object instanceof EEI_Has_Icon
79
+			? $line_item_related_object->get_icon() . $name_html
80
+			: $name_html;
81
+		$name_html = '<span class="ee-line-item-name linked">' . $name_html . '</span><br>';
82
+		$name_html .=  sprintf(
83
+			_x('%1$sfor the %2$s: %3$s%4$s', 'eg. "for the Event: My Cool Event"', 'event_espresso'),
84
+			'<span class="ee-line-item-related-parent-object">',
85
+			$line_item->parent() instanceof EE_Line_Item
86
+				? $line_item->parent()->OBJ_type_i18n()
87
+				: __('Item:', 'event_espresso'),
88
+			$parent_related_object_link
89
+				? '<a href="' . $parent_related_object_link . '">' . $parent_related_object_name . '</a>'
90
+				: $parent_related_object_name,
91
+			'</span>'
92
+		);
93
+
94
+		$name_html = apply_filters(
95
+			'FHEE__EE_Admin_Table_Registration_Line_Item_Display_Strategy___item_row__name_html',
96
+			$name_html,
97
+			$line_item,
98
+			$options
99
+		);
100 100
         
101
-        $html .= EEH_HTML::td($name_html, '', 'jst-left');
102
-        // Type Column
103
-        $type_html = $line_item->OBJ_type() ? $line_item->OBJ_type_i18n() : '';
104
-        $type_html .= $this->_get_cancellations($line_item);
105
-        $type_html .= $line_item->OBJ_type() ? '<br />' : '';
106
-        $code = $line_item_related_object instanceof EEI_Has_Code ? $line_item_related_object->code() : '';
107
-        $type_html .= ! empty($code) ? '<span class="ee-line-item-id">' . sprintf(__('Code: %s', 'event_espresso'), $code) . '</span>' : '';
108
-        $html .= EEH_HTML::td($type_html, '', 'jst-left');
109
-
110
-        // Date column
111
-        $datetime_content = '';
112
-        if ($line_item_related_object instanceof EE_Ticket) {
113
-            $datetimes = $line_item_related_object->datetimes();
114
-            foreach ($datetimes as $datetime) {
115
-                if ($datetime instanceof EE_Datetime) {
116
-                    $datetime_content .= $datetime->get_dtt_display_name() . '<br>';
117
-                }
118
-            }
119
-        }
120
-        $html .= EEH_HTML::td($datetime_content, '', 'jst-left');
121
-
122
-        // Amount Column
123
-        if ($line_item->is_percent()) {
124
-            $html .= EEH_HTML::td($line_item->percent() . '%', '', 'jst-rght');
125
-        } else {
126
-            $html .= EEH_HTML::td($line_item->unit_price_no_code(), '', 'jst-rght');
127
-        }
128
-
129
-
130
-        // finish things off and return
131
-        $html .= EEH_HTML::trx();
132
-        return $html;
133
-    }
134
-
135
-
136
-
137
-    /**
138
-     *  _tax_row
139
-     *
140
-     * @param EE_Line_Item $line_item
141
-     * @param array        $options
142
-     * @return mixed
143
-     */
144
-    protected function _tax_row(EE_Line_Item $line_item, $options = array())
145
-    {
146
-        // start of row
147
-        $html = EEH_HTML::tr('', 'admin-primary-mbox-taxes-tr');
148
-        // name th
149
-        $html .= EEH_HTML::th($line_item->name() . '(' . $line_item->get_pretty('LIN_percent') . '%)', '', 'jst-rght', '', ' colspan="3"');
150
-        // total th
151
-        $html .= EEH_HTML::th(EEH_Template::format_currency($line_item->total(), false, false), '', 'jst-rght');
152
-        // end of row
153
-        $html .= EEH_HTML::trx();
154
-        return $html;
155
-    }
156
-
157
-
158
-
159
-
160
-
161
-    /**
162
-     *  _total_row
163
-     *
164
-     * @param EE_Line_Item $line_item
165
-     * @param array        $options
166
-     * @return mixed
167
-     */
168
-    protected function _total_row(EE_Line_Item $line_item, $options = array())
169
-    {
170
-
171
-        $registration = isset($options['EE_Registration']) ? $options['EE_Registration'] : null;
172
-        $registration_total = $registration instanceof EE_Registration ? $registration->pretty_final_price() : 0;
173
-        // if no valid registration object then we're not going to show the approximate text.
174
-        $total_match = $registration instanceof EE_Registration
175
-            ? $registration->final_price() === $line_item->total()
176
-            : true;
177
-
178
-        // start of row
179
-        $html = EEH_HTML::tr('', '', 'admin-primary-mbox-total-tr');
180
-        // Total th label
181
-        if ($total_match) {
182
-            $total_label = sprintf(__('This registration\'s total %s:', 'event_espresso'), '(' . EE_Registry::instance()->CFG->currency->code . ')');
183
-        } else {
184
-            $total_label = sprintf(__('This registration\'s approximate total %s', 'event_espresso'), '(' . EE_Registry::instance()->CFG->currency->code . ')');
185
-            $total_label .= '<br>';
186
-            $total_label .= '<p class="ee-footnote-text">'
187
-                            . sprintf(
188
-                                __('The registrations\' share of the transaction total is approximate because it might not be possible to evenly divide the transaction total among each registration, and so some registrations may need to pay a penny more than others.  This registration\'s final share is actually %1$s%2$s%3$s.', 'event_espresso'),
189
-                                '<strong>',
190
-                                $registration_total,
191
-                                '</strong>'
192
-                            )
193
-                            . '</p>';
194
-        }
195
-        $html .= EEH_HTML::th($total_label, '', 'jst-rght', '', ' colspan="3"');
196
-        // total th
197
-
198
-        $html .= EEH_HTML::th(EEH_Template::format_currency($line_item->total(), false, false), '', 'jst-rght');
199
-        // end of row
200
-        $html .= EEH_HTML::trx();
201
-        return $html;
202
-    }
101
+		$html .= EEH_HTML::td($name_html, '', 'jst-left');
102
+		// Type Column
103
+		$type_html = $line_item->OBJ_type() ? $line_item->OBJ_type_i18n() : '';
104
+		$type_html .= $this->_get_cancellations($line_item);
105
+		$type_html .= $line_item->OBJ_type() ? '<br />' : '';
106
+		$code = $line_item_related_object instanceof EEI_Has_Code ? $line_item_related_object->code() : '';
107
+		$type_html .= ! empty($code) ? '<span class="ee-line-item-id">' . sprintf(__('Code: %s', 'event_espresso'), $code) . '</span>' : '';
108
+		$html .= EEH_HTML::td($type_html, '', 'jst-left');
109
+
110
+		// Date column
111
+		$datetime_content = '';
112
+		if ($line_item_related_object instanceof EE_Ticket) {
113
+			$datetimes = $line_item_related_object->datetimes();
114
+			foreach ($datetimes as $datetime) {
115
+				if ($datetime instanceof EE_Datetime) {
116
+					$datetime_content .= $datetime->get_dtt_display_name() . '<br>';
117
+				}
118
+			}
119
+		}
120
+		$html .= EEH_HTML::td($datetime_content, '', 'jst-left');
121
+
122
+		// Amount Column
123
+		if ($line_item->is_percent()) {
124
+			$html .= EEH_HTML::td($line_item->percent() . '%', '', 'jst-rght');
125
+		} else {
126
+			$html .= EEH_HTML::td($line_item->unit_price_no_code(), '', 'jst-rght');
127
+		}
128
+
129
+
130
+		// finish things off and return
131
+		$html .= EEH_HTML::trx();
132
+		return $html;
133
+	}
134
+
135
+
136
+
137
+	/**
138
+	 *  _tax_row
139
+	 *
140
+	 * @param EE_Line_Item $line_item
141
+	 * @param array        $options
142
+	 * @return mixed
143
+	 */
144
+	protected function _tax_row(EE_Line_Item $line_item, $options = array())
145
+	{
146
+		// start of row
147
+		$html = EEH_HTML::tr('', 'admin-primary-mbox-taxes-tr');
148
+		// name th
149
+		$html .= EEH_HTML::th($line_item->name() . '(' . $line_item->get_pretty('LIN_percent') . '%)', '', 'jst-rght', '', ' colspan="3"');
150
+		// total th
151
+		$html .= EEH_HTML::th(EEH_Template::format_currency($line_item->total(), false, false), '', 'jst-rght');
152
+		// end of row
153
+		$html .= EEH_HTML::trx();
154
+		return $html;
155
+	}
156
+
157
+
158
+
159
+
160
+
161
+	/**
162
+	 *  _total_row
163
+	 *
164
+	 * @param EE_Line_Item $line_item
165
+	 * @param array        $options
166
+	 * @return mixed
167
+	 */
168
+	protected function _total_row(EE_Line_Item $line_item, $options = array())
169
+	{
170
+
171
+		$registration = isset($options['EE_Registration']) ? $options['EE_Registration'] : null;
172
+		$registration_total = $registration instanceof EE_Registration ? $registration->pretty_final_price() : 0;
173
+		// if no valid registration object then we're not going to show the approximate text.
174
+		$total_match = $registration instanceof EE_Registration
175
+			? $registration->final_price() === $line_item->total()
176
+			: true;
177
+
178
+		// start of row
179
+		$html = EEH_HTML::tr('', '', 'admin-primary-mbox-total-tr');
180
+		// Total th label
181
+		if ($total_match) {
182
+			$total_label = sprintf(__('This registration\'s total %s:', 'event_espresso'), '(' . EE_Registry::instance()->CFG->currency->code . ')');
183
+		} else {
184
+			$total_label = sprintf(__('This registration\'s approximate total %s', 'event_espresso'), '(' . EE_Registry::instance()->CFG->currency->code . ')');
185
+			$total_label .= '<br>';
186
+			$total_label .= '<p class="ee-footnote-text">'
187
+							. sprintf(
188
+								__('The registrations\' share of the transaction total is approximate because it might not be possible to evenly divide the transaction total among each registration, and so some registrations may need to pay a penny more than others.  This registration\'s final share is actually %1$s%2$s%3$s.', 'event_espresso'),
189
+								'<strong>',
190
+								$registration_total,
191
+								'</strong>'
192
+							)
193
+							. '</p>';
194
+		}
195
+		$html .= EEH_HTML::th($total_label, '', 'jst-rght', '', ' colspan="3"');
196
+		// total th
197
+
198
+		$html .= EEH_HTML::th(EEH_Template::format_currency($line_item->total(), false, false), '', 'jst-rght');
199
+		// end of row
200
+		$html .= EEH_HTML::trx();
201
+		return $html;
202
+	}
203 203
 }
Please login to merge, or discard this patch.