Completed
Branch FET/9575/invisible-recaptcha (d42449)
by
unknown
52:19 queued 39:45
created
core/helpers/EEH_MSG_Template.helper.php 2 patches
Indentation   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -492,7 +492,7 @@  discard block
 block discarded – undo
492 492
 		if ( ! empty( $sending_messenger ) ) {
493 493
 			$with_messengers = $message_type->with_messengers();
494 494
 			if ( ! isset( $with_messengers[$message->messenger()] )
495
-			     || ! in_array( $sending_messenger, $with_messengers[$message->messenger()] ) ) {
495
+				 || ! in_array( $sending_messenger, $with_messengers[$message->messenger()] ) ) {
496 496
 				throw new EE_Error(
497 497
 					sprintf(
498 498
 						__(
@@ -1202,14 +1202,14 @@  discard block
 block discarded – undo
1202 1202
 			return array();
1203 1203
 		}
1204 1204
 
1205
-        $excluded_fields_for_messenger = $message_type->excludedFieldsForMessenger($messenger_name);
1205
+		$excluded_fields_for_messenger = $message_type->excludedFieldsForMessenger($messenger_name);
1206 1206
 
1207 1207
 		//okay now let's assemble an array with the messenger template fields added to the message_type contexts.
1208 1208
 		foreach ( $message_type->get_contexts() as $context => $details ) {
1209 1209
 			foreach ( $messenger->get_template_fields() as $field => $value ) {
1210
-			    if (in_array($field, $excluded_fields_for_messenger, true)) {
1211
-			        continue;
1212
-                }
1210
+				if (in_array($field, $excluded_fields_for_messenger, true)) {
1211
+					continue;
1212
+				}
1213 1213
 				$template_fields[ $context ][ $field ] = $value;
1214 1214
 			}
1215 1215
 		}
Please login to merge, or discard this patch.
Spacing   +197 added lines, -197 removed lines patch added patch discarded remove patch
@@ -1,6 +1,6 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 
3
-if (!defined('EVENT_ESPRESSO_VERSION') )
3
+if ( ! defined('EVENT_ESPRESSO_VERSION'))
4 4
 	exit('NO direct script access allowed');
5 5
 
6 6
 /**
@@ -59,24 +59,24 @@  discard block
 block discarded – undo
59 59
 	 *                was not a new generated template but just reactivated (which only happens for global templates that
60 60
 	 *                already exist in the database.
61 61
 	 */
62
-	public static function generate_new_templates( $messenger, $message_types, $GRP_ID = 0, $global = false ) {
62
+	public static function generate_new_templates($messenger, $message_types, $GRP_ID = 0, $global = false) {
63 63
 		//make sure message_type is an array.
64 64
 		$message_types = (array) $message_types;
65 65
 		$templates = array();
66 66
 
67
-		if ( empty( $messenger ) ) {
68
-			throw new EE_Error( __('We need a messenger to generate templates!', 'event_espresso') );
67
+		if (empty($messenger)) {
68
+			throw new EE_Error(__('We need a messenger to generate templates!', 'event_espresso'));
69 69
 		}
70 70
 
71 71
 		//if we STILL have empty $message_types then we need to generate an error message b/c we NEED message types to do the template files.
72
-		if ( empty( $message_types ) ) {
73
-			throw new EE_Error( __('We need at least one message type to generate templates!', 'event_espresso') );
72
+		if (empty($message_types)) {
73
+			throw new EE_Error(__('We need at least one message type to generate templates!', 'event_espresso'));
74 74
 		}
75 75
 
76 76
 		EEH_MSG_Template::_set_autoloader();
77
-		foreach ( $message_types as $message_type ) {
77
+		foreach ($message_types as $message_type) {
78 78
 			//if global then let's attempt to get the GRP_ID for this combo IF GRP_ID is empty.
79
-			if ( $global && empty( $GRP_ID ) ) {
79
+			if ($global && empty($GRP_ID)) {
80 80
 				$GRP_ID = EEM_Message_Template_Group::instance()->get_one(
81 81
 					array(
82 82
 						array(
@@ -91,7 +91,7 @@  discard block
 block discarded – undo
91 91
 			// if this is global template generation.
92 92
 			// First let's determine if we already HAVE global templates for this messenger and message_type combination.
93 93
 			//  If we do then NO generation!!
94
-			if ( $global && EEH_MSG_Template::already_generated( $messenger, $message_type, $GRP_ID ) ) {
94
+			if ($global && EEH_MSG_Template::already_generated($messenger, $message_type, $GRP_ID)) {
95 95
 				$templates[] = array(
96 96
 					'GRP_ID' => $GRP_ID,
97 97
 					'MTP_context' => '',
@@ -99,9 +99,9 @@  discard block
 block discarded – undo
99 99
 				//we already have generated templates for this so let's go to the next message type.
100 100
 				continue;
101 101
 			}
102
-			$new_message_template_group = EEH_MSG_Template::create_new_templates( $messenger, $message_type, $GRP_ID, $global );
102
+			$new_message_template_group = EEH_MSG_Template::create_new_templates($messenger, $message_type, $GRP_ID, $global);
103 103
 
104
-			if ( ! $new_message_template_group ) {
104
+			if ( ! $new_message_template_group) {
105 105
 				continue;
106 106
 			}
107 107
 			$templates[] = $new_message_template_group;
@@ -118,10 +118,10 @@  discard block
 block discarded – undo
118 118
 	 * @param  int $GRP_ID        GRP ID ( if a custom template) (if not provided then we're just doing global template check)
119 119
 	 * @return bool                true = generated, false = hasn't been generated.
120 120
 	 */
121
-	public static function already_generated( $messenger, $message_type, $GRP_ID = 0 ) {
121
+	public static function already_generated($messenger, $message_type, $GRP_ID = 0) {
122 122
 		EEH_MSG_Template::_set_autoloader();
123 123
 		//what method we use depends on whether we have an GRP_ID or not
124
-		$count = empty( $GRP_ID )
124
+		$count = empty($GRP_ID)
125 125
 			? EEM_Message_Template::instance()->count(
126 126
 				array(
127 127
 					array(
@@ -131,7 +131,7 @@  discard block
 block discarded – undo
131 131
 					)
132 132
 				)
133 133
 			)
134
-			: EEM_Message_Template::instance()->count( array( array( 'GRP_ID' => $GRP_ID ) ) );
134
+			: EEM_Message_Template::instance()->count(array(array('GRP_ID' => $GRP_ID)));
135 135
 
136 136
 		return $count > 0;
137 137
 	}
@@ -147,15 +147,15 @@  discard block
 block discarded – undo
147 147
 	 * @param  array  $message_type_names  Message type slug
148 148
 	 * @return  int 						count of updated records.
149 149
 	 */
150
-	public static function update_to_active( $messenger_names, $message_type_names ) {
151
-		$messenger_names = is_array( $messenger_names ) ? $messenger_names : array( $messenger_names );
152
-		$message_type_names = is_array( $message_type_names ) ? $message_type_names : array( $message_type_names );
150
+	public static function update_to_active($messenger_names, $message_type_names) {
151
+		$messenger_names = is_array($messenger_names) ? $messenger_names : array($messenger_names);
152
+		$message_type_names = is_array($message_type_names) ? $message_type_names : array($message_type_names);
153 153
 		return EEM_Message_Template_Group::instance()->update(
154
-			array( 'MTP_is_active' => 1 ),
154
+			array('MTP_is_active' => 1),
155 155
 			array(
156 156
 				array(
157
-					'MTP_messenger' 	=> array( 'IN', $messenger_names ),
158
-					'MTP_message_type'  => array( 'IN', $message_type_names )
157
+					'MTP_messenger' 	=> array('IN', $messenger_names),
158
+					'MTP_message_type'  => array('IN', $message_type_names)
159 159
 				)
160 160
 			)
161 161
 		);
@@ -176,7 +176,7 @@  discard block
 block discarded – undo
176 176
 	 *
177 177
 	 * @return int  count of updated records.
178 178
 	 */
179
-	public static function update_to_inactive( $messenger_names = array(), $message_type_names = array() ) {
179
+	public static function update_to_inactive($messenger_names = array(), $message_type_names = array()) {
180 180
 		return EEM_Message_Template_Group::instance()->deactivate_message_template_groups_for(
181 181
 			$messenger_names,
182 182
 			$message_type_names
@@ -193,9 +193,9 @@  discard block
 block discarded – undo
193 193
 	 * @param string $type
194 194
 	 * @return array array consisting of installed messenger objects and installed message type objects.
195 195
 	 */
196
-	public static function get_installed_message_objects( $type = 'all' ) {
196
+	public static function get_installed_message_objects($type = 'all') {
197 197
 		self::_set_autoloader();
198
-		$message_resource_manager = EE_Registry::instance()->load_lib( 'Message_Resource_Manager' );
198
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
199 199
 		return array(
200 200
 			'messenger' => $message_resource_manager->installed_messengers(),
201 201
 			'message_type' => $message_resource_manager->installed_message_types()
@@ -231,74 +231,74 @@  discard block
 block discarded – undo
231 231
 		$context = 'admin',
232 232
 		$merged = false
233 233
 	) {
234
-		$messenger_name = str_replace( ' ', '_', ucwords( str_replace( '_', ' ', $messenger ) ) );
235
-		$mt_name = str_replace( ' ', '_', ucwords( str_replace( '_', ' ', $message_type ) ) );
234
+		$messenger_name = str_replace(' ', '_', ucwords(str_replace('_', ' ', $messenger)));
235
+		$mt_name = str_replace(' ', '_', ucwords(str_replace('_', ' ', $message_type)));
236 236
 		/** @var EE_Message_Resource_Manager $message_resource_manager */
237
-		$message_resource_manager = EE_Registry::instance()->load_lib( 'Message_Resource_Manager' );
237
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
238 238
 		//convert slug to object
239
-		$messenger = $message_resource_manager->get_messenger( $messenger );
239
+		$messenger = $message_resource_manager->get_messenger($messenger);
240 240
 
241 241
 		//if messenger isn't a EE_messenger resource then bail.
242
-		if ( ! $messenger instanceof EE_messenger ) {
242
+		if ( ! $messenger instanceof EE_messenger) {
243 243
 			return array();
244 244
 		}
245 245
 
246 246
 		//validate class for getting our list of shortcodes
247
-		$classname = 'EE_Messages_' . $messenger_name . '_' . $mt_name . '_Validator';
248
-		if ( ! class_exists( $classname ) ) {
249
-			$msg[] = __( 'The Validator class was unable to load', 'event_espresso' );
247
+		$classname = 'EE_Messages_'.$messenger_name.'_'.$mt_name.'_Validator';
248
+		if ( ! class_exists($classname)) {
249
+			$msg[] = __('The Validator class was unable to load', 'event_espresso');
250 250
 			$msg[] = sprintf(
251
-				__( 'The class name compiled was %s. Please check and make sure the spelling and case is correct for the class name and that there is an autoloader in place for this class', 'event_espresso' ),
251
+				__('The class name compiled was %s. Please check and make sure the spelling and case is correct for the class name and that there is an autoloader in place for this class', 'event_espresso'),
252 252
 				$classname
253 253
 			);
254
-			throw new EE_Error( implode( '||', $msg ) );
254
+			throw new EE_Error(implode('||', $msg));
255 255
 		}
256 256
 
257 257
 		/** @type EE_Messages_Validator $_VLD */
258
-		$_VLD = new $classname( array(), $context );
258
+		$_VLD = new $classname(array(), $context);
259 259
 		$valid_shortcodes = $_VLD->get_validators();
260 260
 
261 261
 		//let's make sure we're only getting the shortcode part of the validators
262 262
 		$shortcodes = array();
263
-		foreach ( $valid_shortcodes as $field => $validators ) {
264
-			$shortcodes[ $field ] = $validators['shortcodes'];
263
+		foreach ($valid_shortcodes as $field => $validators) {
264
+			$shortcodes[$field] = $validators['shortcodes'];
265 265
 		}
266 266
 		$valid_shortcodes = $shortcodes;
267 267
 
268 268
 		//if not all fields let's make sure we ONLY include the shortcodes for the specified fields.
269
-		if ( ! empty( $fields ) ) {
269
+		if ( ! empty($fields)) {
270 270
 			$specified_shortcodes = array();
271
-			foreach ( $fields as $field ) {
272
-				if ( isset( $valid_shortcodes[ $field ] ) ) {
273
-					$specified_shortcodes[ $field ] = $valid_shortcodes[ $field ];
271
+			foreach ($fields as $field) {
272
+				if (isset($valid_shortcodes[$field])) {
273
+					$specified_shortcodes[$field] = $valid_shortcodes[$field];
274 274
 				}
275 275
 			}
276 276
 			$valid_shortcodes = $specified_shortcodes;
277 277
 		}
278 278
 
279 279
 		//if not merged then let's replace the fields with the localized fields
280
-		if ( ! $merged ) {
280
+		if ( ! $merged) {
281 281
 			//let's get all the fields for the set messenger so that we can get the localized label and use that in the returned array.
282 282
 			$field_settings = $messenger->get_template_fields();
283 283
 			$localized = array();
284
-			foreach ( $valid_shortcodes as $field => $shortcodes ) {
284
+			foreach ($valid_shortcodes as $field => $shortcodes) {
285 285
 				//get localized field label
286
-				if ( isset( $field_settings[ $field ] ) ) {
286
+				if (isset($field_settings[$field])) {
287 287
 					//possible that this is used as a main field.
288
-					if ( empty( $field_settings[ $field ] ) ) {
289
-						if ( isset( $field_settings['extra'][ $field ] ) ) {
290
-							$_field = $field_settings['extra'][ $field ]['main']['label'];
288
+					if (empty($field_settings[$field])) {
289
+						if (isset($field_settings['extra'][$field])) {
290
+							$_field = $field_settings['extra'][$field]['main']['label'];
291 291
 						} else {
292 292
 							$_field = $field;
293 293
 						}
294 294
 					} else {
295
-						$_field = $field_settings[ $field ]['label'];
295
+						$_field = $field_settings[$field]['label'];
296 296
 					}
297
-				} else if ( isset( $field_settings['extra'] ) ) {
297
+				} else if (isset($field_settings['extra'])) {
298 298
 					//loop through extra "main fields" and see if any of their children have our field
299
-					foreach ( $field_settings['extra'] as $main_field => $fields ) {
300
-						if ( isset( $fields[ $field ] ) ) {
301
-							$_field = $fields[ $field ]['label'];
299
+					foreach ($field_settings['extra'] as $main_field => $fields) {
300
+						if (isset($fields[$field])) {
301
+							$_field = $fields[$field]['label'];
302 302
 						} else {
303 303
 							$_field = $field;
304 304
 						}
@@ -306,22 +306,22 @@  discard block
 block discarded – undo
306 306
 				} else {
307 307
 					$_field = $field;
308 308
 				}
309
-				if ( isset( $_field ) ) {
310
-					$localized[ $_field ] = $shortcodes;
309
+				if (isset($_field)) {
310
+					$localized[$_field] = $shortcodes;
311 311
 				}
312 312
 			}
313 313
 			$valid_shortcodes = $localized;
314 314
 		}
315 315
 
316 316
 		//if $merged then let's merge all the shortcodes into one list NOT indexed by field.
317
-		if ( $merged ) {
317
+		if ($merged) {
318 318
 			$merged_codes = array();
319
-			foreach ( $valid_shortcodes as $field => $shortcode ) {
320
-				foreach ( $shortcode as $code => $label ) {
321
-					if ( isset( $merged_codes[ $code ] ) ) {
319
+			foreach ($valid_shortcodes as $field => $shortcode) {
320
+				foreach ($shortcode as $code => $label) {
321
+					if (isset($merged_codes[$code])) {
322 322
 						continue;
323 323
 					} else {
324
-						$merged_codes[ $code ] = $label;
324
+						$merged_codes[$code] = $label;
325 325
 					}
326 326
 				}
327 327
 			}
@@ -341,10 +341,10 @@  discard block
 block discarded – undo
341 341
 	 * @throws \EE_Error
342 342
 	 * @return EE_messenger
343 343
 	 */
344
-	public static function messenger_obj( $messenger ) {
344
+	public static function messenger_obj($messenger) {
345 345
 		/** @type EE_Message_Resource_Manager $Message_Resource_Manager */
346
-		$Message_Resource_Manager = EE_Registry::instance()->load_lib( 'Message_Resource_Manager' );
347
-		return $Message_Resource_Manager->get_messenger( $messenger );
346
+		$Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
347
+		return $Message_Resource_Manager->get_messenger($messenger);
348 348
 	}
349 349
 
350 350
 
@@ -357,10 +357,10 @@  discard block
 block discarded – undo
357 357
 	 * @throws \EE_Error
358 358
 	 * @return EE_message_type
359 359
 	 */
360
-	public static function message_type_obj( $message_type ) {
360
+	public static function message_type_obj($message_type) {
361 361
 		/** @type EE_Message_Resource_Manager $Message_Resource_Manager */
362
-		$Message_Resource_Manager = EE_Registry::instance()->load_lib( 'Message_Resource_Manager' );
363
-		return $Message_Resource_Manager->get_message_type( $message_type );
362
+		$Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
363
+		return $Message_Resource_Manager->get_message_type($message_type);
364 364
 	}
365 365
 
366 366
 
@@ -374,11 +374,11 @@  discard block
 block discarded – undo
374 374
 	 * @param  string   $message_type message type to check for.
375 375
 	 * @return boolean
376 376
 	 */
377
-	public static function is_mt_active( $message_type ) {
377
+	public static function is_mt_active($message_type) {
378 378
 		/** @type EE_Message_Resource_Manager $Message_Resource_Manager */
379
-		$Message_Resource_Manager = EE_Registry::instance()->load_lib( 'Message_Resource_Manager' );
379
+		$Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
380 380
 		$active_mts = $Message_Resource_Manager->list_of_active_message_types();
381
-		return in_array( $message_type, $active_mts );
381
+		return in_array($message_type, $active_mts);
382 382
 	}
383 383
 
384 384
 
@@ -391,10 +391,10 @@  discard block
 block discarded – undo
391 391
 	 * @param  string  $messenger slug for messenger to check.
392 392
 	 * @return boolean
393 393
 	 */
394
-	public static function is_messenger_active( $messenger ) {
394
+	public static function is_messenger_active($messenger) {
395 395
 		/** @type EE_Message_Resource_Manager $Message_Resource_Manager */
396
-		$Message_Resource_Manager = EE_Registry::instance()->load_lib( 'Message_Resource_Manager' );
397
-		$active_messenger = $Message_Resource_Manager->get_active_messenger( $messenger );
396
+		$Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
397
+		$active_messenger = $Message_Resource_Manager->get_active_messenger($messenger);
398 398
 		return $active_messenger instanceof EE_messenger ? true : false;
399 399
 	}
400 400
 
@@ -412,11 +412,11 @@  discard block
 block discarded – undo
412 412
 	public static function get_active_messengers_in_db() {
413 413
 		EE_Error::doing_it_wrong(
414 414
 			__METHOD__,
415
-			__( 'Please use EE_Message_Resource_Manager::get_active_messengers_option() instead.', 'event_espresso' ),
415
+			__('Please use EE_Message_Resource_Manager::get_active_messengers_option() instead.', 'event_espresso'),
416 416
 			'4.9.0'
417 417
 		);
418 418
 		/** @var EE_Message_Resource_Manager $Message_Resource_Manager */
419
-		$Message_Resource_Manager = EE_Registry::instance()->load_lib( 'Message_Resource_Manager' );
419
+		$Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
420 420
 		return $Message_Resource_Manager->get_active_messengers_option();
421 421
 	}
422 422
 
@@ -433,15 +433,15 @@  discard block
 block discarded – undo
433 433
 	 *
434 434
 	 * @return bool FALSE if not updated, TRUE if updated.
435 435
 	 */
436
-	public static function update_active_messengers_in_db( $data_to_save ) {
436
+	public static function update_active_messengers_in_db($data_to_save) {
437 437
 		EE_Error::doing_it_wrong(
438 438
 			__METHOD__,
439
-			__( 'Please use EE_Message_Resource_Manager::update_active_messengers_option() instead.', 'event_espresso' ),
439
+			__('Please use EE_Message_Resource_Manager::update_active_messengers_option() instead.', 'event_espresso'),
440 440
 			'4.9.0'
441 441
 		);
442 442
 		/** @var EE_Message_Resource_Manager $Message_Resource_Manager */
443
-		$Message_Resource_Manager = EE_Registry::instance()->load_lib( 'Message_Resource_Manager' );
444
-		return $Message_Resource_Manager->update_active_messengers_option( $data_to_save );
443
+		$Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
444
+		return $Message_Resource_Manager->update_active_messengers_option($data_to_save);
445 445
 	}
446 446
 
447 447
 
@@ -465,34 +465,34 @@  discard block
 block discarded – undo
465 465
 		$sending_messenger = ''
466 466
 	) {
467 467
 		//first determine if the url can be to the EE_Message object.
468
-		if ( ! $message_type->always_generate() ) {
469
-			return EEH_MSG_Template::generate_browser_trigger( $message );
468
+		if ( ! $message_type->always_generate()) {
469
+			return EEH_MSG_Template::generate_browser_trigger($message);
470 470
 		}
471 471
 
472 472
 		//if $registration object is not valid then exit early because there's nothing that can be generated.
473
-		if ( ! $registration instanceof EE_Registration ) {
473
+		if ( ! $registration instanceof EE_Registration) {
474 474
 			throw new EE_Error(
475
-				__( 'Incoming value for registration is not a valid EE_Registration object.', 'event_espresso' )
475
+				__('Incoming value for registration is not a valid EE_Registration object.', 'event_espresso')
476 476
 			);
477 477
 		}
478 478
 
479 479
 		//validate given context
480 480
 		$contexts = $message_type->get_contexts();
481
-		if ( $message->context() !== '' && ! isset( $contexts[$message->context()] ) ) {
481
+		if ($message->context() !== '' && ! isset($contexts[$message->context()])) {
482 482
 			throw new EE_Error(
483 483
 				sprintf(
484
-					__( 'The context %s is not a valid context for %s.', 'event_espresso' ),
484
+					__('The context %s is not a valid context for %s.', 'event_espresso'),
485 485
 					$message->context(),
486
-					get_class( $message_type )
486
+					get_class($message_type)
487 487
 				)
488 488
 			);
489 489
 		}
490 490
 
491 491
 		//valid sending messenger but only if sending messenger set.  Otherwise generating messenger is used.
492
-		if ( ! empty( $sending_messenger ) ) {
492
+		if ( ! empty($sending_messenger)) {
493 493
 			$with_messengers = $message_type->with_messengers();
494
-			if ( ! isset( $with_messengers[$message->messenger()] )
495
-			     || ! in_array( $sending_messenger, $with_messengers[$message->messenger()] ) ) {
494
+			if ( ! isset($with_messengers[$message->messenger()])
495
+			     || ! in_array($sending_messenger, $with_messengers[$message->messenger()])) {
496 496
 				throw new EE_Error(
497 497
 					sprintf(
498 498
 						__(
@@ -500,7 +500,7 @@  discard block
 block discarded – undo
500 500
 							'event_espresso'
501 501
 						),
502 502
 						$sending_messenger,
503
-						get_class( $message_type )
503
+						get_class($message_type)
504 504
 					)
505 505
 				);
506 506
 			}
@@ -523,14 +523,14 @@  discard block
 block discarded – undo
523 523
 	 * @param EE_Message $message
524 524
 	 * @return string.
525 525
 	 */
526
-	public static function generate_browser_trigger( EE_Message $message ) {
526
+	public static function generate_browser_trigger(EE_Message $message) {
527 527
 		$query_args = array(
528 528
 			'ee' => 'msg_browser_trigger',
529 529
 			'token' => $message->MSG_token()
530 530
 		);
531 531
 		return apply_filters(
532 532
 			'FHEE__EEH_MSG_Template__generate_browser_trigger',
533
-			add_query_arg( $query_args, site_url() ),
533
+			add_query_arg($query_args, site_url()),
534 534
 			$message
535 535
 		);
536 536
 	}
@@ -545,7 +545,7 @@  discard block
 block discarded – undo
545 545
 	 * @param EE_Message $message
546 546
 	 * @return string
547 547
 	 */
548
-	public static function generate_error_display_trigger( EE_Message $message ) {
548
+	public static function generate_error_display_trigger(EE_Message $message) {
549 549
 		return apply_filters(
550 550
 			'FHEE__EEH_MSG_Template__generate_error_display_trigger',
551 551
 			add_query_arg(
@@ -595,7 +595,7 @@  discard block
 block discarded – undo
595 595
 			'GRP_ID' => $message_template_group,
596 596
 			'id' => $data_id
597 597
 			);
598
-		$url = add_query_arg( $query_args, get_home_url() );
598
+		$url = add_query_arg($query_args, get_home_url());
599 599
 
600 600
 		//made it here so now we can just get the url and filter it.  Filtered globally and by message type.
601 601
 		$url = apply_filters(
@@ -623,9 +623,9 @@  discard block
 block discarded – undo
623 623
 	 * @param string $type  What action to return.
624 624
 	 * @return string
625 625
 	 */
626
-	public static function get_message_action_icon( $type ) {
626
+	public static function get_message_action_icon($type) {
627 627
 		$action_icons = self::get_message_action_icons();
628
-		return isset( $action_icons[ $type ] ) ? $action_icons[ $type ] : '';
628
+		return isset($action_icons[$type]) ? $action_icons[$type] : '';
629 629
 	}
630 630
 
631 631
 
@@ -637,34 +637,34 @@  discard block
 block discarded – undo
637 637
 	 * @return array
638 638
 	 */
639 639
 	public static function get_message_action_icons() {
640
-		return apply_filters( 'FHEE__EEH_MSG_Template__message_action_icons',
640
+		return apply_filters('FHEE__EEH_MSG_Template__message_action_icons',
641 641
 			array(
642 642
 				'view' => array(
643
-					'label' => __( 'View Message', 'event_espresso' ),
643
+					'label' => __('View Message', 'event_espresso'),
644 644
 					'css_class' => 'dashicons dashicons-welcome-view-site',
645 645
 				),
646 646
 				'error' => array(
647
-					'label' => __( 'View Error Message', 'event_espresso' ),
647
+					'label' => __('View Error Message', 'event_espresso'),
648 648
 					'css_class' => 'dashicons dashicons-info',
649 649
 				),
650 650
 				'see_notifications_for' => array(
651
-					'label' => __( 'View Related Messages', 'event_espresso' ),
651
+					'label' => __('View Related Messages', 'event_espresso'),
652 652
 					'css_class' => 'dashicons dashicons-megaphone',
653 653
 				),
654 654
 				'generate_now' => array(
655
-					'label' => __( 'Generate the message now.', 'event_espresso' ),
655
+					'label' => __('Generate the message now.', 'event_espresso'),
656 656
 					'css_class' => 'dashicons dashicons-admin-tools',
657 657
 				),
658 658
 				'send_now' => array(
659
-					'label' => __( 'Send Immediately', 'event_espresso' ),
659
+					'label' => __('Send Immediately', 'event_espresso'),
660 660
 					'css_class' => 'dashicons dashicons-controls-forward',
661 661
 				),
662 662
 				'queue_for_resending' => array(
663
-					'label' => __( 'Queue for Resending', 'event_espresso' ),
663
+					'label' => __('Queue for Resending', 'event_espresso'),
664 664
 					'css_class' => 'dashicons dashicons-controls-repeat',
665 665
 				),
666 666
 				'view_transaction' => array(
667
-					'label' => __( 'View related Transaction', 'event_espresso' ),
667
+					'label' => __('View related Transaction', 'event_espresso'),
668 668
 					'css_class' => 'dashicons dashicons-cart',
669 669
 				)
670 670
 			)
@@ -683,9 +683,9 @@  discard block
 block discarded – undo
683 683
 	 *
684 684
 	 * @return string
685 685
 	 */
686
-	public static function get_message_action_url( $type, EE_Message $message = null, $query_params = array() ) {
687
-		$action_urls = self::get_message_action_urls( $message, $query_params );
688
-		return isset( $action_urls[ $type ] )  ? $action_urls[ $type ] : '';
686
+	public static function get_message_action_url($type, EE_Message $message = null, $query_params = array()) {
687
+		$action_urls = self::get_message_action_urls($message, $query_params);
688
+		return isset($action_urls[$type]) ? $action_urls[$type] : '';
689 689
 	}
690 690
 
691 691
 
@@ -700,15 +700,15 @@  discard block
 block discarded – undo
700 700
 	 *
701 701
 	 * @return array
702 702
 	 */
703
-	public static function get_message_action_urls( EE_Message $message = null, $query_params = array() ) {
704
-		EE_Registry::instance()->load_helper( 'URL' );
703
+	public static function get_message_action_urls(EE_Message $message = null, $query_params = array()) {
704
+		EE_Registry::instance()->load_helper('URL');
705 705
 		//if $message is not an instance of EE_Message then let's just do a dummy.
706
-		$message = empty( $message ) ? EE_Message_Factory::create() : $message;
707
-		$action_urls =  apply_filters(
706
+		$message = empty($message) ? EE_Message_Factory::create() : $message;
707
+		$action_urls = apply_filters(
708 708
 			'FHEE__EEH_MSG_Template__get_message_action_url',
709 709
 			array(
710
-				'view' => EEH_MSG_Template::generate_browser_trigger( $message ),
711
-				'error' => EEH_MSG_Template::generate_error_display_trigger( $message ),
710
+				'view' => EEH_MSG_Template::generate_browser_trigger($message),
711
+				'error' => EEH_MSG_Template::generate_error_display_trigger($message),
712 712
 				'see_notifications_for' => EEH_URL::add_query_args_and_nonce(
713 713
 					array_merge(
714 714
 						array(
@@ -718,7 +718,7 @@  discard block
 block discarded – undo
718 718
 						),
719 719
 						$query_params
720 720
 					),
721
-					admin_url( 'admin.php' )
721
+					admin_url('admin.php')
722 722
 				),
723 723
 				'generate_now' => EEH_URL::add_query_args_and_nonce(
724 724
 					array(
@@ -726,7 +726,7 @@  discard block
 block discarded – undo
726 726
 						'action' => 'generate_now',
727 727
 						'MSG_ID' => $message->ID()
728 728
 					),
729
-					admin_url( 'admin.php' )
729
+					admin_url('admin.php')
730 730
 				),
731 731
 				'send_now' => EEH_URL::add_query_args_and_nonce(
732 732
 					array(
@@ -734,7 +734,7 @@  discard block
 block discarded – undo
734 734
 						'action' => 'send_now',
735 735
 						'MSG_ID' => $message->ID()
736 736
 					),
737
-					admin_url( 'admin.php' )
737
+					admin_url('admin.php')
738 738
 				),
739 739
 				'queue_for_resending' => EEH_URL::add_query_args_and_nonce(
740 740
 					array(
@@ -742,7 +742,7 @@  discard block
 block discarded – undo
742 742
 						'action' => 'queue_for_resending',
743 743
 						'MSG_ID' => $message->ID()
744 744
 					),
745
-					admin_url( 'admin.php' )
745
+					admin_url('admin.php')
746 746
 				),
747 747
 			)
748 748
 		);
@@ -760,7 +760,7 @@  discard block
 block discarded – undo
760 760
 					'action' => 'view_transaction',
761 761
 					'TXN_ID' => $message->TXN_ID()
762 762
 				),
763
-				admin_url( 'admin.php' )
763
+				admin_url('admin.php')
764 764
 			);
765 765
 		} else {
766 766
 			$action_urls['view_transaction'] = '';
@@ -781,26 +781,26 @@  discard block
 block discarded – undo
781 781
 	 *
782 782
 	 * @return string
783 783
 	 */
784
-	public static function get_message_action_link( $type, EE_Message $message = null, $query_params = array() ) {
785
-		$url = EEH_MSG_Template::get_message_action_url( $type, $message, $query_params );
786
-		$icon_css = EEH_MSG_Template::get_message_action_icon( $type );
787
-		$title = isset( $icon_css['label'] ) ? 'title="' . $icon_css['label'] . '"' : '';
784
+	public static function get_message_action_link($type, EE_Message $message = null, $query_params = array()) {
785
+		$url = EEH_MSG_Template::get_message_action_url($type, $message, $query_params);
786
+		$icon_css = EEH_MSG_Template::get_message_action_icon($type);
787
+		$title = isset($icon_css['label']) ? 'title="'.$icon_css['label'].'"' : '';
788 788
 
789
-		if ( empty( $url ) || empty( $icon_css ) || ! isset( $icon_css['css_class'] ) ) {
789
+		if (empty($url) || empty($icon_css) || ! isset($icon_css['css_class'])) {
790 790
 			return '';
791 791
 		}
792 792
 
793 793
 		$icon_css['css_class'] .= esc_attr(
794 794
 			apply_filters(
795 795
 				'FHEE__EEH_MSG_Template__get_message_action_link__icon_css_class',
796
-				' js-ee-message-action-link ee-message-action-link-' . $type,
796
+				' js-ee-message-action-link ee-message-action-link-'.$type,
797 797
 				$type,
798 798
 				$message,
799 799
 				$query_params
800 800
 			)
801 801
 		);
802 802
 
803
-		return '<a href="' . $url . '"' . $title . '><span class="' . esc_attr( $icon_css['css_class'] ) . '"></span></a>';
803
+		return '<a href="'.$url.'"'.$title.'><span class="'.esc_attr($icon_css['css_class']).'"></span></a>';
804 804
 
805 805
 	}
806 806
 
@@ -838,9 +838,9 @@  discard block
 block discarded – undo
838 838
 	 * @param $reg_status
839 839
 	 * @return string
840 840
 	 */
841
-	public static function convert_reg_status_to_message_type( $reg_status ) {
841
+	public static function convert_reg_status_to_message_type($reg_status) {
842 842
 		$reg_status_array = self::reg_status_to_message_type_array();
843
-		return isset( $reg_status_array[$reg_status] ) ? $reg_status_array[$reg_status] : '';
843
+		return isset($reg_status_array[$reg_status]) ? $reg_status_array[$reg_status] : '';
844 844
 	}
845 845
 
846 846
 
@@ -874,9 +874,9 @@  discard block
 block discarded – undo
874 874
 	 * @param $payment_status
875 875
 	 * @return string
876 876
 	 */
877
-	public static function convert_payment_status_to_message_type( $payment_status ) {
877
+	public static function convert_payment_status_to_message_type($payment_status) {
878 878
 		$payment_status_array = self::payment_status_to_message_type_array();
879
-		return isset( $payment_status_array[$payment_status] ) ? $payment_status_array[$payment_status] : '';
879
+		return isset($payment_status_array[$payment_status]) ? $payment_status_array[$payment_status] : '';
880 880
 	}
881 881
 
882 882
 
@@ -887,32 +887,32 @@  discard block
 block discarded – undo
887 887
 	 *
888 888
 	 * @return EE_Messages_Template_Pack
889 889
 	 */
890
-	public static function get_template_pack( $template_pack_name ) {
891
-		if ( ! self::$_template_pack_collection instanceof EE_Object_Collection ) {
890
+	public static function get_template_pack($template_pack_name) {
891
+		if ( ! self::$_template_pack_collection instanceof EE_Object_Collection) {
892 892
 			self::$_template_pack_collection = new EE_Messages_Template_Pack_Collection();
893 893
 		}
894 894
 
895 895
 		//first see if in collection already
896
-		$template_pack = self::$_template_pack_collection->get_by_name( $template_pack_name );
896
+		$template_pack = self::$_template_pack_collection->get_by_name($template_pack_name);
897 897
 
898
-		if ( $template_pack instanceof EE_Messages_Template_Pack ) {
898
+		if ($template_pack instanceof EE_Messages_Template_Pack) {
899 899
 			return $template_pack;
900 900
 		}
901 901
 
902 902
 		//nope...let's get it.
903 903
 		//not set yet so let's attempt to get it.
904
-		$pack_class_name = 'EE_Messages_Template_Pack_' . str_replace(
904
+		$pack_class_name = 'EE_Messages_Template_Pack_'.str_replace(
905 905
 				' ',
906 906
 				'_',
907 907
 				ucwords(
908
-					str_replace( '_', ' ', $template_pack_name )
908
+					str_replace('_', ' ', $template_pack_name)
909 909
 				)
910 910
 			);
911
-		if ( ! class_exists( $pack_class_name ) && $template_pack_name !== 'default' ) {
912
-			return self::get_template_pack( 'default' );
911
+		if ( ! class_exists($pack_class_name) && $template_pack_name !== 'default') {
912
+			return self::get_template_pack('default');
913 913
 		} else {
914 914
 			$template_pack = new $pack_class_name;
915
-			self::$_template_pack_collection->add( $template_pack );
915
+			self::$_template_pack_collection->add($template_pack);
916 916
 			return $template_pack;
917 917
 		}
918 918
 	}
@@ -930,26 +930,26 @@  discard block
 block discarded – undo
930 930
 	 */
931 931
 	public static function get_template_pack_collection() {
932 932
 		$new_collection = false;
933
-		if ( ! self::$_template_pack_collection instanceof EE_Messages_Template_Pack_Collection ) {
933
+		if ( ! self::$_template_pack_collection instanceof EE_Messages_Template_Pack_Collection) {
934 934
 			self::$_template_pack_collection = new EE_Messages_Template_Pack_Collection();
935 935
 			$new_collection = true;
936 936
 		}
937 937
 
938 938
 		//glob the defaults directory for messages
939
-		$templates = glob( EE_LIBRARIES . 'messages/defaults/*', GLOB_ONLYDIR );
940
-		foreach( $templates as $template_path ) {
939
+		$templates = glob(EE_LIBRARIES.'messages/defaults/*', GLOB_ONLYDIR);
940
+		foreach ($templates as $template_path) {
941 941
 			//grab folder name
942
-			$template = basename( $template_path );
942
+			$template = basename($template_path);
943 943
 
944
-			if ( ! $new_collection ) {
944
+			if ( ! $new_collection) {
945 945
 				//already have it?
946
-				if ( self::$_template_pack_collection->get_by_name( $template ) instanceof EE_Messages_Template_Pack ) {
946
+				if (self::$_template_pack_collection->get_by_name($template) instanceof EE_Messages_Template_Pack) {
947 947
 					continue;
948 948
 				}
949 949
 			}
950 950
 
951 951
 			//setup classname.
952
-			$template_pack_class_name = 'EE_Messages_Template_Pack_' . str_replace(
952
+			$template_pack_class_name = 'EE_Messages_Template_Pack_'.str_replace(
953 953
 					' ',
954 954
 					'_',
955 955
 					ucwords(
@@ -960,20 +960,20 @@  discard block
 block discarded – undo
960 960
 						)
961 961
 					)
962 962
 				);
963
-			if ( ! class_exists( $template_pack_class_name ) ) {
963
+			if ( ! class_exists($template_pack_class_name)) {
964 964
 				continue;
965 965
 			}
966
-			self::$_template_pack_collection->add( new $template_pack_class_name );
966
+			self::$_template_pack_collection->add(new $template_pack_class_name);
967 967
 		}
968 968
 
969 969
 		/**
970 970
 		 * Filter for plugins to add in any additional template packs
971 971
 		 * Note the filter name here is for backward compat, this used to be found in EED_Messages.
972 972
 		 */
973
-		$additional_template_packs = apply_filters( 'FHEE__EED_Messages__get_template_packs__template_packs', array() );
974
-		foreach ( (array) $additional_template_packs as $template_pack ) {
975
-			if ( ! self::$_template_pack_collection->contains($template_pack ) ) {
976
-				self::$_template_pack_collection->add( $template_pack );
973
+		$additional_template_packs = apply_filters('FHEE__EED_Messages__get_template_packs__template_packs', array());
974
+		foreach ((array) $additional_template_packs as $template_pack) {
975
+			if ( ! self::$_template_pack_collection->contains($template_pack)) {
976
+				self::$_template_pack_collection->add($template_pack);
977 977
 			}
978 978
 		}
979 979
 		return self::$_template_pack_collection;
@@ -991,16 +991,16 @@  discard block
 block discarded – undo
991 991
 	 * @return array
992 992
 	 * @throws \EE_Error
993 993
 	 */
994
-	public static function create_new_templates( $messenger_name, $message_type_name, $GRP_ID = 0, $global = false ) {
994
+	public static function create_new_templates($messenger_name, $message_type_name, $GRP_ID = 0, $global = false) {
995 995
 		/** @type EE_Message_Resource_Manager $Message_Resource_Manager */
996
-		$Message_Resource_Manager = EE_Registry::instance()->load_lib( 'Message_Resource_Manager' );
997
-		$messenger = $Message_Resource_Manager->valid_messenger( $messenger_name );
998
-		$message_type = $Message_Resource_Manager->valid_message_type( $message_type_name );
999
-		if ( ! EEH_MSG_Template::message_type_has_active_templates_for_messenger( $messenger, $message_type, $global ) ) {
996
+		$Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
997
+		$messenger = $Message_Resource_Manager->valid_messenger($messenger_name);
998
+		$message_type = $Message_Resource_Manager->valid_message_type($message_type_name);
999
+		if ( ! EEH_MSG_Template::message_type_has_active_templates_for_messenger($messenger, $message_type, $global)) {
1000 1000
 			return array();
1001 1001
 		}
1002 1002
 		//whew made it this far!  Okay, let's go ahead and create the templates then
1003
-		return EEH_MSG_Template::_create_new_templates( $messenger, $message_type, $GRP_ID, $global );
1003
+		return EEH_MSG_Template::_create_new_templates($messenger, $message_type, $GRP_ID, $global);
1004 1004
 	}
1005 1005
 
1006 1006
 
@@ -1012,15 +1012,15 @@  discard block
 block discarded – undo
1012 1012
 	 * @param                  $global
1013 1013
 	 * @return array|mixed
1014 1014
 	 */
1015
-	protected static function _create_new_templates( EE_messenger $messenger, EE_message_type $message_type, $GRP_ID, $global ) {
1015
+	protected static function _create_new_templates(EE_messenger $messenger, EE_message_type $message_type, $GRP_ID, $global) {
1016 1016
 		//if we're creating a custom template then we don't need to use the defaults class
1017
-		if ( ! $global ) {
1018
-			return EEH_MSG_Template::_create_custom_template_group( $messenger, $message_type, $GRP_ID );
1017
+		if ( ! $global) {
1018
+			return EEH_MSG_Template::_create_custom_template_group($messenger, $message_type, $GRP_ID);
1019 1019
 		}
1020 1020
 		/** @type EE_Messages_Template_Defaults $Message_Template_Defaults */
1021 1021
 		$Message_Template_Defaults = EE_Registry::factory(
1022 1022
 			'EE_Messages_Template_Defaults',
1023
-			array( $messenger, $message_type, $GRP_ID )
1023
+			array($messenger, $message_type, $GRP_ID)
1024 1024
 		);
1025 1025
 		//generate templates
1026 1026
 		$success = $Message_Template_Defaults->create_new_templates();
@@ -1028,10 +1028,10 @@  discard block
 block discarded – undo
1028 1028
 		//if creating the template failed.  Then we should deactivate the related message_type for the messenger because
1029 1029
 		//its not active if it doesn't have a template.  Note this is only happening for GLOBAL template creation
1030 1030
 		//attempts.
1031
-		if ( ! $success ) {
1031
+		if ( ! $success) {
1032 1032
 			/** @var EE_Message_Resource_Manager $message_resource_manager */
1033
-			$message_resource_manager = EE_Registry::instance()->load_lib( 'Message_Resource_Manager' );
1034
-			$message_resource_manager->deactivate_message_type_for_messenger( $message_type->name, $messenger->name );
1033
+			$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1034
+			$message_resource_manager->deactivate_message_type_for_messenger($message_type->name, $messenger->name);
1035 1035
 		}
1036 1036
 
1037 1037
 		/**
@@ -1059,11 +1059,11 @@  discard block
 block discarded – undo
1059 1059
 	 * 										)
1060 1060
 	 * @access private
1061 1061
 	 */
1062
-	private static function _create_custom_template_group( EE_messenger $messenger, EE_message_type $message_type, $GRP_ID ) {
1062
+	private static function _create_custom_template_group(EE_messenger $messenger, EE_message_type $message_type, $GRP_ID) {
1063 1063
 		//defaults
1064
-		$success = array( 'GRP_ID' => null, 'MTP_context' => '' );
1064
+		$success = array('GRP_ID' => null, 'MTP_context' => '');
1065 1065
 		//get the template group to use as a template from the db.  If $GRP_ID is empty then we'll assume the base will be the global template matching the messenger and message type.
1066
-		$Message_Template_Group = empty( $GRP_ID )
1066
+		$Message_Template_Group = empty($GRP_ID)
1067 1067
 			? EEM_Message_Template_Group::instance()->get_one(
1068 1068
 				array(
1069 1069
 					array(
@@ -1073,9 +1073,9 @@  discard block
 block discarded – undo
1073 1073
 					)
1074 1074
 				)
1075 1075
 			)
1076
-			: EEM_Message_Template_Group::instance()->get_one_by_ID( $GRP_ID );
1076
+			: EEM_Message_Template_Group::instance()->get_one_by_ID($GRP_ID);
1077 1077
 		//if we don't have a mtg at this point then we need to bail.
1078
-		if ( ! $Message_Template_Group instanceof EE_Message_Template_Group ) {
1078
+		if ( ! $Message_Template_Group instanceof EE_Message_Template_Group) {
1079 1079
 			EE_Error::add_error(
1080 1080
 				sprintf(
1081 1081
 					__(
@@ -1094,42 +1094,42 @@  discard block
 block discarded – undo
1094 1094
 		$message_templates = $Message_Template_Group->message_templates();
1095 1095
 		//now we have what we need to setup the new template
1096 1096
 		$new_mtg = clone $Message_Template_Group;
1097
-		$new_mtg->set( 'GRP_ID', 0 );
1098
-		$new_mtg->set( 'MTP_is_global', false );
1099
-		$template_name = defined( 'DOING_AJAX' ) && ! empty( $_POST[ 'templateName' ] )
1100
-			? $_POST[ 'templateName' ]
1097
+		$new_mtg->set('GRP_ID', 0);
1098
+		$new_mtg->set('MTP_is_global', false);
1099
+		$template_name = defined('DOING_AJAX') && ! empty($_POST['templateName'])
1100
+			? $_POST['templateName']
1101 1101
 			: __(
1102 1102
 				'New Custom Template',
1103 1103
 				'event_espresso'
1104 1104
 			);
1105
-		$template_description = defined( "DOING_AJAX" ) && ! empty( $_POST[ 'templateDescription' ] )
1106
-			? $_POST[ 'templateDescription' ]
1105
+		$template_description = defined("DOING_AJAX") && ! empty($_POST['templateDescription'])
1106
+			? $_POST['templateDescription']
1107 1107
 			: sprintf(
1108 1108
 				__(
1109 1109
 					'This is a custom template that was created for the %s messenger and %s message type.',
1110 1110
 					'event_espresso'
1111 1111
 				),
1112
-				$new_mtg->messenger_obj()->label[ 'singular' ],
1113
-				$new_mtg->message_type_obj()->label[ 'singular' ]
1112
+				$new_mtg->messenger_obj()->label['singular'],
1113
+				$new_mtg->message_type_obj()->label['singular']
1114 1114
 			);
1115
-		$new_mtg->set( 'MTP_name', $template_name );
1116
-		$new_mtg->set( 'MTP_description', $template_description );
1115
+		$new_mtg->set('MTP_name', $template_name);
1116
+		$new_mtg->set('MTP_description', $template_description);
1117 1117
 		//remove ALL relations on this template group so they don't get saved!
1118
-		$new_mtg->_remove_relations( 'Message_Template' );
1118
+		$new_mtg->_remove_relations('Message_Template');
1119 1119
 		$new_mtg->save();
1120
-		$success[ 'GRP_ID' ] = $new_mtg->ID();
1121
-		$success[ 'template_name' ] = $template_name;
1120
+		$success['GRP_ID'] = $new_mtg->ID();
1121
+		$success['template_name'] = $template_name;
1122 1122
 		//add new message templates and add relation to.
1123
-		foreach ( $message_templates as $message_template ) {
1124
-			if ( ! $message_template instanceof EE_Message_Template ) {
1123
+		foreach ($message_templates as $message_template) {
1124
+			if ( ! $message_template instanceof EE_Message_Template) {
1125 1125
 				continue;
1126 1126
 			}
1127 1127
 			$new_message_template = clone $message_template;
1128
-			$new_message_template->set( 'MTP_ID', 0 );
1129
-			$new_message_template->set( 'GRP_ID', $new_mtg->ID() ); //relation
1128
+			$new_message_template->set('MTP_ID', 0);
1129
+			$new_message_template->set('GRP_ID', $new_mtg->ID()); //relation
1130 1130
 			$new_message_template->save();
1131
-			if ( empty( $success[ 'MTP_context' ] ) ) {
1132
-				$success[ 'MTP_context' ] = $new_message_template->get( 'MTP_context' );
1131
+			if (empty($success['MTP_context'])) {
1132
+				$success['MTP_context'] = $new_message_template->get('MTP_context');
1133 1133
 			}
1134 1134
 		}
1135 1135
 		return $success;
@@ -1151,7 +1151,7 @@  discard block
 block discarded – undo
1151 1151
 		$global = false
1152 1152
 	) {
1153 1153
 		//is given message_type valid for given messenger (if this is not a global save)
1154
-		if ( $global ) {
1154
+		if ($global) {
1155 1155
 			return true;
1156 1156
 		}
1157 1157
 		$active_templates = EEM_Message_Template_Group::instance()->count(
@@ -1163,7 +1163,7 @@  discard block
 block discarded – undo
1163 1163
 				)
1164 1164
 			)
1165 1165
 		);
1166
-		if ( $active_templates > 0 ) {
1166
+		if ($active_templates > 0) {
1167 1167
 			return true;
1168 1168
 		}
1169 1169
 		EE_Error::add_error(
@@ -1192,30 +1192,30 @@  discard block
 block discarded – undo
1192 1192
 	 * @param  string $message_type_name name of EE_message_type
1193 1193
 	 * @return array
1194 1194
 	 */
1195
-	public static function get_fields( $messenger_name, $message_type_name ) {
1195
+	public static function get_fields($messenger_name, $message_type_name) {
1196 1196
 		$template_fields = array();
1197 1197
 		/** @type EE_Message_Resource_Manager $Message_Resource_Manager */
1198
-		$Message_Resource_Manager = EE_Registry::instance()->load_lib( 'Message_Resource_Manager' );
1199
-		$messenger = $Message_Resource_Manager->valid_messenger( $messenger_name );
1200
-		$message_type = $Message_Resource_Manager->valid_message_type( $message_type_name );
1201
-		if ( ! EEH_MSG_Template::message_type_has_active_templates_for_messenger( $messenger, $message_type ) ) {
1198
+		$Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1199
+		$messenger = $Message_Resource_Manager->valid_messenger($messenger_name);
1200
+		$message_type = $Message_Resource_Manager->valid_message_type($message_type_name);
1201
+		if ( ! EEH_MSG_Template::message_type_has_active_templates_for_messenger($messenger, $message_type)) {
1202 1202
 			return array();
1203 1203
 		}
1204 1204
 
1205 1205
         $excluded_fields_for_messenger = $message_type->excludedFieldsForMessenger($messenger_name);
1206 1206
 
1207 1207
 		//okay now let's assemble an array with the messenger template fields added to the message_type contexts.
1208
-		foreach ( $message_type->get_contexts() as $context => $details ) {
1209
-			foreach ( $messenger->get_template_fields() as $field => $value ) {
1208
+		foreach ($message_type->get_contexts() as $context => $details) {
1209
+			foreach ($messenger->get_template_fields() as $field => $value) {
1210 1210
 			    if (in_array($field, $excluded_fields_for_messenger, true)) {
1211 1211
 			        continue;
1212 1212
                 }
1213
-				$template_fields[ $context ][ $field ] = $value;
1213
+				$template_fields[$context][$field] = $value;
1214 1214
 			}
1215 1215
 		}
1216
-		if ( empty( $template_fields ) ) {
1216
+		if (empty($template_fields)) {
1217 1217
 			EE_Error::add_error(
1218
-				__( 'Something went wrong and we couldn\'t get any templates assembled', 'event_espresso' ),
1218
+				__('Something went wrong and we couldn\'t get any templates assembled', 'event_espresso'),
1219 1219
 				__FILE__,
1220 1220
 				__FUNCTION__,
1221 1221
 				__LINE__
Please login to merge, or discard this patch.
message_type/newsletter/EE_Messages_Email_Newsletter_Validator.class.php 1 patch
Indentation   +65 added lines, -65 removed lines patch added patch discarded remove patch
@@ -13,72 +13,72 @@
 block discarded – undo
13 13
  */
14 14
 class EE_Messages_Email_Newsletter_Validator extends EE_Messages_Validator
15 15
 {
16
-    /**
17
-     * EE_Messages_Email_Newsletter_Validator constructor.
18
-     *
19
-     * @param array $fields
20
-     * @param string $context
21
-     * @throws EE_Error
22
-     * @throws ReflectionException
23
-     */
24
-    public function __construct(array $fields, $context)
25
-    {
26
-        $this->_m_name = 'email';
27
-        $this->_mt_name = 'newsletter';
16
+	/**
17
+	 * EE_Messages_Email_Newsletter_Validator constructor.
18
+	 *
19
+	 * @param array $fields
20
+	 * @param string $context
21
+	 * @throws EE_Error
22
+	 * @throws ReflectionException
23
+	 */
24
+	public function __construct(array $fields, $context)
25
+	{
26
+		$this->_m_name = 'email';
27
+		$this->_mt_name = 'newsletter';
28 28
 
29
-        parent::__construct($fields, $context);
30
-    }
29
+		parent::__construct($fields, $context);
30
+	}
31 31
 
32
-    /**
33
-     * custom validator (restricting what was originally set by the messenger)
34
-     */
35
-    protected function _modify_validator()
36
-    {
37
-        if ($this->_context === 'attendee') {
38
-            $this->_valid_shortcodes_modifier[$this->_context]['from'] = array(
39
-                'recipient_details',
40
-                'email',
41
-                'organization',
42
-            );
43
-        }
32
+	/**
33
+	 * custom validator (restricting what was originally set by the messenger)
34
+	 */
35
+	protected function _modify_validator()
36
+	{
37
+		if ($this->_context === 'attendee') {
38
+			$this->_valid_shortcodes_modifier[$this->_context]['from'] = array(
39
+				'recipient_details',
40
+				'email',
41
+				'organization',
42
+			);
43
+		}
44 44
 
45
-        //excluded shortcodes
46
-        $fields = array('to', 'from', 'subject', 'content', 'newsletter_content');
47
-        foreach ($fields as $field) {
48
-            $this->_specific_shortcode_excludes[$field] = array(
49
-                '[RECIPIENT_REGISTRATION_CODE]',
50
-                '[EVENT_AUTHOR_FORMATTED_EMAIL]',
51
-                '[EVENT_AUTHOR_EMAIL]',
52
-            );
53
-        }
54
-        $add_excludes = array(
55
-            '[RECIPIENT_FNAME]',
56
-            '[RECIPIENT_LNAME]',
57
-            '[RECIPIENT_EMAIL]',
58
-            '[COMPANY]',
59
-            '[CO_ADD1]',
60
-            '[CO_ADD2]',
61
-            '[CO_CITY]',
62
-            '[CO_STATE]',
63
-            '[CO_ZIP]',
64
-            '[CO_LOGO]',
65
-            '[CO_PHONE]',
66
-            '[CO_LOGO_URL]',
67
-            '[CO_FACEBOOK_URL]',
68
-            '[CO_TWITTER_URL]',
69
-            '[CO_PINTEREST_URL]',
70
-            '[CO_GOOGLE_URL]',
71
-            '[CO_LINKEDIN_URL]',
72
-            '[CO_INSTAGRAM_URL]',
73
-        );
74
-        $this->_specific_shortcode_excludes['from'] =
75
-            array_merge(
76
-                $this->_specific_shortcode_excludes['from'],
77
-                $add_excludes
78
-            );
79
-        $this->_specific_shortcode_excludes['content'] = array_merge(
80
-            $this->_specific_shortcode_excludes['content'],
81
-            array('[DISPLAY_PDF_URL]', '[DISPLAY_PDF_BUTTON]')
82
-        );
83
-    }
45
+		//excluded shortcodes
46
+		$fields = array('to', 'from', 'subject', 'content', 'newsletter_content');
47
+		foreach ($fields as $field) {
48
+			$this->_specific_shortcode_excludes[$field] = array(
49
+				'[RECIPIENT_REGISTRATION_CODE]',
50
+				'[EVENT_AUTHOR_FORMATTED_EMAIL]',
51
+				'[EVENT_AUTHOR_EMAIL]',
52
+			);
53
+		}
54
+		$add_excludes = array(
55
+			'[RECIPIENT_FNAME]',
56
+			'[RECIPIENT_LNAME]',
57
+			'[RECIPIENT_EMAIL]',
58
+			'[COMPANY]',
59
+			'[CO_ADD1]',
60
+			'[CO_ADD2]',
61
+			'[CO_CITY]',
62
+			'[CO_STATE]',
63
+			'[CO_ZIP]',
64
+			'[CO_LOGO]',
65
+			'[CO_PHONE]',
66
+			'[CO_LOGO_URL]',
67
+			'[CO_FACEBOOK_URL]',
68
+			'[CO_TWITTER_URL]',
69
+			'[CO_PINTEREST_URL]',
70
+			'[CO_GOOGLE_URL]',
71
+			'[CO_LINKEDIN_URL]',
72
+			'[CO_INSTAGRAM_URL]',
73
+		);
74
+		$this->_specific_shortcode_excludes['from'] =
75
+			array_merge(
76
+				$this->_specific_shortcode_excludes['from'],
77
+				$add_excludes
78
+			);
79
+		$this->_specific_shortcode_excludes['content'] = array_merge(
80
+			$this->_specific_shortcode_excludes['content'],
81
+			array('[DISPLAY_PDF_URL]', '[DISPLAY_PDF_BUTTON]')
82
+		);
83
+	}
84 84
 }
Please login to merge, or discard this patch.
messages/message_type/newsletter/EE_Newsletter_message_type.class.php 2 patches
Indentation   +190 added lines, -190 removed lines patch added patch discarded remove patch
@@ -14,196 +14,196 @@
 block discarded – undo
14 14
 class EE_Newsletter_message_type extends EE_message_type
15 15
 {
16 16
 
17
-    public function __construct()
18
-    {
19
-        $this->name = 'newsletter';
20
-        $this->description = esc_html__(
21
-            'Batch message type messages are triggered manually by the admin for sending notifications to a selected group of recipients. This should only be used for more general notification type messages that contain information specific for the recipients. For "newsletter" type messages we recommend using an email list service like MailChimp, because sending non-related mail-outs to contacts increases the risk of your site domain getting added to spam lists, which will prevent messages getting to users.',
22
-            'event_espresso'
23
-        );
24
-        $this->label = array(
25
-            'singular' => esc_html__('batch', 'event_espresso'),
26
-            'plural'   => esc_html__('batches', 'event_espresso'),
27
-        );
28
-        $this->_master_templates = array(
29
-            'email' => 'registration',
30
-        );
31
-
32
-        parent::__construct();
33
-    }
34
-
35
-
36
-    /**
37
-     * Sets admin_registered_pages property
38
-     */
39
-    protected function _set_admin_pages()
40
-    {
41
-        $this->admin_registered_pages = array(); //no admin pages to register this with.
42
-    }
43
-
44
-
45
-    /**
46
-     * Sets property related to data handler.
47
-     */
48
-    protected function _set_data_handler()
49
-    {
50
-        $this->_data_handler = 'Registrations';
51
-        $this->_single_message = $this->_data instanceof EE_Registration;
52
-    }
53
-
54
-
55
-    /**
56
-     * Returns the data for the given context for this message type.
57
-     * @param string          $context
58
-     * @param EE_Registration $registration
59
-     * @param int             $id
60
-     * @return array|mixed
61
-     */
62
-    protected function _get_data_for_context($context, EE_Registration $registration, $id)
63
-    {
64
-        //newsletter message type data handler is 'Registrations' and it expects an array of EE_Registration objects.
65
-        return array($registration);
66
-    }
67
-
68
-
69
-    /**
70
-     * Sets the admin settings fields property for this message type.
71
-     */
72
-    protected function _set_admin_settings_fields()
73
-    {
74
-        $this->_admin_settings_fields = array();
75
-    }
76
-
77
-
78
-    /**
79
-     * Sets the contexts for this message type.
80
-     */
81
-    protected function _set_contexts()
82
-    {
83
-        $this->_context_label = array(
84
-            'label'       => esc_html__('recipient', 'event_espresso'),
85
-            'plural'      => esc_html__('recipients', 'event_espresso'),
86
-            'description' => esc_html__('Recipient\'s are who will receive the message.', 'event_espresso'),
87
-        );
88
-
89
-        $this->_contexts = array(
90
-            'attendee' => array(
91
-                'label'       => esc_html__('Registrant', 'event_espresso'),
92
-                'description' => esc_html__('This template goes to selected registrants.', 'event_espresso'),
93
-            ),
94
-        );
95
-    }
96
-
97
-
98
-    /**
99
-     * used to set the valid shortcodes.
100
-     * For the newsletter message type we only have two valid shortcode libraries in use, recipient details and
101
-     * organization.  That's it!
102
-     *
103
-     * @since   4.3.0
104
-     * @return  void
105
-     */
106
-    protected function _set_valid_shortcodes()
107
-    {
108
-        parent::_set_valid_shortcodes();
109
-
110
-        $included_shortcodes = array(
111
-            'recipient_details',
112
-            'organization',
113
-            'newsletter',
114
-        );
115
-
116
-        foreach ($this->_valid_shortcodes as $context => $shortcodes) {
117
-            foreach ($shortcodes as $key => $shortcode) {
118
-                if (! in_array($shortcode, $included_shortcodes, true)) {
119
-                    unset($this->_valid_shortcodes[$context][$key]);
120
-                }
121
-            }
122
-            $this->_valid_shortcodes[$context][] = 'newsletter';
123
-        }
124
-    }
125
-
126
-
127
-    /**
128
-     * Override default _attendee_addressees in EE_message_type because we want to loop through the registrations
129
-     * for EE_message_type.
130
-     *
131
-     * @return array
132
-     * @throws EE_Error
133
-     * @throws InvalidArgumentException
134
-     * @throws ReflectionException
135
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
136
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
137
-     */
138
-    protected function _attendee_addressees()
139
-    {
140
-        $addressee = array();
141
-
142
-        //looping through registrations
143
-        foreach ($this->_data->registrations as $reg_id => $details) {
144
-            //set $attendee array to blank on each loop
145
-            $aee = array();
146
-
147
-            //need to get the attendee from this registration.
148
-            $attendee = isset($details['att_obj']) && $details['att_obj'] instanceof EE_Attendee
149
-                ? $details['att_obj']
150
-                : null;
151
-
152
-            if (! $attendee instanceof EE_Attendee) {
153
-                continue;
154
-            }
155
-
156
-            //set $aee from attendee object
157
-            $aee['att_obj'] = $attendee;
158
-            $aee['reg_objs'] = isset($this->_data->attendees[$attendee->ID()]['reg_objs'])
159
-                ? $this->_data->attendees[$attendee->ID()]['reg_objs']
160
-                : array();
161
-            $aee['attendee_email'] = $attendee->email();
162
-            $aee['tkt_objs'] = isset($this->_data->attendees[$attendee->ID()]['tkt_objs'])
163
-                ? $this->_data->attendees[$attendee->ID()]['tkt_objs']
164
-                : array();
165
-
166
-            if (isset($this->_data->attendees[$attendee->ID()]['evt_objs'])) {
167
-                $aee['evt_objs'] = $this->_data->attendees[$attendee->ID()]['evt_objs'];
168
-                $aee['events'] = $this->_data->attendees[$attendee->ID()]['evt_objs'];
169
-            } else {
170
-                $aee['evt_objs'] = $aee['events'] = array();
171
-            }
172
-
173
-            $aee['reg_obj'] = isset($details['reg_obj'])
174
-                ? $details['reg_obj']
175
-                : null;
176
-            $aee['attendees'] = $this->_data->attendees;
177
-
178
-            //merge in the primary attendee data
179
-            $aee = array_merge($this->_default_addressee_data, $aee);
180
-
181
-            //make sure txn is set
182
-            if (empty($aee['txn']) && $aee['reg_obj'] instanceof EE_Registration) {
183
-                $aee['txn'] = $aee['reg_obj']->transaction();
184
-            }
185
-
186
-            $addressee[] = new EE_Messages_Addressee($aee);
187
-        }
188
-        return $addressee;
189
-    }
190
-
191
-    /**
192
-     * Allows a message type to specifically exclude template fields for the provided messenger.
193
-     * Filtered so this can be programmatically altered as well.
194
-     *
195
-     * @param string $messenger_name name of messenger
196
-     * @return array
197
-     */
198
-    public function excludedFieldsForMessenger($messenger_name)
199
-    {
200
-        $excluded_fields = array(
201
-            'email' => array('cc')
202
-        );
203
-        return isset($excluded_fields[$messenger_name])
204
-            ? $excluded_fields[$messenger_name]
205
-            : parent::excludedFieldsForMessenger($messenger_name);
206
-    }
17
+	public function __construct()
18
+	{
19
+		$this->name = 'newsletter';
20
+		$this->description = esc_html__(
21
+			'Batch message type messages are triggered manually by the admin for sending notifications to a selected group of recipients. This should only be used for more general notification type messages that contain information specific for the recipients. For "newsletter" type messages we recommend using an email list service like MailChimp, because sending non-related mail-outs to contacts increases the risk of your site domain getting added to spam lists, which will prevent messages getting to users.',
22
+			'event_espresso'
23
+		);
24
+		$this->label = array(
25
+			'singular' => esc_html__('batch', 'event_espresso'),
26
+			'plural'   => esc_html__('batches', 'event_espresso'),
27
+		);
28
+		$this->_master_templates = array(
29
+			'email' => 'registration',
30
+		);
31
+
32
+		parent::__construct();
33
+	}
34
+
35
+
36
+	/**
37
+	 * Sets admin_registered_pages property
38
+	 */
39
+	protected function _set_admin_pages()
40
+	{
41
+		$this->admin_registered_pages = array(); //no admin pages to register this with.
42
+	}
43
+
44
+
45
+	/**
46
+	 * Sets property related to data handler.
47
+	 */
48
+	protected function _set_data_handler()
49
+	{
50
+		$this->_data_handler = 'Registrations';
51
+		$this->_single_message = $this->_data instanceof EE_Registration;
52
+	}
53
+
54
+
55
+	/**
56
+	 * Returns the data for the given context for this message type.
57
+	 * @param string          $context
58
+	 * @param EE_Registration $registration
59
+	 * @param int             $id
60
+	 * @return array|mixed
61
+	 */
62
+	protected function _get_data_for_context($context, EE_Registration $registration, $id)
63
+	{
64
+		//newsletter message type data handler is 'Registrations' and it expects an array of EE_Registration objects.
65
+		return array($registration);
66
+	}
67
+
68
+
69
+	/**
70
+	 * Sets the admin settings fields property for this message type.
71
+	 */
72
+	protected function _set_admin_settings_fields()
73
+	{
74
+		$this->_admin_settings_fields = array();
75
+	}
76
+
77
+
78
+	/**
79
+	 * Sets the contexts for this message type.
80
+	 */
81
+	protected function _set_contexts()
82
+	{
83
+		$this->_context_label = array(
84
+			'label'       => esc_html__('recipient', 'event_espresso'),
85
+			'plural'      => esc_html__('recipients', 'event_espresso'),
86
+			'description' => esc_html__('Recipient\'s are who will receive the message.', 'event_espresso'),
87
+		);
88
+
89
+		$this->_contexts = array(
90
+			'attendee' => array(
91
+				'label'       => esc_html__('Registrant', 'event_espresso'),
92
+				'description' => esc_html__('This template goes to selected registrants.', 'event_espresso'),
93
+			),
94
+		);
95
+	}
96
+
97
+
98
+	/**
99
+	 * used to set the valid shortcodes.
100
+	 * For the newsletter message type we only have two valid shortcode libraries in use, recipient details and
101
+	 * organization.  That's it!
102
+	 *
103
+	 * @since   4.3.0
104
+	 * @return  void
105
+	 */
106
+	protected function _set_valid_shortcodes()
107
+	{
108
+		parent::_set_valid_shortcodes();
109
+
110
+		$included_shortcodes = array(
111
+			'recipient_details',
112
+			'organization',
113
+			'newsletter',
114
+		);
115
+
116
+		foreach ($this->_valid_shortcodes as $context => $shortcodes) {
117
+			foreach ($shortcodes as $key => $shortcode) {
118
+				if (! in_array($shortcode, $included_shortcodes, true)) {
119
+					unset($this->_valid_shortcodes[$context][$key]);
120
+				}
121
+			}
122
+			$this->_valid_shortcodes[$context][] = 'newsletter';
123
+		}
124
+	}
125
+
126
+
127
+	/**
128
+	 * Override default _attendee_addressees in EE_message_type because we want to loop through the registrations
129
+	 * for EE_message_type.
130
+	 *
131
+	 * @return array
132
+	 * @throws EE_Error
133
+	 * @throws InvalidArgumentException
134
+	 * @throws ReflectionException
135
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
136
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
137
+	 */
138
+	protected function _attendee_addressees()
139
+	{
140
+		$addressee = array();
141
+
142
+		//looping through registrations
143
+		foreach ($this->_data->registrations as $reg_id => $details) {
144
+			//set $attendee array to blank on each loop
145
+			$aee = array();
146
+
147
+			//need to get the attendee from this registration.
148
+			$attendee = isset($details['att_obj']) && $details['att_obj'] instanceof EE_Attendee
149
+				? $details['att_obj']
150
+				: null;
151
+
152
+			if (! $attendee instanceof EE_Attendee) {
153
+				continue;
154
+			}
155
+
156
+			//set $aee from attendee object
157
+			$aee['att_obj'] = $attendee;
158
+			$aee['reg_objs'] = isset($this->_data->attendees[$attendee->ID()]['reg_objs'])
159
+				? $this->_data->attendees[$attendee->ID()]['reg_objs']
160
+				: array();
161
+			$aee['attendee_email'] = $attendee->email();
162
+			$aee['tkt_objs'] = isset($this->_data->attendees[$attendee->ID()]['tkt_objs'])
163
+				? $this->_data->attendees[$attendee->ID()]['tkt_objs']
164
+				: array();
165
+
166
+			if (isset($this->_data->attendees[$attendee->ID()]['evt_objs'])) {
167
+				$aee['evt_objs'] = $this->_data->attendees[$attendee->ID()]['evt_objs'];
168
+				$aee['events'] = $this->_data->attendees[$attendee->ID()]['evt_objs'];
169
+			} else {
170
+				$aee['evt_objs'] = $aee['events'] = array();
171
+			}
172
+
173
+			$aee['reg_obj'] = isset($details['reg_obj'])
174
+				? $details['reg_obj']
175
+				: null;
176
+			$aee['attendees'] = $this->_data->attendees;
177
+
178
+			//merge in the primary attendee data
179
+			$aee = array_merge($this->_default_addressee_data, $aee);
180
+
181
+			//make sure txn is set
182
+			if (empty($aee['txn']) && $aee['reg_obj'] instanceof EE_Registration) {
183
+				$aee['txn'] = $aee['reg_obj']->transaction();
184
+			}
185
+
186
+			$addressee[] = new EE_Messages_Addressee($aee);
187
+		}
188
+		return $addressee;
189
+	}
190
+
191
+	/**
192
+	 * Allows a message type to specifically exclude template fields for the provided messenger.
193
+	 * Filtered so this can be programmatically altered as well.
194
+	 *
195
+	 * @param string $messenger_name name of messenger
196
+	 * @return array
197
+	 */
198
+	public function excludedFieldsForMessenger($messenger_name)
199
+	{
200
+		$excluded_fields = array(
201
+			'email' => array('cc')
202
+		);
203
+		return isset($excluded_fields[$messenger_name])
204
+			? $excluded_fields[$messenger_name]
205
+			: parent::excludedFieldsForMessenger($messenger_name);
206
+	}
207 207
 
208 208
 
209 209
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -115,7 +115,7 @@  discard block
 block discarded – undo
115 115
 
116 116
         foreach ($this->_valid_shortcodes as $context => $shortcodes) {
117 117
             foreach ($shortcodes as $key => $shortcode) {
118
-                if (! in_array($shortcode, $included_shortcodes, true)) {
118
+                if ( ! in_array($shortcode, $included_shortcodes, true)) {
119 119
                     unset($this->_valid_shortcodes[$context][$key]);
120 120
                 }
121 121
             }
@@ -149,7 +149,7 @@  discard block
 block discarded – undo
149 149
                 ? $details['att_obj']
150 150
                 : null;
151 151
 
152
-            if (! $attendee instanceof EE_Attendee) {
152
+            if ( ! $attendee instanceof EE_Attendee) {
153 153
                 continue;
154 154
             }
155 155
 
Please login to merge, or discard this patch.
modules/ticket_sales_monitor/EED_Ticket_Sales_Monitor.module.php 2 patches
Indentation   +1050 added lines, -1050 removed lines patch added patch discarded remove patch
@@ -24,1057 +24,1057 @@
 block discarded – undo
24 24
 class EED_Ticket_Sales_Monitor extends EED_Module
25 25
 {
26 26
 
27
-    const debug = false;    //	true false
28
-
29
-    /**
30
-     * an array of raw ticket data from EED_Ticket_Selector
31
-     *
32
-     * @var array $ticket_selections
33
-     */
34
-    protected $ticket_selections = array();
35
-
36
-    /**
37
-     * the raw ticket data from EED_Ticket_Selector is organized in rows
38
-     * according to how they are displayed in the actual Ticket_Selector
39
-     * this tracks the current row being processed
40
-     *
41
-     * @var int $current_row
42
-     */
43
-    protected $current_row = 0;
44
-
45
-    /**
46
-     * an array for tracking names of tickets that have sold out
47
-     *
48
-     * @var array $sold_out_tickets
49
-     */
50
-    protected $sold_out_tickets = array();
51
-
52
-    /**
53
-     * an array for tracking names of tickets that have had their quantities reduced
54
-     *
55
-     * @var array $decremented_tickets
56
-     */
57
-    protected $decremented_tickets = array();
58
-
59
-
60
-
61
-    /**
62
-     * set_hooks - for hooking into EE Core, other modules, etc
63
-     *
64
-     * @return    void
65
-     */
66
-    public static function set_hooks()
67
-    {
68
-        // release tickets for expired carts
69
-        add_action(
70
-            'EED_Ticket_Selector__process_ticket_selections__before',
71
-            array('EED_Ticket_Sales_Monitor', 'release_tickets_for_expired_carts'),
72
-            1
73
-        );
74
-        // check ticket reserves AFTER MER does it's check (hence priority 20)
75
-        add_filter(
76
-            'FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty',
77
-            array('EED_Ticket_Sales_Monitor', 'validate_ticket_sale'),
78
-            20,
79
-            3
80
-        );
81
-        // add notices for sold out tickets
82
-        add_action(
83
-            'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
84
-            array('EED_Ticket_Sales_Monitor', 'post_notices'),
85
-            10
86
-        );
87
-        // handle ticket quantities adjusted in cart
88
-        //add_action(
89
-        //	'FHEE__EED_Multi_Event_Registration__adjust_line_item_quantity__line_item_quantity_updated',
90
-        //	array( 'EED_Ticket_Sales_Monitor', 'ticket_quantity_updated' ),
91
-        //	10, 2
92
-        //);
93
-        // handle tickets deleted from cart
94
-        add_action(
95
-            'FHEE__EED_Multi_Event_Registration__delete_ticket__ticket_removed_from_cart',
96
-            array('EED_Ticket_Sales_Monitor', 'ticket_removed_from_cart'),
97
-            10,
98
-            2
99
-        );
100
-        // handle emptied carts
101
-        add_action(
102
-            'AHEE__EE_Session__reset_cart__before_reset',
103
-            array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
104
-            10,
105
-            1
106
-        );
107
-        add_action(
108
-            'AHEE__EED_Multi_Event_Registration__empty_event_cart__before_delete_cart',
109
-            array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
110
-            10,
111
-            1
112
-        );
113
-        // handle cancelled registrations
114
-        add_action(
115
-            'AHEE__EE_Session__reset_checkout__before_reset',
116
-            array('EED_Ticket_Sales_Monitor', 'session_checkout_reset'),
117
-            10,
118
-            1
119
-        );
120
-        // cron tasks
121
-        add_action(
122
-            'AHEE__EE_Cron_Tasks__process_expired_transactions__abandoned_transaction',
123
-            array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
124
-            10,
125
-            1
126
-        );
127
-        add_action(
128
-            'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_transaction',
129
-            array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
130
-            10,
131
-            1
132
-        );
133
-        add_action(
134
-            'AHEE__EE_Cron_Tasks__process_expired_transactions__failed_transaction',
135
-            array('EED_Ticket_Sales_Monitor', 'process_failed_transactions'),
136
-            10,
137
-            1
138
-        );
139
-    }
140
-
141
-
142
-
143
-    /**
144
-     * set_hooks_admin - for hooking into EE Admin Core, other modules, etc
145
-     *
146
-     * @return void
147
-     */
148
-    public static function set_hooks_admin()
149
-    {
150
-        EED_Ticket_Sales_Monitor::set_hooks();
151
-    }
152
-
153
-
154
-
155
-    /**
156
-     * @return EED_Ticket_Sales_Monitor|EED_Module
157
-     */
158
-    public static function instance()
159
-    {
160
-        return parent::get_instance(__CLASS__);
161
-    }
162
-
163
-
164
-
165
-    /**
166
-     * @param WP_Query $WP_Query
167
-     * @return    void
168
-     */
169
-    public function run($WP_Query)
170
-    {
171
-    }
172
-
173
-
174
-
175
-    /********************************** PRE_TICKET_SALES  **********************************/
176
-
177
-
178
-
179
-    /**
180
-     * Retrieves grand totals from the line items that have no TXN ID
181
-     * and timestamps less than the current time minus the session lifespan.
182
-     * These are carts that have been abandoned before the "registrant" even attempted to checkout.
183
-     * We're going to release the tickets for these line items before attempting to add more to the cart.
184
-     *
185
-     * @return void
186
-     * @throws DomainException
187
-     * @throws EE_Error
188
-     * @throws InvalidArgumentException
189
-     * @throws InvalidDataTypeException
190
-     * @throws InvalidInterfaceException
191
-     * @throws UnexpectedEntityException
192
-     */
193
-    public static function release_tickets_for_expired_carts()
194
-    {
195
-        do_action('AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__begin');
196
-        $expired_ticket_IDs      = array();
197
-        $valid_ticket_line_items = array();
198
-        $total_line_items        = EEM_Line_Item::instance()->get_total_line_items_with_no_transaction();
199
-        if (empty($total_line_items)) {
200
-            do_action(
201
-                'AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__end',
202
-                $total_line_items,
203
-                $valid_ticket_line_items,
204
-                $expired_ticket_IDs
205
-            );
206
-            return;
207
-        }
208
-        /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
209
-        $session_lifespan = LoaderFactory::getLoader()->getShared(
210
-            'EventEspresso\core\domain\values\session\SessionLifespan'
211
-        );
212
-        foreach ($total_line_items as $total_line_item) {
213
-            /** @var EE_Line_Item $total_line_item */
214
-            $ticket_line_items = EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total($total_line_item);
215
-            foreach ($ticket_line_items as $ticket_line_item) {
216
-                if (! $ticket_line_item instanceof EE_Line_Item) {
217
-                    continue;
218
-                }
219
-                if ($total_line_item->timestamp(true) <= $session_lifespan->expiration()) {
220
-                    $expired_ticket_IDs[ $ticket_line_item->OBJ_ID() ] = $ticket_line_item->OBJ_ID();
221
-                } else {
222
-                    $valid_ticket_line_items[ $ticket_line_item->OBJ_ID() ] = $ticket_line_item;
223
-                }
224
-            }
225
-        }
226
-        if (! empty($expired_ticket_IDs)) {
227
-            EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
228
-                \EEM_Ticket::instance()->get_tickets_with_IDs($expired_ticket_IDs),
229
-                $valid_ticket_line_items,
230
-                __FUNCTION__
231
-            );
232
-            // let's get rid of expired line items so that they can't interfere with tracking
233
-            add_action(
234
-                'shutdown',
235
-                array('EED_Ticket_Sales_Monitor', 'clear_expired_line_items_with_no_transaction'),
236
-                999
237
-            );
238
-        }
239
-        do_action(
240
-            'AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__end',
241
-            $total_line_items,
242
-            $valid_ticket_line_items,
243
-            $expired_ticket_IDs
244
-        );
245
-    }
246
-
247
-
248
-
249
-    /********************************** VALIDATE_TICKET_SALE  **********************************/
250
-
251
-
252
-
253
-    /**
254
-     * callback for 'FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data'
255
-     *
256
-     * @param int       $qty
257
-     * @param EE_Ticket $ticket
258
-     * @return bool
259
-     * @throws UnexpectedEntityException
260
-     * @throws EE_Error
261
-     */
262
-    public static function validate_ticket_sale($qty = 1, EE_Ticket $ticket)
263
-    {
264
-        $qty = absint($qty);
265
-        if ($qty > 0) {
266
-            $qty = EED_Ticket_Sales_Monitor::instance()->_validate_ticket_sale($ticket, $qty);
267
-        }
268
-        if (self::debug) {
269
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '()';
270
-            echo '<br /><br /><b> RETURNED QTY: ' . $qty . '</b>';
271
-        }
272
-        return $qty;
273
-    }
274
-
275
-
276
-
277
-    /**
278
-     * checks whether an individual ticket is available for purchase based on datetime, and ticket details
279
-     *
280
-     * @param   EE_Ticket $ticket
281
-     * @param int         $qty
282
-     * @return int
283
-     * @throws UnexpectedEntityException
284
-     * @throws EE_Error
285
-     */
286
-    protected function _validate_ticket_sale(EE_Ticket $ticket, $qty = 1)
287
-    {
288
-        if (self::debug) {
289
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
290
-        }
291
-        if (! $ticket instanceof EE_Ticket) {
292
-            return 0;
293
-        }
294
-        if (self::debug) {
295
-            echo '<br /><b> . ticket->ID: ' . $ticket->ID() . '</b>';
296
-            echo '<br /> . original ticket->reserved: ' . $ticket->reserved();
297
-        }
298
-        $ticket->refresh_from_db();
299
-        // first let's determine the ticket availability based on sales
300
-        $available = $ticket->qty('saleable');
301
-        if (self::debug) {
302
-            echo '<br /> . . . ticket->qty: ' . $ticket->qty();
303
-            echo '<br /> . . . ticket->sold: ' . $ticket->sold();
304
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
305
-            echo '<br /> . . . ticket->qty(saleable): ' . $ticket->qty('saleable');
306
-            echo '<br /> . . . available: ' . $available;
307
-        }
308
-        if ($available < 1) {
309
-            $this->_ticket_sold_out($ticket);
310
-            return 0;
311
-        }
312
-        if (self::debug) {
313
-            echo '<br /> . . . qty: ' . $qty;
314
-        }
315
-        if ($available < $qty) {
316
-            $qty = $available;
317
-            if (self::debug) {
318
-                echo '<br /> . . . QTY ADJUSTED: ' . $qty;
319
-            }
320
-            $this->_ticket_quantity_decremented($ticket);
321
-        }
322
-        $this->_reserve_ticket($ticket, $qty);
323
-        return $qty;
324
-    }
325
-
326
-
327
-
328
-    /**
329
-     * increments ticket reserved based on quantity passed
330
-     *
331
-     * @param    EE_Ticket $ticket
332
-     * @param int          $quantity
333
-     * @return bool
334
-     * @throws EE_Error
335
-     */
336
-    protected function _reserve_ticket(EE_Ticket $ticket, $quantity = 1)
337
-    {
338
-        if (self::debug) {
339
-            echo '<br /><br /> . . . INCREASE RESERVED: ' . $quantity;
340
-        }
341
-        $ticket->increase_reserved($quantity, 'TicketSalesMonitor:'. __LINE__);
342
-        return $ticket->save();
343
-    }
344
-
345
-
346
-
347
-    /**
348
-     * @param  EE_Ticket $ticket
349
-     * @param  int       $quantity
350
-     * @return bool
351
-     * @throws EE_Error
352
-     */
353
-    protected function _release_reserved_ticket(EE_Ticket $ticket, $quantity = 1)
354
-    {
355
-        if (self::debug) {
356
-            echo '<br /> . . . ticket->ID: ' . $ticket->ID();
357
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
358
-        }
359
-        $ticket->decrease_reserved($quantity, true, 'TicketSalesMonitor:'. __LINE__);
360
-        if (self::debug) {
361
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
362
-        }
363
-        return $ticket->save() ? 1 : 0;
364
-    }
365
-
366
-
367
-
368
-    /**
369
-     * removes quantities within the ticket selector based on zero ticket availability
370
-     *
371
-     * @param    EE_Ticket $ticket
372
-     * @return    void
373
-     * @throws UnexpectedEntityException
374
-     * @throws EE_Error
375
-     */
376
-    protected function _ticket_sold_out(EE_Ticket $ticket)
377
-    {
378
-        if (self::debug) {
379
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
380
-            echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
381
-        }
382
-        $this->sold_out_tickets[] = $this->_get_ticket_and_event_name($ticket);
383
-    }
384
-
385
-
386
-
387
-    /**
388
-     * adjusts quantities within the ticket selector based on decreased ticket availability
389
-     *
390
-     * @param    EE_Ticket $ticket
391
-     * @return void
392
-     * @throws UnexpectedEntityException
393
-     * @throws EE_Error
394
-     */
395
-    protected function _ticket_quantity_decremented(EE_Ticket $ticket)
396
-    {
397
-        if (self::debug) {
398
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
399
-            echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
400
-        }
401
-        $this->decremented_tickets[] = $this->_get_ticket_and_event_name($ticket);
402
-    }
403
-
404
-
405
-
406
-    /**
407
-     * builds string out of ticket and event name
408
-     *
409
-     * @param    EE_Ticket $ticket
410
-     * @return string
411
-     * @throws UnexpectedEntityException
412
-     * @throws EE_Error
413
-     */
414
-    protected function _get_ticket_and_event_name(EE_Ticket $ticket)
415
-    {
416
-        $event = $ticket->get_related_event();
417
-        if ($event instanceof EE_Event) {
418
-            $ticket_name = sprintf(
419
-                _x('%1$s for %2$s', 'ticket name for event name', 'event_espresso'),
420
-                $ticket->name(),
421
-                $event->name()
422
-            );
423
-        } else {
424
-            $ticket_name = $ticket->name();
425
-        }
426
-        return $ticket_name;
427
-    }
428
-
429
-
430
-
431
-    /********************************** EVENT CART  **********************************/
432
-
433
-
434
-
435
-    /**
436
-     * releases or reserves ticket(s) based on quantity passed
437
-     *
438
-     * @param  EE_Line_Item $line_item
439
-     * @param  int          $quantity
440
-     * @return void
441
-     * @throws EE_Error
442
-     * @throws InvalidArgumentException
443
-     * @throws InvalidDataTypeException
444
-     * @throws InvalidInterfaceException
445
-     */
446
-    public static function ticket_quantity_updated(EE_Line_Item $line_item, $quantity = 1)
447
-    {
448
-        $ticket = EEM_Ticket::instance()->get_one_by_ID(absint($line_item->OBJ_ID()));
449
-        if ($ticket instanceof EE_Ticket) {
450
-            $ticket->add_extra_meta(
451
-                EE_Ticket::META_KEY_TICKET_RESERVATIONS,
452
-                __LINE__ . ') ' . __METHOD__ . '()'
453
-            );
454
-            if ($quantity > 0) {
455
-                EED_Ticket_Sales_Monitor::instance()->_reserve_ticket($ticket, $quantity);
456
-            } else {
457
-                EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
458
-            }
459
-        }
460
-    }
461
-
462
-
463
-
464
-    /**
465
-     * releases reserved ticket(s) based on quantity passed
466
-     *
467
-     * @param  EE_Ticket $ticket
468
-     * @param  int       $quantity
469
-     * @return void
470
-     * @throws EE_Error
471
-     */
472
-    public static function ticket_removed_from_cart(EE_Ticket $ticket, $quantity = 1)
473
-    {
474
-        $ticket->add_extra_meta(
475
-            EE_Ticket::META_KEY_TICKET_RESERVATIONS,
476
-            __LINE__ . ') ' . __METHOD__ . '()'
477
-        );
478
-        EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
479
-    }
480
-
481
-
482
-
483
-    /********************************** POST_NOTICES  **********************************/
484
-
485
-
486
-
487
-    /**
488
-     * @return void
489
-     * @throws EE_Error
490
-     * @throws InvalidArgumentException
491
-     * @throws ReflectionException
492
-     * @throws InvalidDataTypeException
493
-     * @throws InvalidInterfaceException
494
-     */
495
-    public static function post_notices()
496
-    {
497
-        EED_Ticket_Sales_Monitor::instance()->_post_notices();
498
-    }
499
-
500
-
501
-
502
-    /**
503
-     * @return void
504
-     * @throws EE_Error
505
-     * @throws InvalidArgumentException
506
-     * @throws ReflectionException
507
-     * @throws InvalidDataTypeException
508
-     * @throws InvalidInterfaceException
509
-     */
510
-    protected function _post_notices()
511
-    {
512
-        if (self::debug) {
513
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
514
-        }
515
-        $refresh_msg    = '';
516
-        $none_added_msg = '';
517
-        if (defined('DOING_AJAX') && DOING_AJAX) {
518
-            $refresh_msg    = __(
519
-                'Please refresh the page to view updated ticket quantities.',
520
-                'event_espresso'
521
-            );
522
-            $none_added_msg = __('No tickets were added for the event.', 'event_espresso');
523
-        }
524
-        if (! empty($this->sold_out_tickets)) {
525
-            EE_Error::add_attention(
526
-                sprintf(
527
-                    apply_filters(
528
-                        'FHEE__EED_Ticket_Sales_Monitor___post_notices__sold_out_tickets_notice',
529
-                        __(
530
-                            'We\'re sorry...%1$sThe following items have sold out since you first viewed this page, and can no longer be registered for:%1$s%1$s%2$s%1$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%1$s%1$s%3$s%1$s%4$s%1$s',
531
-                            'event_espresso'
532
-                        )
533
-                    ),
534
-                    '<br />',
535
-                    implode('<br />', $this->sold_out_tickets),
536
-                    $none_added_msg,
537
-                    $refresh_msg
538
-                )
539
-            );
540
-            // alter code flow in the Ticket Selector for better UX
541
-            add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', '__return_true');
542
-            add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__success', '__return_false');
543
-            $this->sold_out_tickets = array();
544
-            // and reset the cart
545
-            EED_Ticket_Sales_Monitor::session_cart_reset(EE_Registry::instance()->SSN);
546
-        }
547
-        if (! empty($this->decremented_tickets)) {
548
-            EE_Error::add_attention(
549
-                sprintf(
550
-                    apply_filters(
551
-                        'FHEE__EED_Ticket_Sales_Monitor___ticket_quantity_decremented__notice',
552
-                        __(
553
-                            'We\'re sorry...%1$sDue to sales that have occurred since you first viewed the last page, the following items have had their quantities adjusted to match the current available amount:%1$s%1$s%2$s%1$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%1$s%1$s%3$s%1$s%4$s%1$s',
554
-                            'event_espresso'
555
-                        )
556
-                    ),
557
-                    '<br />',
558
-                    implode('<br />', $this->decremented_tickets),
559
-                    $none_added_msg,
560
-                    $refresh_msg
561
-                )
562
-            );
563
-            $this->decremented_tickets = array();
564
-        }
565
-    }
566
-
567
-
568
-
569
-    /********************************** RELEASE_ALL_RESERVED_TICKETS_FOR_TRANSACTION  **********************************/
570
-
571
-
572
-
573
-    /**
574
-     * releases reserved tickets for all registrations of an EE_Transaction
575
-     * by default, will NOT release tickets for finalized transactions
576
-     *
577
-     * @param    EE_Transaction $transaction
578
-     * @return int
579
-     * @throws EE_Error
580
-     * @throws InvalidSessionDataException
581
-     */
582
-    protected function _release_all_reserved_tickets_for_transaction(EE_Transaction $transaction)
583
-    {
584
-        if (self::debug) {
585
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
586
-            echo '<br /> . transaction->ID: ' . $transaction->ID();
587
-            echo '<br /> . TXN status_ID: ' . $transaction->status_ID();
588
-        }
589
-        // check if 'finalize_registration' step has been completed...
590
-        $finalized = $transaction->reg_step_completed('finalize_registration');
591
-        if (self::debug) {
592
-            // DEBUG LOG
593
-            EEH_Debug_Tools::log(
594
-                __CLASS__,
595
-                __FUNCTION__,
596
-                __LINE__,
597
-                array('finalized' => $finalized),
598
-                false,
599
-                'EE_Transaction: ' . $transaction->ID()
600
-            );
601
-        }
602
-        // how many tickets were released
603
-        $count = 0;
604
-        if (self::debug) {
605
-            echo '<br /> . . . TXN finalized: ' . $finalized;
606
-        }
607
-        $release_tickets_with_TXN_status = array(
608
-            EEM_Transaction::failed_status_code,
609
-            EEM_Transaction::abandoned_status_code,
610
-            EEM_Transaction::incomplete_status_code,
611
-        );
612
-        $events = array();
613
-        // if the session is getting cleared BEFORE the TXN has been finalized or the transaction is not completed
614
-        if (! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
615
-            // cancel any reserved tickets for registrations that were not approved
616
-            $registrations = $transaction->registrations();
617
-            if (self::debug) {
618
-                echo '<br /> . . . # registrations: ' . count($registrations);
619
-                $reg    = reset($registrations);
620
-                $ticket = $reg->ticket();
621
-                if ($ticket instanceof EE_Ticket) {
622
-                    $ticket->add_extra_meta(
623
-                        EE_Ticket::META_KEY_TICKET_RESERVATIONS,
624
-                        __LINE__ . ') Release All Tickets TXN:' . $transaction->ID()
625
-                    );
626
-                }
627
-            }
628
-            if (! empty($registrations)) {
629
-                foreach ($registrations as $registration) {
630
-                    if (
631
-                        $registration instanceof EE_Registration
632
-                        && $this->_release_reserved_ticket_for_registration($registration, $transaction)
633
-                    ) {
634
-                        $count++;
635
-                        $events[ $registration->event_ID() ] = $registration->event();
636
-                    }
637
-                }
638
-            }
639
-        }
640
-        if ($events !== array()) {
641
-            foreach ($events as $event) {
642
-                /** @var EE_Event $event */
643
-                $event->perform_sold_out_status_check();
644
-            }
645
-        }
646
-        return $count;
647
-    }
648
-
649
-
650
-
651
-    /**
652
-     * releases reserved tickets for an EE_Registration
653
-     * by default, will NOT release tickets for APPROVED registrations
654
-     *
655
-     * @param EE_Registration $registration
656
-     * @param EE_Transaction  $transaction
657
-     * @return int
658
-     * @throws EE_Error
659
-     */
660
-    protected function _release_reserved_ticket_for_registration(
661
-        EE_Registration $registration,
662
-        EE_Transaction $transaction
663
-    ) {
664
-        $STS_ID = $transaction->status_ID();
665
-        if (self::debug) {
666
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
667
-            echo '<br /> . . registration->ID: ' . $registration->ID();
668
-            echo '<br /> . . registration->status_ID: ' . $registration->status_ID();
669
-            echo '<br /> . . transaction->status_ID(): ' . $STS_ID;
670
-        }
671
-        if (
672
-            // release Tickets for Failed Transactions and Abandoned Transactions
673
-            $STS_ID === EEM_Transaction::failed_status_code
674
-            || $STS_ID === EEM_Transaction::abandoned_status_code
675
-            || (
676
-                // also release Tickets for Incomplete Transactions, but ONLY if the Registrations are NOT Approved
677
-                $STS_ID === EEM_Transaction::incomplete_status_code
678
-                && $registration->status_ID() !== EEM_Registration::status_id_approved
679
-            )
680
-        ) {
681
-            if (self::debug) {
682
-                echo '<br /><br /> . . RELEASE RESERVED TICKET';
683
-                $rsrvd = $registration->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true);
684
-                echo '<br /> . . . registration HAS_RESERVED_TICKET_KEY: ';
685
-                var_dump($rsrvd);
686
-            }
687
-            $registration->release_reserved_ticket(true, 'TicketSalesMonitor:'. __LINE__);
688
-            return 1;
689
-        }
690
-        return 0;
691
-    }
692
-
693
-
694
-
695
-    /********************************** SESSION_CART_RESET  **********************************/
696
-
697
-
698
-
699
-    /**
700
-     * callback hooked into 'AHEE__EE_Session__reset_cart__before_reset'
701
-     *
702
-     * @param EE_Session $session
703
-     * @return void
704
-     * @throws EE_Error
705
-     * @throws InvalidArgumentException
706
-     * @throws ReflectionException
707
-     * @throws InvalidDataTypeException
708
-     * @throws InvalidInterfaceException
709
-     */
710
-    public static function session_cart_reset(EE_Session $session)
711
-    {
712
-        if (self::debug) {
713
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
714
-        }
715
-        // first check of the session has a valid Checkout object
716
-        $checkout = $session->checkout();
717
-        if ($checkout instanceof EE_Checkout) {
718
-            // and use that to clear ticket reservations because it will update the associated registration meta data
719
-            EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
720
-            return;
721
-        }
722
-        $cart = $session->cart();
723
-        if ($cart instanceof EE_Cart) {
724
-            if (self::debug) {
725
-                echo '<br /><br /> cart instance of EE_Cart: ';
726
-            }
727
-            EED_Ticket_Sales_Monitor::instance()->_session_cart_reset($cart, $session);
728
-        } else {
729
-            if (self::debug) {
730
-                echo '<br /><br /> invalid EE_Cart: ';
731
-                var_export($cart, true);
732
-            }
733
-        }
734
-    }
735
-
736
-
737
-
738
-    /**
739
-     * releases reserved tickets in the EE_Cart
740
-     *
741
-     * @param EE_Cart $cart
742
-     * @return void
743
-     * @throws EE_Error
744
-     * @throws InvalidArgumentException
745
-     * @throws ReflectionException
746
-     * @throws InvalidDataTypeException
747
-     * @throws InvalidInterfaceException
748
-     */
749
-    protected function _session_cart_reset(EE_Cart $cart, EE_Session $session)
750
-    {
751
-        if (self::debug) {
752
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
753
-        }
754
-        EE_Registry::instance()->load_helper('Line_Item');
755
-        $ticket_line_items = $cart->get_tickets();
756
-        if (empty($ticket_line_items)) {
757
-            return;
758
-        }
759
-        foreach ($ticket_line_items as $ticket_line_item) {
760
-            if (self::debug) {
761
-                echo '<br /> . ticket_line_item->ID(): ' . $ticket_line_item->ID();
762
-            }
763
-            if ($ticket_line_item instanceof EE_Line_Item && $ticket_line_item->OBJ_type() === 'Ticket') {
764
-                if (self::debug) {
765
-                    echo '<br /> . . ticket_line_item->OBJ_ID(): ' . $ticket_line_item->OBJ_ID();
766
-                }
767
-                $ticket = EEM_Ticket::instance()->get_one_by_ID($ticket_line_item->OBJ_ID());
768
-                if ($ticket instanceof EE_Ticket) {
769
-                    if (self::debug) {
770
-                        echo '<br /> . . ticket->ID(): ' . $ticket->ID();
771
-                        echo '<br /> . . ticket_line_item->quantity(): ' . $ticket_line_item->quantity();
772
-                    }
773
-                    $ticket->add_extra_meta(
774
-                        EE_Ticket::META_KEY_TICKET_RESERVATIONS,
775
-                        __LINE__ . ') ' . __METHOD__ . '() SID = ' . $session->id()
776
-                    );
777
-                    $this->_release_reserved_ticket($ticket, $ticket_line_item->quantity());
778
-                }
779
-            }
780
-        }
781
-        if (self::debug) {
782
-            echo '<br /><br /> RESET COMPLETED ';
783
-        }
784
-    }
785
-
786
-
787
-
788
-    /********************************** SESSION_CHECKOUT_RESET  **********************************/
789
-
790
-
791
-
792
-    /**
793
-     * callback hooked into 'AHEE__EE_Session__reset_checkout__before_reset'
794
-     *
795
-     * @param EE_Session $session
796
-     * @return void
797
-     * @throws EE_Error
798
-     * @throws InvalidSessionDataException
799
-     */
800
-    public static function session_checkout_reset(EE_Session $session)
801
-    {
802
-        $checkout = $session->checkout();
803
-        if ($checkout instanceof EE_Checkout) {
804
-            EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
805
-        }
806
-    }
807
-
808
-
809
-
810
-    /**
811
-     * releases reserved tickets for the EE_Checkout->transaction
812
-     *
813
-     * @param EE_Checkout $checkout
814
-     * @return void
815
-     * @throws EE_Error
816
-     * @throws InvalidSessionDataException
817
-     */
818
-    protected function _session_checkout_reset(EE_Checkout $checkout)
819
-    {
820
-        if (self::debug) {
821
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
822
-        }
823
-        // we want to release the each registration's reserved tickets if the session was cleared, but not if this is a revisit
824
-        if ($checkout->revisit || ! $checkout->transaction instanceof EE_Transaction) {
825
-            return;
826
-        }
827
-        $this->_release_all_reserved_tickets_for_transaction($checkout->transaction);
828
-    }
829
-
830
-
831
-
832
-    /********************************** SESSION_EXPIRED_RESET  **********************************/
833
-
834
-
835
-
836
-    /**
837
-     * @param    EE_Session $session
838
-     * @return    void
839
-     */
840
-    public static function session_expired_reset(EE_Session $session)
841
-    {
842
-    }
843
-
844
-
845
-
846
-    /********************************** PROCESS_ABANDONED_TRANSACTIONS  **********************************/
847
-
848
-
849
-
850
-    /**
851
-     * releases reserved tickets for all registrations of an ABANDONED EE_Transaction
852
-     * by default, will NOT release tickets for free transactions, or any that have received a payment
853
-     *
854
-     * @param EE_Transaction $transaction
855
-     * @return void
856
-     * @throws EE_Error
857
-     * @throws InvalidSessionDataException
858
-     */
859
-    public static function process_abandoned_transactions(EE_Transaction $transaction)
860
-    {
861
-        // is this TXN free or has any money been paid towards this TXN? If so, then leave it alone
862
-        if ($transaction->is_free() || $transaction->paid() > 0) {
863
-            if (self::debug) {
864
-                // DEBUG LOG
865
-                EEH_Debug_Tools::log(
866
-                    __CLASS__,
867
-                    __FUNCTION__,
868
-                    __LINE__,
869
-                    array($transaction),
870
-                    false,
871
-                    'EE_Transaction: ' . $transaction->ID()
872
-                );
873
-            }
874
-            return;
875
-        }
876
-        // have their been any successful payments made ?
877
-        $payments = $transaction->payments();
878
-        foreach ($payments as $payment) {
879
-            if ($payment instanceof EE_Payment && $payment->status() === EEM_Payment::status_id_approved) {
880
-                if (self::debug) {
881
-                    // DEBUG LOG
882
-                    EEH_Debug_Tools::log(
883
-                        __CLASS__,
884
-                        __FUNCTION__,
885
-                        __LINE__,
886
-                        array($payment),
887
-                        false,
888
-                        'EE_Transaction: ' . $transaction->ID()
889
-                    );
890
-                }
891
-                return;
892
-            }
893
-        }
894
-        // since you haven't even attempted to pay for your ticket...
895
-        EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
896
-    }
897
-
898
-
899
-
900
-    /********************************** PROCESS_FAILED_TRANSACTIONS  **********************************/
901
-
902
-
903
-
904
-    /**
905
-     * releases reserved tickets for absolutely ALL registrations of a FAILED EE_Transaction
906
-     *
907
-     * @param EE_Transaction $transaction
908
-     * @return void
909
-     * @throws EE_Error
910
-     * @throws InvalidSessionDataException
911
-     */
912
-    public static function process_failed_transactions(EE_Transaction $transaction)
913
-    {
914
-        // since you haven't even attempted to pay for your ticket...
915
-        EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
916
-    }
917
-
918
-
919
-
920
-    /********************************** RESET RESERVATION COUNTS  *********************************/
921
-
922
-
923
-
924
-    /**
925
-     * Resets all ticket and datetime reserved counts to zero
926
-     * Tickets that are currently associated with a Transaction that is in progress
927
-     *
928
-     * @throws EE_Error
929
-     * @throws DomainException
930
-     * @throws InvalidDataTypeException
931
-     * @throws InvalidInterfaceException
932
-     * @throws InvalidArgumentException
933
-     * @throws UnexpectedEntityException
934
-     */
935
-    public static function reset_reservation_counts()
936
-    {
937
-        /** @var EE_Line_Item[] $valid_reserved_tickets */
938
-        $valid_reserved_tickets = array();
939
-        /** @var EE_Transaction[] $transactions_not_in_progress */
940
-        $transactions_not_in_progress = EEM_Transaction::instance()->get_transactions_not_in_progress();
941
-        foreach ($transactions_not_in_progress as $transaction) {
942
-            // if this TXN has been fully completed, then skip it
943
-            if ($transaction->reg_step_completed('finalize_registration')) {
944
-                continue;
945
-            }
946
-            $total_line_item = $transaction->total_line_item();
947
-            // $transaction_in_progress->line
948
-            if (! $total_line_item instanceof EE_Line_Item) {
949
-                throw new DomainException(
950
-                    esc_html__(
951
-                        'Transaction does not have a valid Total Line Item associated with it.',
952
-                        'event_espresso'
953
-                    )
954
-                );
955
-            }
956
-            $valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
957
-                $total_line_item
958
-            );
959
-        }
960
-        $total_line_items = EEM_Line_Item::instance()->get_total_line_items_for_active_carts();
961
-        foreach ($total_line_items as $total_line_item) {
962
-            $valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
963
-                $total_line_item
964
-            );
965
-        }
966
-        $tickets_with_reservations = EEM_Ticket::instance()->get_tickets_with_reservations();
967
-        return EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
968
-            $tickets_with_reservations,
969
-            $valid_reserved_tickets,
970
-            __FUNCTION__
971
-        );
972
-    }
973
-
974
-
975
-
976
-    /**
977
-     * @param EE_Line_Item $total_line_item
978
-     * @return EE_Line_Item[]
979
-     */
980
-    private static function get_ticket_line_items_for_grand_total(EE_Line_Item $total_line_item)
981
-    {
982
-        /** @var EE_Line_Item[] $valid_reserved_tickets */
983
-        $valid_reserved_tickets = array();
984
-        $ticket_line_items      = EEH_Line_Item::get_ticket_line_items($total_line_item);
985
-        foreach ($ticket_line_items as $ticket_line_item) {
986
-            if ($ticket_line_item instanceof EE_Line_Item) {
987
-                $valid_reserved_tickets[] = $ticket_line_item;
988
-            }
989
-        }
990
-        return $valid_reserved_tickets;
991
-    }
992
-
993
-
994
-
995
-    /**
996
-     * @param EE_Ticket[]    $tickets_with_reservations
997
-     * @param EE_Line_Item[] $valid_reserved_ticket_line_items
998
-     * @return int
999
-     * @throws UnexpectedEntityException
1000
-     * @throws DomainException
1001
-     * @throws EE_Error
1002
-     */
1003
-    private static function release_reservations_for_tickets(
1004
-        array $tickets_with_reservations,
1005
-        array $valid_reserved_ticket_line_items = array(),
1006
-        $source
1007
-    ) {
1008
-        $total_tickets_released = 0;
1009
-        $sold_out_events = array();
1010
-        foreach ($tickets_with_reservations as $ticket_with_reservations) {
1011
-            if (! $ticket_with_reservations instanceof EE_Ticket) {
1012
-                continue;
1013
-            }
1014
-            $reserved_qty = $ticket_with_reservations->reserved();
1015
-            foreach ($valid_reserved_ticket_line_items as $valid_reserved_ticket_line_item) {
1016
-                if (
1017
-                    $valid_reserved_ticket_line_item instanceof EE_Line_Item
1018
-                    && $valid_reserved_ticket_line_item->OBJ_ID() === $ticket_with_reservations->ID()
1019
-                ) {
1020
-                    $reserved_qty -= $valid_reserved_ticket_line_item->quantity();
1021
-                }
1022
-            }
1023
-            if ($reserved_qty > 0) {
1024
-                $ticket_with_reservations->add_extra_meta(
1025
-                    EE_Ticket::META_KEY_TICKET_RESERVATIONS,
1026
-                    __LINE__ . ') ' . $source . '()'
1027
-                );
1028
-                $ticket_with_reservations->decrease_reserved($reserved_qty, true, 'TicketSalesMonitor:'. __LINE__);
1029
-                $ticket_with_reservations->save();
1030
-                $total_tickets_released += $reserved_qty;
1031
-                $event = $ticket_with_reservations->get_related_event();
1032
-                // track sold out events
1033
-                if ($event instanceof EE_Event && $event->is_sold_out()) {
1034
-                    $sold_out_events[] = $event;
1035
-                }
1036
-            }
1037
-        }
1038
-        // double check whether sold out events should remain sold out after releasing tickets
1039
-        if($sold_out_events !== array()){
1040
-            foreach ($sold_out_events as $sold_out_event) {
1041
-                /** @var EE_Event $sold_out_event */
1042
-                $sold_out_event->perform_sold_out_status_check();
1043
-            }
1044
-        }
1045
-        return $total_tickets_released;
1046
-    }
1047
-
1048
-
1049
-
1050
-    /********************************** SHUTDOWN  **********************************/
1051
-
1052
-
1053
-
1054
-    /**
1055
-     * @return false|int
1056
-     * @throws EE_Error
1057
-     * @throws InvalidArgumentException
1058
-     * @throws InvalidDataTypeException
1059
-     * @throws InvalidInterfaceException
1060
-     */
1061
-    public static function clear_expired_line_items_with_no_transaction()
1062
-    {
1063
-        /** @type WPDB $wpdb */
1064
-        global $wpdb;
1065
-        /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
1066
-        $session_lifespan = LoaderFactory::getLoader()->getShared(
1067
-            'EventEspresso\core\domain\values\session\SessionLifespan'
1068
-        );
1069
-        return $wpdb->query(
1070
-            $wpdb->prepare(
1071
-                'DELETE FROM ' . EEM_Line_Item::instance()->table() . '
27
+	const debug = false;    //	true false
28
+
29
+	/**
30
+	 * an array of raw ticket data from EED_Ticket_Selector
31
+	 *
32
+	 * @var array $ticket_selections
33
+	 */
34
+	protected $ticket_selections = array();
35
+
36
+	/**
37
+	 * the raw ticket data from EED_Ticket_Selector is organized in rows
38
+	 * according to how they are displayed in the actual Ticket_Selector
39
+	 * this tracks the current row being processed
40
+	 *
41
+	 * @var int $current_row
42
+	 */
43
+	protected $current_row = 0;
44
+
45
+	/**
46
+	 * an array for tracking names of tickets that have sold out
47
+	 *
48
+	 * @var array $sold_out_tickets
49
+	 */
50
+	protected $sold_out_tickets = array();
51
+
52
+	/**
53
+	 * an array for tracking names of tickets that have had their quantities reduced
54
+	 *
55
+	 * @var array $decremented_tickets
56
+	 */
57
+	protected $decremented_tickets = array();
58
+
59
+
60
+
61
+	/**
62
+	 * set_hooks - for hooking into EE Core, other modules, etc
63
+	 *
64
+	 * @return    void
65
+	 */
66
+	public static function set_hooks()
67
+	{
68
+		// release tickets for expired carts
69
+		add_action(
70
+			'EED_Ticket_Selector__process_ticket_selections__before',
71
+			array('EED_Ticket_Sales_Monitor', 'release_tickets_for_expired_carts'),
72
+			1
73
+		);
74
+		// check ticket reserves AFTER MER does it's check (hence priority 20)
75
+		add_filter(
76
+			'FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty',
77
+			array('EED_Ticket_Sales_Monitor', 'validate_ticket_sale'),
78
+			20,
79
+			3
80
+		);
81
+		// add notices for sold out tickets
82
+		add_action(
83
+			'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
84
+			array('EED_Ticket_Sales_Monitor', 'post_notices'),
85
+			10
86
+		);
87
+		// handle ticket quantities adjusted in cart
88
+		//add_action(
89
+		//	'FHEE__EED_Multi_Event_Registration__adjust_line_item_quantity__line_item_quantity_updated',
90
+		//	array( 'EED_Ticket_Sales_Monitor', 'ticket_quantity_updated' ),
91
+		//	10, 2
92
+		//);
93
+		// handle tickets deleted from cart
94
+		add_action(
95
+			'FHEE__EED_Multi_Event_Registration__delete_ticket__ticket_removed_from_cart',
96
+			array('EED_Ticket_Sales_Monitor', 'ticket_removed_from_cart'),
97
+			10,
98
+			2
99
+		);
100
+		// handle emptied carts
101
+		add_action(
102
+			'AHEE__EE_Session__reset_cart__before_reset',
103
+			array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
104
+			10,
105
+			1
106
+		);
107
+		add_action(
108
+			'AHEE__EED_Multi_Event_Registration__empty_event_cart__before_delete_cart',
109
+			array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
110
+			10,
111
+			1
112
+		);
113
+		// handle cancelled registrations
114
+		add_action(
115
+			'AHEE__EE_Session__reset_checkout__before_reset',
116
+			array('EED_Ticket_Sales_Monitor', 'session_checkout_reset'),
117
+			10,
118
+			1
119
+		);
120
+		// cron tasks
121
+		add_action(
122
+			'AHEE__EE_Cron_Tasks__process_expired_transactions__abandoned_transaction',
123
+			array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
124
+			10,
125
+			1
126
+		);
127
+		add_action(
128
+			'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_transaction',
129
+			array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
130
+			10,
131
+			1
132
+		);
133
+		add_action(
134
+			'AHEE__EE_Cron_Tasks__process_expired_transactions__failed_transaction',
135
+			array('EED_Ticket_Sales_Monitor', 'process_failed_transactions'),
136
+			10,
137
+			1
138
+		);
139
+	}
140
+
141
+
142
+
143
+	/**
144
+	 * set_hooks_admin - for hooking into EE Admin Core, other modules, etc
145
+	 *
146
+	 * @return void
147
+	 */
148
+	public static function set_hooks_admin()
149
+	{
150
+		EED_Ticket_Sales_Monitor::set_hooks();
151
+	}
152
+
153
+
154
+
155
+	/**
156
+	 * @return EED_Ticket_Sales_Monitor|EED_Module
157
+	 */
158
+	public static function instance()
159
+	{
160
+		return parent::get_instance(__CLASS__);
161
+	}
162
+
163
+
164
+
165
+	/**
166
+	 * @param WP_Query $WP_Query
167
+	 * @return    void
168
+	 */
169
+	public function run($WP_Query)
170
+	{
171
+	}
172
+
173
+
174
+
175
+	/********************************** PRE_TICKET_SALES  **********************************/
176
+
177
+
178
+
179
+	/**
180
+	 * Retrieves grand totals from the line items that have no TXN ID
181
+	 * and timestamps less than the current time minus the session lifespan.
182
+	 * These are carts that have been abandoned before the "registrant" even attempted to checkout.
183
+	 * We're going to release the tickets for these line items before attempting to add more to the cart.
184
+	 *
185
+	 * @return void
186
+	 * @throws DomainException
187
+	 * @throws EE_Error
188
+	 * @throws InvalidArgumentException
189
+	 * @throws InvalidDataTypeException
190
+	 * @throws InvalidInterfaceException
191
+	 * @throws UnexpectedEntityException
192
+	 */
193
+	public static function release_tickets_for_expired_carts()
194
+	{
195
+		do_action('AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__begin');
196
+		$expired_ticket_IDs      = array();
197
+		$valid_ticket_line_items = array();
198
+		$total_line_items        = EEM_Line_Item::instance()->get_total_line_items_with_no_transaction();
199
+		if (empty($total_line_items)) {
200
+			do_action(
201
+				'AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__end',
202
+				$total_line_items,
203
+				$valid_ticket_line_items,
204
+				$expired_ticket_IDs
205
+			);
206
+			return;
207
+		}
208
+		/** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
209
+		$session_lifespan = LoaderFactory::getLoader()->getShared(
210
+			'EventEspresso\core\domain\values\session\SessionLifespan'
211
+		);
212
+		foreach ($total_line_items as $total_line_item) {
213
+			/** @var EE_Line_Item $total_line_item */
214
+			$ticket_line_items = EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total($total_line_item);
215
+			foreach ($ticket_line_items as $ticket_line_item) {
216
+				if (! $ticket_line_item instanceof EE_Line_Item) {
217
+					continue;
218
+				}
219
+				if ($total_line_item->timestamp(true) <= $session_lifespan->expiration()) {
220
+					$expired_ticket_IDs[ $ticket_line_item->OBJ_ID() ] = $ticket_line_item->OBJ_ID();
221
+				} else {
222
+					$valid_ticket_line_items[ $ticket_line_item->OBJ_ID() ] = $ticket_line_item;
223
+				}
224
+			}
225
+		}
226
+		if (! empty($expired_ticket_IDs)) {
227
+			EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
228
+				\EEM_Ticket::instance()->get_tickets_with_IDs($expired_ticket_IDs),
229
+				$valid_ticket_line_items,
230
+				__FUNCTION__
231
+			);
232
+			// let's get rid of expired line items so that they can't interfere with tracking
233
+			add_action(
234
+				'shutdown',
235
+				array('EED_Ticket_Sales_Monitor', 'clear_expired_line_items_with_no_transaction'),
236
+				999
237
+			);
238
+		}
239
+		do_action(
240
+			'AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__end',
241
+			$total_line_items,
242
+			$valid_ticket_line_items,
243
+			$expired_ticket_IDs
244
+		);
245
+	}
246
+
247
+
248
+
249
+	/********************************** VALIDATE_TICKET_SALE  **********************************/
250
+
251
+
252
+
253
+	/**
254
+	 * callback for 'FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data'
255
+	 *
256
+	 * @param int       $qty
257
+	 * @param EE_Ticket $ticket
258
+	 * @return bool
259
+	 * @throws UnexpectedEntityException
260
+	 * @throws EE_Error
261
+	 */
262
+	public static function validate_ticket_sale($qty = 1, EE_Ticket $ticket)
263
+	{
264
+		$qty = absint($qty);
265
+		if ($qty > 0) {
266
+			$qty = EED_Ticket_Sales_Monitor::instance()->_validate_ticket_sale($ticket, $qty);
267
+		}
268
+		if (self::debug) {
269
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '()';
270
+			echo '<br /><br /><b> RETURNED QTY: ' . $qty . '</b>';
271
+		}
272
+		return $qty;
273
+	}
274
+
275
+
276
+
277
+	/**
278
+	 * checks whether an individual ticket is available for purchase based on datetime, and ticket details
279
+	 *
280
+	 * @param   EE_Ticket $ticket
281
+	 * @param int         $qty
282
+	 * @return int
283
+	 * @throws UnexpectedEntityException
284
+	 * @throws EE_Error
285
+	 */
286
+	protected function _validate_ticket_sale(EE_Ticket $ticket, $qty = 1)
287
+	{
288
+		if (self::debug) {
289
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
290
+		}
291
+		if (! $ticket instanceof EE_Ticket) {
292
+			return 0;
293
+		}
294
+		if (self::debug) {
295
+			echo '<br /><b> . ticket->ID: ' . $ticket->ID() . '</b>';
296
+			echo '<br /> . original ticket->reserved: ' . $ticket->reserved();
297
+		}
298
+		$ticket->refresh_from_db();
299
+		// first let's determine the ticket availability based on sales
300
+		$available = $ticket->qty('saleable');
301
+		if (self::debug) {
302
+			echo '<br /> . . . ticket->qty: ' . $ticket->qty();
303
+			echo '<br /> . . . ticket->sold: ' . $ticket->sold();
304
+			echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
305
+			echo '<br /> . . . ticket->qty(saleable): ' . $ticket->qty('saleable');
306
+			echo '<br /> . . . available: ' . $available;
307
+		}
308
+		if ($available < 1) {
309
+			$this->_ticket_sold_out($ticket);
310
+			return 0;
311
+		}
312
+		if (self::debug) {
313
+			echo '<br /> . . . qty: ' . $qty;
314
+		}
315
+		if ($available < $qty) {
316
+			$qty = $available;
317
+			if (self::debug) {
318
+				echo '<br /> . . . QTY ADJUSTED: ' . $qty;
319
+			}
320
+			$this->_ticket_quantity_decremented($ticket);
321
+		}
322
+		$this->_reserve_ticket($ticket, $qty);
323
+		return $qty;
324
+	}
325
+
326
+
327
+
328
+	/**
329
+	 * increments ticket reserved based on quantity passed
330
+	 *
331
+	 * @param    EE_Ticket $ticket
332
+	 * @param int          $quantity
333
+	 * @return bool
334
+	 * @throws EE_Error
335
+	 */
336
+	protected function _reserve_ticket(EE_Ticket $ticket, $quantity = 1)
337
+	{
338
+		if (self::debug) {
339
+			echo '<br /><br /> . . . INCREASE RESERVED: ' . $quantity;
340
+		}
341
+		$ticket->increase_reserved($quantity, 'TicketSalesMonitor:'. __LINE__);
342
+		return $ticket->save();
343
+	}
344
+
345
+
346
+
347
+	/**
348
+	 * @param  EE_Ticket $ticket
349
+	 * @param  int       $quantity
350
+	 * @return bool
351
+	 * @throws EE_Error
352
+	 */
353
+	protected function _release_reserved_ticket(EE_Ticket $ticket, $quantity = 1)
354
+	{
355
+		if (self::debug) {
356
+			echo '<br /> . . . ticket->ID: ' . $ticket->ID();
357
+			echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
358
+		}
359
+		$ticket->decrease_reserved($quantity, true, 'TicketSalesMonitor:'. __LINE__);
360
+		if (self::debug) {
361
+			echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
362
+		}
363
+		return $ticket->save() ? 1 : 0;
364
+	}
365
+
366
+
367
+
368
+	/**
369
+	 * removes quantities within the ticket selector based on zero ticket availability
370
+	 *
371
+	 * @param    EE_Ticket $ticket
372
+	 * @return    void
373
+	 * @throws UnexpectedEntityException
374
+	 * @throws EE_Error
375
+	 */
376
+	protected function _ticket_sold_out(EE_Ticket $ticket)
377
+	{
378
+		if (self::debug) {
379
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
380
+			echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
381
+		}
382
+		$this->sold_out_tickets[] = $this->_get_ticket_and_event_name($ticket);
383
+	}
384
+
385
+
386
+
387
+	/**
388
+	 * adjusts quantities within the ticket selector based on decreased ticket availability
389
+	 *
390
+	 * @param    EE_Ticket $ticket
391
+	 * @return void
392
+	 * @throws UnexpectedEntityException
393
+	 * @throws EE_Error
394
+	 */
395
+	protected function _ticket_quantity_decremented(EE_Ticket $ticket)
396
+	{
397
+		if (self::debug) {
398
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
399
+			echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
400
+		}
401
+		$this->decremented_tickets[] = $this->_get_ticket_and_event_name($ticket);
402
+	}
403
+
404
+
405
+
406
+	/**
407
+	 * builds string out of ticket and event name
408
+	 *
409
+	 * @param    EE_Ticket $ticket
410
+	 * @return string
411
+	 * @throws UnexpectedEntityException
412
+	 * @throws EE_Error
413
+	 */
414
+	protected function _get_ticket_and_event_name(EE_Ticket $ticket)
415
+	{
416
+		$event = $ticket->get_related_event();
417
+		if ($event instanceof EE_Event) {
418
+			$ticket_name = sprintf(
419
+				_x('%1$s for %2$s', 'ticket name for event name', 'event_espresso'),
420
+				$ticket->name(),
421
+				$event->name()
422
+			);
423
+		} else {
424
+			$ticket_name = $ticket->name();
425
+		}
426
+		return $ticket_name;
427
+	}
428
+
429
+
430
+
431
+	/********************************** EVENT CART  **********************************/
432
+
433
+
434
+
435
+	/**
436
+	 * releases or reserves ticket(s) based on quantity passed
437
+	 *
438
+	 * @param  EE_Line_Item $line_item
439
+	 * @param  int          $quantity
440
+	 * @return void
441
+	 * @throws EE_Error
442
+	 * @throws InvalidArgumentException
443
+	 * @throws InvalidDataTypeException
444
+	 * @throws InvalidInterfaceException
445
+	 */
446
+	public static function ticket_quantity_updated(EE_Line_Item $line_item, $quantity = 1)
447
+	{
448
+		$ticket = EEM_Ticket::instance()->get_one_by_ID(absint($line_item->OBJ_ID()));
449
+		if ($ticket instanceof EE_Ticket) {
450
+			$ticket->add_extra_meta(
451
+				EE_Ticket::META_KEY_TICKET_RESERVATIONS,
452
+				__LINE__ . ') ' . __METHOD__ . '()'
453
+			);
454
+			if ($quantity > 0) {
455
+				EED_Ticket_Sales_Monitor::instance()->_reserve_ticket($ticket, $quantity);
456
+			} else {
457
+				EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
458
+			}
459
+		}
460
+	}
461
+
462
+
463
+
464
+	/**
465
+	 * releases reserved ticket(s) based on quantity passed
466
+	 *
467
+	 * @param  EE_Ticket $ticket
468
+	 * @param  int       $quantity
469
+	 * @return void
470
+	 * @throws EE_Error
471
+	 */
472
+	public static function ticket_removed_from_cart(EE_Ticket $ticket, $quantity = 1)
473
+	{
474
+		$ticket->add_extra_meta(
475
+			EE_Ticket::META_KEY_TICKET_RESERVATIONS,
476
+			__LINE__ . ') ' . __METHOD__ . '()'
477
+		);
478
+		EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
479
+	}
480
+
481
+
482
+
483
+	/********************************** POST_NOTICES  **********************************/
484
+
485
+
486
+
487
+	/**
488
+	 * @return void
489
+	 * @throws EE_Error
490
+	 * @throws InvalidArgumentException
491
+	 * @throws ReflectionException
492
+	 * @throws InvalidDataTypeException
493
+	 * @throws InvalidInterfaceException
494
+	 */
495
+	public static function post_notices()
496
+	{
497
+		EED_Ticket_Sales_Monitor::instance()->_post_notices();
498
+	}
499
+
500
+
501
+
502
+	/**
503
+	 * @return void
504
+	 * @throws EE_Error
505
+	 * @throws InvalidArgumentException
506
+	 * @throws ReflectionException
507
+	 * @throws InvalidDataTypeException
508
+	 * @throws InvalidInterfaceException
509
+	 */
510
+	protected function _post_notices()
511
+	{
512
+		if (self::debug) {
513
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
514
+		}
515
+		$refresh_msg    = '';
516
+		$none_added_msg = '';
517
+		if (defined('DOING_AJAX') && DOING_AJAX) {
518
+			$refresh_msg    = __(
519
+				'Please refresh the page to view updated ticket quantities.',
520
+				'event_espresso'
521
+			);
522
+			$none_added_msg = __('No tickets were added for the event.', 'event_espresso');
523
+		}
524
+		if (! empty($this->sold_out_tickets)) {
525
+			EE_Error::add_attention(
526
+				sprintf(
527
+					apply_filters(
528
+						'FHEE__EED_Ticket_Sales_Monitor___post_notices__sold_out_tickets_notice',
529
+						__(
530
+							'We\'re sorry...%1$sThe following items have sold out since you first viewed this page, and can no longer be registered for:%1$s%1$s%2$s%1$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%1$s%1$s%3$s%1$s%4$s%1$s',
531
+							'event_espresso'
532
+						)
533
+					),
534
+					'<br />',
535
+					implode('<br />', $this->sold_out_tickets),
536
+					$none_added_msg,
537
+					$refresh_msg
538
+				)
539
+			);
540
+			// alter code flow in the Ticket Selector for better UX
541
+			add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', '__return_true');
542
+			add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__success', '__return_false');
543
+			$this->sold_out_tickets = array();
544
+			// and reset the cart
545
+			EED_Ticket_Sales_Monitor::session_cart_reset(EE_Registry::instance()->SSN);
546
+		}
547
+		if (! empty($this->decremented_tickets)) {
548
+			EE_Error::add_attention(
549
+				sprintf(
550
+					apply_filters(
551
+						'FHEE__EED_Ticket_Sales_Monitor___ticket_quantity_decremented__notice',
552
+						__(
553
+							'We\'re sorry...%1$sDue to sales that have occurred since you first viewed the last page, the following items have had their quantities adjusted to match the current available amount:%1$s%1$s%2$s%1$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%1$s%1$s%3$s%1$s%4$s%1$s',
554
+							'event_espresso'
555
+						)
556
+					),
557
+					'<br />',
558
+					implode('<br />', $this->decremented_tickets),
559
+					$none_added_msg,
560
+					$refresh_msg
561
+				)
562
+			);
563
+			$this->decremented_tickets = array();
564
+		}
565
+	}
566
+
567
+
568
+
569
+	/********************************** RELEASE_ALL_RESERVED_TICKETS_FOR_TRANSACTION  **********************************/
570
+
571
+
572
+
573
+	/**
574
+	 * releases reserved tickets for all registrations of an EE_Transaction
575
+	 * by default, will NOT release tickets for finalized transactions
576
+	 *
577
+	 * @param    EE_Transaction $transaction
578
+	 * @return int
579
+	 * @throws EE_Error
580
+	 * @throws InvalidSessionDataException
581
+	 */
582
+	protected function _release_all_reserved_tickets_for_transaction(EE_Transaction $transaction)
583
+	{
584
+		if (self::debug) {
585
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
586
+			echo '<br /> . transaction->ID: ' . $transaction->ID();
587
+			echo '<br /> . TXN status_ID: ' . $transaction->status_ID();
588
+		}
589
+		// check if 'finalize_registration' step has been completed...
590
+		$finalized = $transaction->reg_step_completed('finalize_registration');
591
+		if (self::debug) {
592
+			// DEBUG LOG
593
+			EEH_Debug_Tools::log(
594
+				__CLASS__,
595
+				__FUNCTION__,
596
+				__LINE__,
597
+				array('finalized' => $finalized),
598
+				false,
599
+				'EE_Transaction: ' . $transaction->ID()
600
+			);
601
+		}
602
+		// how many tickets were released
603
+		$count = 0;
604
+		if (self::debug) {
605
+			echo '<br /> . . . TXN finalized: ' . $finalized;
606
+		}
607
+		$release_tickets_with_TXN_status = array(
608
+			EEM_Transaction::failed_status_code,
609
+			EEM_Transaction::abandoned_status_code,
610
+			EEM_Transaction::incomplete_status_code,
611
+		);
612
+		$events = array();
613
+		// if the session is getting cleared BEFORE the TXN has been finalized or the transaction is not completed
614
+		if (! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
615
+			// cancel any reserved tickets for registrations that were not approved
616
+			$registrations = $transaction->registrations();
617
+			if (self::debug) {
618
+				echo '<br /> . . . # registrations: ' . count($registrations);
619
+				$reg    = reset($registrations);
620
+				$ticket = $reg->ticket();
621
+				if ($ticket instanceof EE_Ticket) {
622
+					$ticket->add_extra_meta(
623
+						EE_Ticket::META_KEY_TICKET_RESERVATIONS,
624
+						__LINE__ . ') Release All Tickets TXN:' . $transaction->ID()
625
+					);
626
+				}
627
+			}
628
+			if (! empty($registrations)) {
629
+				foreach ($registrations as $registration) {
630
+					if (
631
+						$registration instanceof EE_Registration
632
+						&& $this->_release_reserved_ticket_for_registration($registration, $transaction)
633
+					) {
634
+						$count++;
635
+						$events[ $registration->event_ID() ] = $registration->event();
636
+					}
637
+				}
638
+			}
639
+		}
640
+		if ($events !== array()) {
641
+			foreach ($events as $event) {
642
+				/** @var EE_Event $event */
643
+				$event->perform_sold_out_status_check();
644
+			}
645
+		}
646
+		return $count;
647
+	}
648
+
649
+
650
+
651
+	/**
652
+	 * releases reserved tickets for an EE_Registration
653
+	 * by default, will NOT release tickets for APPROVED registrations
654
+	 *
655
+	 * @param EE_Registration $registration
656
+	 * @param EE_Transaction  $transaction
657
+	 * @return int
658
+	 * @throws EE_Error
659
+	 */
660
+	protected function _release_reserved_ticket_for_registration(
661
+		EE_Registration $registration,
662
+		EE_Transaction $transaction
663
+	) {
664
+		$STS_ID = $transaction->status_ID();
665
+		if (self::debug) {
666
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
667
+			echo '<br /> . . registration->ID: ' . $registration->ID();
668
+			echo '<br /> . . registration->status_ID: ' . $registration->status_ID();
669
+			echo '<br /> . . transaction->status_ID(): ' . $STS_ID;
670
+		}
671
+		if (
672
+			// release Tickets for Failed Transactions and Abandoned Transactions
673
+			$STS_ID === EEM_Transaction::failed_status_code
674
+			|| $STS_ID === EEM_Transaction::abandoned_status_code
675
+			|| (
676
+				// also release Tickets for Incomplete Transactions, but ONLY if the Registrations are NOT Approved
677
+				$STS_ID === EEM_Transaction::incomplete_status_code
678
+				&& $registration->status_ID() !== EEM_Registration::status_id_approved
679
+			)
680
+		) {
681
+			if (self::debug) {
682
+				echo '<br /><br /> . . RELEASE RESERVED TICKET';
683
+				$rsrvd = $registration->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true);
684
+				echo '<br /> . . . registration HAS_RESERVED_TICKET_KEY: ';
685
+				var_dump($rsrvd);
686
+			}
687
+			$registration->release_reserved_ticket(true, 'TicketSalesMonitor:'. __LINE__);
688
+			return 1;
689
+		}
690
+		return 0;
691
+	}
692
+
693
+
694
+
695
+	/********************************** SESSION_CART_RESET  **********************************/
696
+
697
+
698
+
699
+	/**
700
+	 * callback hooked into 'AHEE__EE_Session__reset_cart__before_reset'
701
+	 *
702
+	 * @param EE_Session $session
703
+	 * @return void
704
+	 * @throws EE_Error
705
+	 * @throws InvalidArgumentException
706
+	 * @throws ReflectionException
707
+	 * @throws InvalidDataTypeException
708
+	 * @throws InvalidInterfaceException
709
+	 */
710
+	public static function session_cart_reset(EE_Session $session)
711
+	{
712
+		if (self::debug) {
713
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
714
+		}
715
+		// first check of the session has a valid Checkout object
716
+		$checkout = $session->checkout();
717
+		if ($checkout instanceof EE_Checkout) {
718
+			// and use that to clear ticket reservations because it will update the associated registration meta data
719
+			EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
720
+			return;
721
+		}
722
+		$cart = $session->cart();
723
+		if ($cart instanceof EE_Cart) {
724
+			if (self::debug) {
725
+				echo '<br /><br /> cart instance of EE_Cart: ';
726
+			}
727
+			EED_Ticket_Sales_Monitor::instance()->_session_cart_reset($cart, $session);
728
+		} else {
729
+			if (self::debug) {
730
+				echo '<br /><br /> invalid EE_Cart: ';
731
+				var_export($cart, true);
732
+			}
733
+		}
734
+	}
735
+
736
+
737
+
738
+	/**
739
+	 * releases reserved tickets in the EE_Cart
740
+	 *
741
+	 * @param EE_Cart $cart
742
+	 * @return void
743
+	 * @throws EE_Error
744
+	 * @throws InvalidArgumentException
745
+	 * @throws ReflectionException
746
+	 * @throws InvalidDataTypeException
747
+	 * @throws InvalidInterfaceException
748
+	 */
749
+	protected function _session_cart_reset(EE_Cart $cart, EE_Session $session)
750
+	{
751
+		if (self::debug) {
752
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
753
+		}
754
+		EE_Registry::instance()->load_helper('Line_Item');
755
+		$ticket_line_items = $cart->get_tickets();
756
+		if (empty($ticket_line_items)) {
757
+			return;
758
+		}
759
+		foreach ($ticket_line_items as $ticket_line_item) {
760
+			if (self::debug) {
761
+				echo '<br /> . ticket_line_item->ID(): ' . $ticket_line_item->ID();
762
+			}
763
+			if ($ticket_line_item instanceof EE_Line_Item && $ticket_line_item->OBJ_type() === 'Ticket') {
764
+				if (self::debug) {
765
+					echo '<br /> . . ticket_line_item->OBJ_ID(): ' . $ticket_line_item->OBJ_ID();
766
+				}
767
+				$ticket = EEM_Ticket::instance()->get_one_by_ID($ticket_line_item->OBJ_ID());
768
+				if ($ticket instanceof EE_Ticket) {
769
+					if (self::debug) {
770
+						echo '<br /> . . ticket->ID(): ' . $ticket->ID();
771
+						echo '<br /> . . ticket_line_item->quantity(): ' . $ticket_line_item->quantity();
772
+					}
773
+					$ticket->add_extra_meta(
774
+						EE_Ticket::META_KEY_TICKET_RESERVATIONS,
775
+						__LINE__ . ') ' . __METHOD__ . '() SID = ' . $session->id()
776
+					);
777
+					$this->_release_reserved_ticket($ticket, $ticket_line_item->quantity());
778
+				}
779
+			}
780
+		}
781
+		if (self::debug) {
782
+			echo '<br /><br /> RESET COMPLETED ';
783
+		}
784
+	}
785
+
786
+
787
+
788
+	/********************************** SESSION_CHECKOUT_RESET  **********************************/
789
+
790
+
791
+
792
+	/**
793
+	 * callback hooked into 'AHEE__EE_Session__reset_checkout__before_reset'
794
+	 *
795
+	 * @param EE_Session $session
796
+	 * @return void
797
+	 * @throws EE_Error
798
+	 * @throws InvalidSessionDataException
799
+	 */
800
+	public static function session_checkout_reset(EE_Session $session)
801
+	{
802
+		$checkout = $session->checkout();
803
+		if ($checkout instanceof EE_Checkout) {
804
+			EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
805
+		}
806
+	}
807
+
808
+
809
+
810
+	/**
811
+	 * releases reserved tickets for the EE_Checkout->transaction
812
+	 *
813
+	 * @param EE_Checkout $checkout
814
+	 * @return void
815
+	 * @throws EE_Error
816
+	 * @throws InvalidSessionDataException
817
+	 */
818
+	protected function _session_checkout_reset(EE_Checkout $checkout)
819
+	{
820
+		if (self::debug) {
821
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
822
+		}
823
+		// we want to release the each registration's reserved tickets if the session was cleared, but not if this is a revisit
824
+		if ($checkout->revisit || ! $checkout->transaction instanceof EE_Transaction) {
825
+			return;
826
+		}
827
+		$this->_release_all_reserved_tickets_for_transaction($checkout->transaction);
828
+	}
829
+
830
+
831
+
832
+	/********************************** SESSION_EXPIRED_RESET  **********************************/
833
+
834
+
835
+
836
+	/**
837
+	 * @param    EE_Session $session
838
+	 * @return    void
839
+	 */
840
+	public static function session_expired_reset(EE_Session $session)
841
+	{
842
+	}
843
+
844
+
845
+
846
+	/********************************** PROCESS_ABANDONED_TRANSACTIONS  **********************************/
847
+
848
+
849
+
850
+	/**
851
+	 * releases reserved tickets for all registrations of an ABANDONED EE_Transaction
852
+	 * by default, will NOT release tickets for free transactions, or any that have received a payment
853
+	 *
854
+	 * @param EE_Transaction $transaction
855
+	 * @return void
856
+	 * @throws EE_Error
857
+	 * @throws InvalidSessionDataException
858
+	 */
859
+	public static function process_abandoned_transactions(EE_Transaction $transaction)
860
+	{
861
+		// is this TXN free or has any money been paid towards this TXN? If so, then leave it alone
862
+		if ($transaction->is_free() || $transaction->paid() > 0) {
863
+			if (self::debug) {
864
+				// DEBUG LOG
865
+				EEH_Debug_Tools::log(
866
+					__CLASS__,
867
+					__FUNCTION__,
868
+					__LINE__,
869
+					array($transaction),
870
+					false,
871
+					'EE_Transaction: ' . $transaction->ID()
872
+				);
873
+			}
874
+			return;
875
+		}
876
+		// have their been any successful payments made ?
877
+		$payments = $transaction->payments();
878
+		foreach ($payments as $payment) {
879
+			if ($payment instanceof EE_Payment && $payment->status() === EEM_Payment::status_id_approved) {
880
+				if (self::debug) {
881
+					// DEBUG LOG
882
+					EEH_Debug_Tools::log(
883
+						__CLASS__,
884
+						__FUNCTION__,
885
+						__LINE__,
886
+						array($payment),
887
+						false,
888
+						'EE_Transaction: ' . $transaction->ID()
889
+					);
890
+				}
891
+				return;
892
+			}
893
+		}
894
+		// since you haven't even attempted to pay for your ticket...
895
+		EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
896
+	}
897
+
898
+
899
+
900
+	/********************************** PROCESS_FAILED_TRANSACTIONS  **********************************/
901
+
902
+
903
+
904
+	/**
905
+	 * releases reserved tickets for absolutely ALL registrations of a FAILED EE_Transaction
906
+	 *
907
+	 * @param EE_Transaction $transaction
908
+	 * @return void
909
+	 * @throws EE_Error
910
+	 * @throws InvalidSessionDataException
911
+	 */
912
+	public static function process_failed_transactions(EE_Transaction $transaction)
913
+	{
914
+		// since you haven't even attempted to pay for your ticket...
915
+		EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
916
+	}
917
+
918
+
919
+
920
+	/********************************** RESET RESERVATION COUNTS  *********************************/
921
+
922
+
923
+
924
+	/**
925
+	 * Resets all ticket and datetime reserved counts to zero
926
+	 * Tickets that are currently associated with a Transaction that is in progress
927
+	 *
928
+	 * @throws EE_Error
929
+	 * @throws DomainException
930
+	 * @throws InvalidDataTypeException
931
+	 * @throws InvalidInterfaceException
932
+	 * @throws InvalidArgumentException
933
+	 * @throws UnexpectedEntityException
934
+	 */
935
+	public static function reset_reservation_counts()
936
+	{
937
+		/** @var EE_Line_Item[] $valid_reserved_tickets */
938
+		$valid_reserved_tickets = array();
939
+		/** @var EE_Transaction[] $transactions_not_in_progress */
940
+		$transactions_not_in_progress = EEM_Transaction::instance()->get_transactions_not_in_progress();
941
+		foreach ($transactions_not_in_progress as $transaction) {
942
+			// if this TXN has been fully completed, then skip it
943
+			if ($transaction->reg_step_completed('finalize_registration')) {
944
+				continue;
945
+			}
946
+			$total_line_item = $transaction->total_line_item();
947
+			// $transaction_in_progress->line
948
+			if (! $total_line_item instanceof EE_Line_Item) {
949
+				throw new DomainException(
950
+					esc_html__(
951
+						'Transaction does not have a valid Total Line Item associated with it.',
952
+						'event_espresso'
953
+					)
954
+				);
955
+			}
956
+			$valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
957
+				$total_line_item
958
+			);
959
+		}
960
+		$total_line_items = EEM_Line_Item::instance()->get_total_line_items_for_active_carts();
961
+		foreach ($total_line_items as $total_line_item) {
962
+			$valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
963
+				$total_line_item
964
+			);
965
+		}
966
+		$tickets_with_reservations = EEM_Ticket::instance()->get_tickets_with_reservations();
967
+		return EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
968
+			$tickets_with_reservations,
969
+			$valid_reserved_tickets,
970
+			__FUNCTION__
971
+		);
972
+	}
973
+
974
+
975
+
976
+	/**
977
+	 * @param EE_Line_Item $total_line_item
978
+	 * @return EE_Line_Item[]
979
+	 */
980
+	private static function get_ticket_line_items_for_grand_total(EE_Line_Item $total_line_item)
981
+	{
982
+		/** @var EE_Line_Item[] $valid_reserved_tickets */
983
+		$valid_reserved_tickets = array();
984
+		$ticket_line_items      = EEH_Line_Item::get_ticket_line_items($total_line_item);
985
+		foreach ($ticket_line_items as $ticket_line_item) {
986
+			if ($ticket_line_item instanceof EE_Line_Item) {
987
+				$valid_reserved_tickets[] = $ticket_line_item;
988
+			}
989
+		}
990
+		return $valid_reserved_tickets;
991
+	}
992
+
993
+
994
+
995
+	/**
996
+	 * @param EE_Ticket[]    $tickets_with_reservations
997
+	 * @param EE_Line_Item[] $valid_reserved_ticket_line_items
998
+	 * @return int
999
+	 * @throws UnexpectedEntityException
1000
+	 * @throws DomainException
1001
+	 * @throws EE_Error
1002
+	 */
1003
+	private static function release_reservations_for_tickets(
1004
+		array $tickets_with_reservations,
1005
+		array $valid_reserved_ticket_line_items = array(),
1006
+		$source
1007
+	) {
1008
+		$total_tickets_released = 0;
1009
+		$sold_out_events = array();
1010
+		foreach ($tickets_with_reservations as $ticket_with_reservations) {
1011
+			if (! $ticket_with_reservations instanceof EE_Ticket) {
1012
+				continue;
1013
+			}
1014
+			$reserved_qty = $ticket_with_reservations->reserved();
1015
+			foreach ($valid_reserved_ticket_line_items as $valid_reserved_ticket_line_item) {
1016
+				if (
1017
+					$valid_reserved_ticket_line_item instanceof EE_Line_Item
1018
+					&& $valid_reserved_ticket_line_item->OBJ_ID() === $ticket_with_reservations->ID()
1019
+				) {
1020
+					$reserved_qty -= $valid_reserved_ticket_line_item->quantity();
1021
+				}
1022
+			}
1023
+			if ($reserved_qty > 0) {
1024
+				$ticket_with_reservations->add_extra_meta(
1025
+					EE_Ticket::META_KEY_TICKET_RESERVATIONS,
1026
+					__LINE__ . ') ' . $source . '()'
1027
+				);
1028
+				$ticket_with_reservations->decrease_reserved($reserved_qty, true, 'TicketSalesMonitor:'. __LINE__);
1029
+				$ticket_with_reservations->save();
1030
+				$total_tickets_released += $reserved_qty;
1031
+				$event = $ticket_with_reservations->get_related_event();
1032
+				// track sold out events
1033
+				if ($event instanceof EE_Event && $event->is_sold_out()) {
1034
+					$sold_out_events[] = $event;
1035
+				}
1036
+			}
1037
+		}
1038
+		// double check whether sold out events should remain sold out after releasing tickets
1039
+		if($sold_out_events !== array()){
1040
+			foreach ($sold_out_events as $sold_out_event) {
1041
+				/** @var EE_Event $sold_out_event */
1042
+				$sold_out_event->perform_sold_out_status_check();
1043
+			}
1044
+		}
1045
+		return $total_tickets_released;
1046
+	}
1047
+
1048
+
1049
+
1050
+	/********************************** SHUTDOWN  **********************************/
1051
+
1052
+
1053
+
1054
+	/**
1055
+	 * @return false|int
1056
+	 * @throws EE_Error
1057
+	 * @throws InvalidArgumentException
1058
+	 * @throws InvalidDataTypeException
1059
+	 * @throws InvalidInterfaceException
1060
+	 */
1061
+	public static function clear_expired_line_items_with_no_transaction()
1062
+	{
1063
+		/** @type WPDB $wpdb */
1064
+		global $wpdb;
1065
+		/** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
1066
+		$session_lifespan = LoaderFactory::getLoader()->getShared(
1067
+			'EventEspresso\core\domain\values\session\SessionLifespan'
1068
+		);
1069
+		return $wpdb->query(
1070
+			$wpdb->prepare(
1071
+				'DELETE FROM ' . EEM_Line_Item::instance()->table() . '
1072 1072
                 WHERE TXN_ID = 0 AND LIN_timestamp <= %s',
1073
-                // use GMT time because that's what LIN_timestamps are in
1074
-                date('Y-m-d H:i:s', $session_lifespan->expiration())
1075
-            )
1076
-        );
1077
-    }
1073
+				// use GMT time because that's what LIN_timestamps are in
1074
+				date('Y-m-d H:i:s', $session_lifespan->expiration())
1075
+			)
1076
+		);
1077
+	}
1078 1078
 
1079 1079
 }
1080 1080
 // End of file EED_Ticket_Sales_Monitor.module.php
Please login to merge, or discard this patch.
Spacing   +65 added lines, -65 removed lines patch added patch discarded remove patch
@@ -24,7 +24,7 @@  discard block
 block discarded – undo
24 24
 class EED_Ticket_Sales_Monitor extends EED_Module
25 25
 {
26 26
 
27
-    const debug = false;    //	true false
27
+    const debug = false; //	true false
28 28
 
29 29
     /**
30 30
      * an array of raw ticket data from EED_Ticket_Selector
@@ -213,17 +213,17 @@  discard block
 block discarded – undo
213 213
             /** @var EE_Line_Item $total_line_item */
214 214
             $ticket_line_items = EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total($total_line_item);
215 215
             foreach ($ticket_line_items as $ticket_line_item) {
216
-                if (! $ticket_line_item instanceof EE_Line_Item) {
216
+                if ( ! $ticket_line_item instanceof EE_Line_Item) {
217 217
                     continue;
218 218
                 }
219 219
                 if ($total_line_item->timestamp(true) <= $session_lifespan->expiration()) {
220
-                    $expired_ticket_IDs[ $ticket_line_item->OBJ_ID() ] = $ticket_line_item->OBJ_ID();
220
+                    $expired_ticket_IDs[$ticket_line_item->OBJ_ID()] = $ticket_line_item->OBJ_ID();
221 221
                 } else {
222
-                    $valid_ticket_line_items[ $ticket_line_item->OBJ_ID() ] = $ticket_line_item;
222
+                    $valid_ticket_line_items[$ticket_line_item->OBJ_ID()] = $ticket_line_item;
223 223
                 }
224 224
             }
225 225
         }
226
-        if (! empty($expired_ticket_IDs)) {
226
+        if ( ! empty($expired_ticket_IDs)) {
227 227
             EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
228 228
                 \EEM_Ticket::instance()->get_tickets_with_IDs($expired_ticket_IDs),
229 229
                 $valid_ticket_line_items,
@@ -266,8 +266,8 @@  discard block
 block discarded – undo
266 266
             $qty = EED_Ticket_Sales_Monitor::instance()->_validate_ticket_sale($ticket, $qty);
267 267
         }
268 268
         if (self::debug) {
269
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '()';
270
-            echo '<br /><br /><b> RETURNED QTY: ' . $qty . '</b>';
269
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'()';
270
+            echo '<br /><br /><b> RETURNED QTY: '.$qty.'</b>';
271 271
         }
272 272
         return $qty;
273 273
     }
@@ -286,36 +286,36 @@  discard block
 block discarded – undo
286 286
     protected function _validate_ticket_sale(EE_Ticket $ticket, $qty = 1)
287 287
     {
288 288
         if (self::debug) {
289
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
289
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
290 290
         }
291
-        if (! $ticket instanceof EE_Ticket) {
291
+        if ( ! $ticket instanceof EE_Ticket) {
292 292
             return 0;
293 293
         }
294 294
         if (self::debug) {
295
-            echo '<br /><b> . ticket->ID: ' . $ticket->ID() . '</b>';
296
-            echo '<br /> . original ticket->reserved: ' . $ticket->reserved();
295
+            echo '<br /><b> . ticket->ID: '.$ticket->ID().'</b>';
296
+            echo '<br /> . original ticket->reserved: '.$ticket->reserved();
297 297
         }
298 298
         $ticket->refresh_from_db();
299 299
         // first let's determine the ticket availability based on sales
300 300
         $available = $ticket->qty('saleable');
301 301
         if (self::debug) {
302
-            echo '<br /> . . . ticket->qty: ' . $ticket->qty();
303
-            echo '<br /> . . . ticket->sold: ' . $ticket->sold();
304
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
305
-            echo '<br /> . . . ticket->qty(saleable): ' . $ticket->qty('saleable');
306
-            echo '<br /> . . . available: ' . $available;
302
+            echo '<br /> . . . ticket->qty: '.$ticket->qty();
303
+            echo '<br /> . . . ticket->sold: '.$ticket->sold();
304
+            echo '<br /> . . . ticket->reserved: '.$ticket->reserved();
305
+            echo '<br /> . . . ticket->qty(saleable): '.$ticket->qty('saleable');
306
+            echo '<br /> . . . available: '.$available;
307 307
         }
308 308
         if ($available < 1) {
309 309
             $this->_ticket_sold_out($ticket);
310 310
             return 0;
311 311
         }
312 312
         if (self::debug) {
313
-            echo '<br /> . . . qty: ' . $qty;
313
+            echo '<br /> . . . qty: '.$qty;
314 314
         }
315 315
         if ($available < $qty) {
316 316
             $qty = $available;
317 317
             if (self::debug) {
318
-                echo '<br /> . . . QTY ADJUSTED: ' . $qty;
318
+                echo '<br /> . . . QTY ADJUSTED: '.$qty;
319 319
             }
320 320
             $this->_ticket_quantity_decremented($ticket);
321 321
         }
@@ -336,9 +336,9 @@  discard block
 block discarded – undo
336 336
     protected function _reserve_ticket(EE_Ticket $ticket, $quantity = 1)
337 337
     {
338 338
         if (self::debug) {
339
-            echo '<br /><br /> . . . INCREASE RESERVED: ' . $quantity;
339
+            echo '<br /><br /> . . . INCREASE RESERVED: '.$quantity;
340 340
         }
341
-        $ticket->increase_reserved($quantity, 'TicketSalesMonitor:'. __LINE__);
341
+        $ticket->increase_reserved($quantity, 'TicketSalesMonitor:'.__LINE__);
342 342
         return $ticket->save();
343 343
     }
344 344
 
@@ -353,12 +353,12 @@  discard block
 block discarded – undo
353 353
     protected function _release_reserved_ticket(EE_Ticket $ticket, $quantity = 1)
354 354
     {
355 355
         if (self::debug) {
356
-            echo '<br /> . . . ticket->ID: ' . $ticket->ID();
357
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
356
+            echo '<br /> . . . ticket->ID: '.$ticket->ID();
357
+            echo '<br /> . . . ticket->reserved: '.$ticket->reserved();
358 358
         }
359
-        $ticket->decrease_reserved($quantity, true, 'TicketSalesMonitor:'. __LINE__);
359
+        $ticket->decrease_reserved($quantity, true, 'TicketSalesMonitor:'.__LINE__);
360 360
         if (self::debug) {
361
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
361
+            echo '<br /> . . . ticket->reserved: '.$ticket->reserved();
362 362
         }
363 363
         return $ticket->save() ? 1 : 0;
364 364
     }
@@ -376,8 +376,8 @@  discard block
 block discarded – undo
376 376
     protected function _ticket_sold_out(EE_Ticket $ticket)
377 377
     {
378 378
         if (self::debug) {
379
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
380
-            echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
379
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
380
+            echo '<br /> . . ticket->name: '.$this->_get_ticket_and_event_name($ticket);
381 381
         }
382 382
         $this->sold_out_tickets[] = $this->_get_ticket_and_event_name($ticket);
383 383
     }
@@ -395,8 +395,8 @@  discard block
 block discarded – undo
395 395
     protected function _ticket_quantity_decremented(EE_Ticket $ticket)
396 396
     {
397 397
         if (self::debug) {
398
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
399
-            echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
398
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
399
+            echo '<br /> . . ticket->name: '.$this->_get_ticket_and_event_name($ticket);
400 400
         }
401 401
         $this->decremented_tickets[] = $this->_get_ticket_and_event_name($ticket);
402 402
     }
@@ -449,7 +449,7 @@  discard block
 block discarded – undo
449 449
         if ($ticket instanceof EE_Ticket) {
450 450
             $ticket->add_extra_meta(
451 451
                 EE_Ticket::META_KEY_TICKET_RESERVATIONS,
452
-                __LINE__ . ') ' . __METHOD__ . '()'
452
+                __LINE__.') '.__METHOD__.'()'
453 453
             );
454 454
             if ($quantity > 0) {
455 455
                 EED_Ticket_Sales_Monitor::instance()->_reserve_ticket($ticket, $quantity);
@@ -473,7 +473,7 @@  discard block
 block discarded – undo
473 473
     {
474 474
         $ticket->add_extra_meta(
475 475
             EE_Ticket::META_KEY_TICKET_RESERVATIONS,
476
-            __LINE__ . ') ' . __METHOD__ . '()'
476
+            __LINE__.') '.__METHOD__.'()'
477 477
         );
478 478
         EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
479 479
     }
@@ -510,18 +510,18 @@  discard block
 block discarded – undo
510 510
     protected function _post_notices()
511 511
     {
512 512
         if (self::debug) {
513
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
513
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
514 514
         }
515 515
         $refresh_msg    = '';
516 516
         $none_added_msg = '';
517 517
         if (defined('DOING_AJAX') && DOING_AJAX) {
518
-            $refresh_msg    = __(
518
+            $refresh_msg = __(
519 519
                 'Please refresh the page to view updated ticket quantities.',
520 520
                 'event_espresso'
521 521
             );
522 522
             $none_added_msg = __('No tickets were added for the event.', 'event_espresso');
523 523
         }
524
-        if (! empty($this->sold_out_tickets)) {
524
+        if ( ! empty($this->sold_out_tickets)) {
525 525
             EE_Error::add_attention(
526 526
                 sprintf(
527 527
                     apply_filters(
@@ -544,7 +544,7 @@  discard block
 block discarded – undo
544 544
             // and reset the cart
545 545
             EED_Ticket_Sales_Monitor::session_cart_reset(EE_Registry::instance()->SSN);
546 546
         }
547
-        if (! empty($this->decremented_tickets)) {
547
+        if ( ! empty($this->decremented_tickets)) {
548 548
             EE_Error::add_attention(
549 549
                 sprintf(
550 550
                     apply_filters(
@@ -582,9 +582,9 @@  discard block
 block discarded – undo
582 582
     protected function _release_all_reserved_tickets_for_transaction(EE_Transaction $transaction)
583 583
     {
584 584
         if (self::debug) {
585
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
586
-            echo '<br /> . transaction->ID: ' . $transaction->ID();
587
-            echo '<br /> . TXN status_ID: ' . $transaction->status_ID();
585
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
586
+            echo '<br /> . transaction->ID: '.$transaction->ID();
587
+            echo '<br /> . TXN status_ID: '.$transaction->status_ID();
588 588
         }
589 589
         // check if 'finalize_registration' step has been completed...
590 590
         $finalized = $transaction->reg_step_completed('finalize_registration');
@@ -596,13 +596,13 @@  discard block
 block discarded – undo
596 596
                 __LINE__,
597 597
                 array('finalized' => $finalized),
598 598
                 false,
599
-                'EE_Transaction: ' . $transaction->ID()
599
+                'EE_Transaction: '.$transaction->ID()
600 600
             );
601 601
         }
602 602
         // how many tickets were released
603 603
         $count = 0;
604 604
         if (self::debug) {
605
-            echo '<br /> . . . TXN finalized: ' . $finalized;
605
+            echo '<br /> . . . TXN finalized: '.$finalized;
606 606
         }
607 607
         $release_tickets_with_TXN_status = array(
608 608
             EEM_Transaction::failed_status_code,
@@ -611,28 +611,28 @@  discard block
 block discarded – undo
611 611
         );
612 612
         $events = array();
613 613
         // if the session is getting cleared BEFORE the TXN has been finalized or the transaction is not completed
614
-        if (! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
614
+        if ( ! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
615 615
             // cancel any reserved tickets for registrations that were not approved
616 616
             $registrations = $transaction->registrations();
617 617
             if (self::debug) {
618
-                echo '<br /> . . . # registrations: ' . count($registrations);
618
+                echo '<br /> . . . # registrations: '.count($registrations);
619 619
                 $reg    = reset($registrations);
620 620
                 $ticket = $reg->ticket();
621 621
                 if ($ticket instanceof EE_Ticket) {
622 622
                     $ticket->add_extra_meta(
623 623
                         EE_Ticket::META_KEY_TICKET_RESERVATIONS,
624
-                        __LINE__ . ') Release All Tickets TXN:' . $transaction->ID()
624
+                        __LINE__.') Release All Tickets TXN:'.$transaction->ID()
625 625
                     );
626 626
                 }
627 627
             }
628
-            if (! empty($registrations)) {
628
+            if ( ! empty($registrations)) {
629 629
                 foreach ($registrations as $registration) {
630 630
                     if (
631 631
                         $registration instanceof EE_Registration
632 632
                         && $this->_release_reserved_ticket_for_registration($registration, $transaction)
633 633
                     ) {
634 634
                         $count++;
635
-                        $events[ $registration->event_ID() ] = $registration->event();
635
+                        $events[$registration->event_ID()] = $registration->event();
636 636
                     }
637 637
                 }
638 638
             }
@@ -663,10 +663,10 @@  discard block
 block discarded – undo
663 663
     ) {
664 664
         $STS_ID = $transaction->status_ID();
665 665
         if (self::debug) {
666
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
667
-            echo '<br /> . . registration->ID: ' . $registration->ID();
668
-            echo '<br /> . . registration->status_ID: ' . $registration->status_ID();
669
-            echo '<br /> . . transaction->status_ID(): ' . $STS_ID;
666
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
667
+            echo '<br /> . . registration->ID: '.$registration->ID();
668
+            echo '<br /> . . registration->status_ID: '.$registration->status_ID();
669
+            echo '<br /> . . transaction->status_ID(): '.$STS_ID;
670 670
         }
671 671
         if (
672 672
             // release Tickets for Failed Transactions and Abandoned Transactions
@@ -684,7 +684,7 @@  discard block
 block discarded – undo
684 684
                 echo '<br /> . . . registration HAS_RESERVED_TICKET_KEY: ';
685 685
                 var_dump($rsrvd);
686 686
             }
687
-            $registration->release_reserved_ticket(true, 'TicketSalesMonitor:'. __LINE__);
687
+            $registration->release_reserved_ticket(true, 'TicketSalesMonitor:'.__LINE__);
688 688
             return 1;
689 689
         }
690 690
         return 0;
@@ -710,7 +710,7 @@  discard block
 block discarded – undo
710 710
     public static function session_cart_reset(EE_Session $session)
711 711
     {
712 712
         if (self::debug) {
713
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
713
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
714 714
         }
715 715
         // first check of the session has a valid Checkout object
716 716
         $checkout = $session->checkout();
@@ -749,7 +749,7 @@  discard block
 block discarded – undo
749 749
     protected function _session_cart_reset(EE_Cart $cart, EE_Session $session)
750 750
     {
751 751
         if (self::debug) {
752
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
752
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
753 753
         }
754 754
         EE_Registry::instance()->load_helper('Line_Item');
755 755
         $ticket_line_items = $cart->get_tickets();
@@ -758,21 +758,21 @@  discard block
 block discarded – undo
758 758
         }
759 759
         foreach ($ticket_line_items as $ticket_line_item) {
760 760
             if (self::debug) {
761
-                echo '<br /> . ticket_line_item->ID(): ' . $ticket_line_item->ID();
761
+                echo '<br /> . ticket_line_item->ID(): '.$ticket_line_item->ID();
762 762
             }
763 763
             if ($ticket_line_item instanceof EE_Line_Item && $ticket_line_item->OBJ_type() === 'Ticket') {
764 764
                 if (self::debug) {
765
-                    echo '<br /> . . ticket_line_item->OBJ_ID(): ' . $ticket_line_item->OBJ_ID();
765
+                    echo '<br /> . . ticket_line_item->OBJ_ID(): '.$ticket_line_item->OBJ_ID();
766 766
                 }
767 767
                 $ticket = EEM_Ticket::instance()->get_one_by_ID($ticket_line_item->OBJ_ID());
768 768
                 if ($ticket instanceof EE_Ticket) {
769 769
                     if (self::debug) {
770
-                        echo '<br /> . . ticket->ID(): ' . $ticket->ID();
771
-                        echo '<br /> . . ticket_line_item->quantity(): ' . $ticket_line_item->quantity();
770
+                        echo '<br /> . . ticket->ID(): '.$ticket->ID();
771
+                        echo '<br /> . . ticket_line_item->quantity(): '.$ticket_line_item->quantity();
772 772
                     }
773 773
                     $ticket->add_extra_meta(
774 774
                         EE_Ticket::META_KEY_TICKET_RESERVATIONS,
775
-                        __LINE__ . ') ' . __METHOD__ . '() SID = ' . $session->id()
775
+                        __LINE__.') '.__METHOD__.'() SID = '.$session->id()
776 776
                     );
777 777
                     $this->_release_reserved_ticket($ticket, $ticket_line_item->quantity());
778 778
                 }
@@ -818,7 +818,7 @@  discard block
 block discarded – undo
818 818
     protected function _session_checkout_reset(EE_Checkout $checkout)
819 819
     {
820 820
         if (self::debug) {
821
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
821
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
822 822
         }
823 823
         // we want to release the each registration's reserved tickets if the session was cleared, but not if this is a revisit
824 824
         if ($checkout->revisit || ! $checkout->transaction instanceof EE_Transaction) {
@@ -868,7 +868,7 @@  discard block
 block discarded – undo
868 868
                     __LINE__,
869 869
                     array($transaction),
870 870
                     false,
871
-                    'EE_Transaction: ' . $transaction->ID()
871
+                    'EE_Transaction: '.$transaction->ID()
872 872
                 );
873 873
             }
874 874
             return;
@@ -885,7 +885,7 @@  discard block
 block discarded – undo
885 885
                         __LINE__,
886 886
                         array($payment),
887 887
                         false,
888
-                        'EE_Transaction: ' . $transaction->ID()
888
+                        'EE_Transaction: '.$transaction->ID()
889 889
                     );
890 890
                 }
891 891
                 return;
@@ -945,7 +945,7 @@  discard block
 block discarded – undo
945 945
             }
946 946
             $total_line_item = $transaction->total_line_item();
947 947
             // $transaction_in_progress->line
948
-            if (! $total_line_item instanceof EE_Line_Item) {
948
+            if ( ! $total_line_item instanceof EE_Line_Item) {
949 949
                 throw new DomainException(
950 950
                     esc_html__(
951 951
                         'Transaction does not have a valid Total Line Item associated with it.',
@@ -1008,7 +1008,7 @@  discard block
 block discarded – undo
1008 1008
         $total_tickets_released = 0;
1009 1009
         $sold_out_events = array();
1010 1010
         foreach ($tickets_with_reservations as $ticket_with_reservations) {
1011
-            if (! $ticket_with_reservations instanceof EE_Ticket) {
1011
+            if ( ! $ticket_with_reservations instanceof EE_Ticket) {
1012 1012
                 continue;
1013 1013
             }
1014 1014
             $reserved_qty = $ticket_with_reservations->reserved();
@@ -1023,9 +1023,9 @@  discard block
 block discarded – undo
1023 1023
             if ($reserved_qty > 0) {
1024 1024
                 $ticket_with_reservations->add_extra_meta(
1025 1025
                     EE_Ticket::META_KEY_TICKET_RESERVATIONS,
1026
-                    __LINE__ . ') ' . $source . '()'
1026
+                    __LINE__.') '.$source.'()'
1027 1027
                 );
1028
-                $ticket_with_reservations->decrease_reserved($reserved_qty, true, 'TicketSalesMonitor:'. __LINE__);
1028
+                $ticket_with_reservations->decrease_reserved($reserved_qty, true, 'TicketSalesMonitor:'.__LINE__);
1029 1029
                 $ticket_with_reservations->save();
1030 1030
                 $total_tickets_released += $reserved_qty;
1031 1031
                 $event = $ticket_with_reservations->get_related_event();
@@ -1036,7 +1036,7 @@  discard block
 block discarded – undo
1036 1036
             }
1037 1037
         }
1038 1038
         // double check whether sold out events should remain sold out after releasing tickets
1039
-        if($sold_out_events !== array()){
1039
+        if ($sold_out_events !== array()) {
1040 1040
             foreach ($sold_out_events as $sold_out_event) {
1041 1041
                 /** @var EE_Event $sold_out_event */
1042 1042
                 $sold_out_event->perform_sold_out_status_check();
@@ -1068,7 +1068,7 @@  discard block
 block discarded – undo
1068 1068
         );
1069 1069
         return $wpdb->query(
1070 1070
             $wpdb->prepare(
1071
-                'DELETE FROM ' . EEM_Line_Item::instance()->table() . '
1071
+                'DELETE FROM '.EEM_Line_Item::instance()->table().'
1072 1072
                 WHERE TXN_ID = 0 AND LIN_timestamp <= %s',
1073 1073
                 // use GMT time because that's what LIN_timestamps are in
1074 1074
                 date('Y-m-d H:i:s', $session_lifespan->expiration())
Please login to merge, or discard this patch.
admin_pages/transactions/EE_Admin_Transactions_List_Table.class.php 1 patch
Indentation   +630 added lines, -630 removed lines patch added patch discarded remove patch
@@ -17,121 +17,121 @@  discard block
 block discarded – undo
17 17
 class EE_Admin_Transactions_List_Table extends EE_Admin_List_Table
18 18
 {
19 19
 
20
-    /**
21
-     * @var SessionLifespan $session_lifespan
22
-     */
23
-    private $session_lifespan;
24
-
25
-    private $_status;
26
-
27
-
28
-    /**
29
-     * @param \Transactions_Admin_Page $admin_page
30
-     * @param SessionLifespan          $lifespan
31
-     */
32
-    public function __construct(\Transactions_Admin_Page $admin_page, SessionLifespan $lifespan)
33
-    {
34
-        parent::__construct($admin_page);
35
-        $this->session_lifespan = $lifespan;
36
-        $this->_status = $this->_admin_page->get_transaction_status_array();
37
-    }
38
-
39
-
40
-    /**
41
-     *_setup_data
42
-     */
43
-    protected function _setup_data()
44
-    {
45
-        $this->_data           = $this->_admin_page->get_transactions($this->_per_page);
46
-        $status                = ! empty($this->_req_data['status']) ? $this->_req_data['status'] : 'all';
47
-        $this->_all_data_count = $this->_admin_page->get_transactions($this->_per_page, true, $status);
48
-    }
49
-
50
-
51
-    /**
52
-     *_set_properties
53
-     */
54
-    protected function _set_properties()
55
-    {
56
-        $this->_wp_list_args = array(
57
-            'singular' => __('transaction', 'event_espresso'),
58
-            'plural'   => __('transactions', 'event_espresso'),
59
-            'ajax'     => true,
60
-            'screen'   => $this->_admin_page->get_current_screen()->id,
61
-        );
62
-        $ID_column_name      = __('ID', 'event_espresso');
63
-        $ID_column_name      .= ' : <span class="show-on-mobile-view-only" style="float:none">';
64
-        $ID_column_name      .= __('Transaction Date', 'event_espresso');
65
-        $ID_column_name      .= '</span> ';
66
-        $this->_columns      = array(
67
-            'TXN_ID'        => $ID_column_name,
68
-            'TXN_timestamp' => __('Transaction Date', 'event_espresso'),
69
-            'TXN_total'     => __('Total', 'event_espresso'),
70
-            'TXN_paid'      => __('Paid', 'event_espresso'),
71
-            'ATT_fname'     => __('Primary Registrant', 'event_espresso'),
72
-            'event_name'    => __('Event', 'event_espresso'),
73
-            'actions'       => __('Actions', 'event_espresso'),
74
-        );
75
-
76
-        $this->_sortable_columns = array(
77
-            'TXN_ID'        => array('TXN_ID' => false),
78
-            'event_name'    => array('event_name' => false),
79
-            'ATT_fname'     => array('ATT_fname' => false),
80
-            'TXN_timestamp' => array('TXN_timestamp' => true) //true means its already sorted
81
-        );
82
-
83
-        $this->_primary_column = 'TXN_ID';
84
-
85
-        $this->_hidden_columns = array();
86
-    }
87
-
88
-
89
-    /**
90
-     * This simply sets up the row class for the table rows.
91
-     * Allows for easier overriding of child methods for setting up sorting.
92
-     *
93
-     * @param  EE_Transaction $transaction the current item
94
-     * @return string
95
-     * @throws \EE_Error
96
-     */
97
-    protected function _get_row_class($transaction)
98
-    {
99
-        $class = parent::_get_row_class($transaction);
100
-        //add status class
101
-        $class .= ' ee-status-strip txn-status-' . $transaction->status_ID();
102
-        if ($this->_has_checkbox_column) {
103
-            $class .= ' has-checkbox-column';
104
-        }
105
-        return $class;
106
-    }
107
-
108
-
109
-    /**
110
-     * _get_table_filters
111
-     * We use this to assemble and return any filters that are associated with this table that help further refine what
112
-     * get's shown in the table.
113
-     *
114
-     * @abstract
115
-     * @access protected
116
-     * @return array
117
-     */
118
-    protected function _get_table_filters()
119
-    {
120
-        $filters    = array();
121
-        $start_date = isset($this->_req_data['txn-filter-start-date'])
122
-            ? wp_strip_all_tags($this->_req_data['txn-filter-start-date'])
123
-            : date(
124
-                'm/d/Y',
125
-                strtotime('-10 year')
126
-            );
127
-        $end_date   = isset($this->_req_data['txn-filter-end-date'])
128
-            ? wp_strip_all_tags($this->_req_data['txn-filter-end-date'])
129
-            : date(
130
-                'm/d/Y',
131
-                current_time('timestamp')
132
-            );
133
-        ob_start();
134
-        ?>
20
+	/**
21
+	 * @var SessionLifespan $session_lifespan
22
+	 */
23
+	private $session_lifespan;
24
+
25
+	private $_status;
26
+
27
+
28
+	/**
29
+	 * @param \Transactions_Admin_Page $admin_page
30
+	 * @param SessionLifespan          $lifespan
31
+	 */
32
+	public function __construct(\Transactions_Admin_Page $admin_page, SessionLifespan $lifespan)
33
+	{
34
+		parent::__construct($admin_page);
35
+		$this->session_lifespan = $lifespan;
36
+		$this->_status = $this->_admin_page->get_transaction_status_array();
37
+	}
38
+
39
+
40
+	/**
41
+	 *_setup_data
42
+	 */
43
+	protected function _setup_data()
44
+	{
45
+		$this->_data           = $this->_admin_page->get_transactions($this->_per_page);
46
+		$status                = ! empty($this->_req_data['status']) ? $this->_req_data['status'] : 'all';
47
+		$this->_all_data_count = $this->_admin_page->get_transactions($this->_per_page, true, $status);
48
+	}
49
+
50
+
51
+	/**
52
+	 *_set_properties
53
+	 */
54
+	protected function _set_properties()
55
+	{
56
+		$this->_wp_list_args = array(
57
+			'singular' => __('transaction', 'event_espresso'),
58
+			'plural'   => __('transactions', 'event_espresso'),
59
+			'ajax'     => true,
60
+			'screen'   => $this->_admin_page->get_current_screen()->id,
61
+		);
62
+		$ID_column_name      = __('ID', 'event_espresso');
63
+		$ID_column_name      .= ' : <span class="show-on-mobile-view-only" style="float:none">';
64
+		$ID_column_name      .= __('Transaction Date', 'event_espresso');
65
+		$ID_column_name      .= '</span> ';
66
+		$this->_columns      = array(
67
+			'TXN_ID'        => $ID_column_name,
68
+			'TXN_timestamp' => __('Transaction Date', 'event_espresso'),
69
+			'TXN_total'     => __('Total', 'event_espresso'),
70
+			'TXN_paid'      => __('Paid', 'event_espresso'),
71
+			'ATT_fname'     => __('Primary Registrant', 'event_espresso'),
72
+			'event_name'    => __('Event', 'event_espresso'),
73
+			'actions'       => __('Actions', 'event_espresso'),
74
+		);
75
+
76
+		$this->_sortable_columns = array(
77
+			'TXN_ID'        => array('TXN_ID' => false),
78
+			'event_name'    => array('event_name' => false),
79
+			'ATT_fname'     => array('ATT_fname' => false),
80
+			'TXN_timestamp' => array('TXN_timestamp' => true) //true means its already sorted
81
+		);
82
+
83
+		$this->_primary_column = 'TXN_ID';
84
+
85
+		$this->_hidden_columns = array();
86
+	}
87
+
88
+
89
+	/**
90
+	 * This simply sets up the row class for the table rows.
91
+	 * Allows for easier overriding of child methods for setting up sorting.
92
+	 *
93
+	 * @param  EE_Transaction $transaction the current item
94
+	 * @return string
95
+	 * @throws \EE_Error
96
+	 */
97
+	protected function _get_row_class($transaction)
98
+	{
99
+		$class = parent::_get_row_class($transaction);
100
+		//add status class
101
+		$class .= ' ee-status-strip txn-status-' . $transaction->status_ID();
102
+		if ($this->_has_checkbox_column) {
103
+			$class .= ' has-checkbox-column';
104
+		}
105
+		return $class;
106
+	}
107
+
108
+
109
+	/**
110
+	 * _get_table_filters
111
+	 * We use this to assemble and return any filters that are associated with this table that help further refine what
112
+	 * get's shown in the table.
113
+	 *
114
+	 * @abstract
115
+	 * @access protected
116
+	 * @return array
117
+	 */
118
+	protected function _get_table_filters()
119
+	{
120
+		$filters    = array();
121
+		$start_date = isset($this->_req_data['txn-filter-start-date'])
122
+			? wp_strip_all_tags($this->_req_data['txn-filter-start-date'])
123
+			: date(
124
+				'm/d/Y',
125
+				strtotime('-10 year')
126
+			);
127
+		$end_date   = isset($this->_req_data['txn-filter-end-date'])
128
+			? wp_strip_all_tags($this->_req_data['txn-filter-end-date'])
129
+			: date(
130
+				'm/d/Y',
131
+				current_time('timestamp')
132
+			);
133
+		ob_start();
134
+		?>
135 135
         <label for="txn-filter-start-date">Display Transactions from </label>
136 136
         <input id="txn-filter-start-date" class="datepicker" type="text" value="<?php echo $start_date; ?>"
137 137
                name="txn-filter-start-date" size="15"/>
@@ -139,551 +139,551 @@  discard block
 block discarded – undo
139 139
         <input id="txn-filter-end-date" class="datepicker" type="text" value="<?php echo $end_date; ?>"
140 140
                name="txn-filter-end-date" size="15"/>
141 141
         <?php
142
-        $filters[] = ob_get_contents();
143
-        ob_end_clean();
144
-        return $filters;
145
-    }
146
-
147
-
148
-    /**
149
-     *_add_view_counts
150
-     */
151
-    protected function _add_view_counts()
152
-    {
153
-        $this->_views['all']['count']       = $this->_admin_page->get_transactions($this->_per_page, true, 'all');
154
-        $this->_views['abandoned']['count'] = $this->_admin_page->get_transactions($this->_per_page, true, 'abandoned');
155
-        $this->_views['failed']['count']    = $this->_admin_page->get_transactions($this->_per_page, true, 'failed');
156
-    }
157
-
158
-
159
-    /**
160
-     *    column TXN_ID
161
-     *
162
-     * @param \EE_Transaction $transaction
163
-     * @return string
164
-     * @throws \EE_Error
165
-     */
166
-    public function column_TXN_ID(EE_Transaction $transaction)
167
-    {
168
-        $view_lnk_url = EE_Admin_Page::add_query_args_and_nonce(array(
169
-            'action' => 'view_transaction',
170
-            'TXN_ID' => $transaction->ID(),
171
-        ), TXN_ADMIN_URL);
172
-        $content      = '<a href="' . $view_lnk_url . '"'
173
-                        . ' title="' . esc_attr__('Go to Transaction Details', 'event_espresso') . '">'
174
-                        . $transaction->ID()
175
-                        . '</a>';
176
-
177
-        //txn timestamp
178
-        $content .= '  <span class="show-on-mobile-view-only">' . $this->_get_txn_timestamp($transaction) . '</span>';
179
-        return $content;
180
-    }
181
-
182
-
183
-    /**
184
-     * @param \EE_Transaction $transaction
185
-     * @return string
186
-     * @throws EE_Error
187
-     * @throws InvalidArgumentException
188
-     * @throws InvalidDataTypeException
189
-     * @throws InvalidInterfaceException
190
-     */
191
-    protected function _get_txn_timestamp(EE_Transaction $transaction)
192
-    {
193
-        // is TXN less than 2 hours old ?
194
-        if (($transaction->failed() || $transaction->is_abandoned())
195
-            && $this->session_lifespan->expiration() < $transaction->datetime(false, true)
196
-        ) {
197
-            $timestamp = esc_html__('TXN in progress...', 'event_espresso');
198
-        } else {
199
-            $timestamp = $transaction->get_i18n_datetime('TXN_timestamp');
200
-        }
201
-        return $timestamp;
202
-    }
203
-
204
-
205
-    /**
206
-     *    column_cb
207
-     *
208
-     * @param \EE_Transaction $transaction
209
-     * @return string
210
-     * @throws \EE_Error
211
-     */
212
-    public function column_cb($transaction)
213
-    {
214
-        return sprintf(
215
-            '<input type="checkbox" name="%1$s[]" value="%2$s" />',
216
-            $this->_wp_list_args['singular'],
217
-            $transaction->ID()
218
-        );
219
-    }
220
-
221
-
222
-    /**
223
-     *    column_TXN_timestamp
224
-     *
225
-     * @param \EE_Transaction $transaction
226
-     * @return string
227
-     * @throws \EE_Error
228
-     */
229
-    public function column_TXN_timestamp(EE_Transaction $transaction)
230
-    {
231
-        $view_lnk_url = EE_Admin_Page::add_query_args_and_nonce(array(
232
-            'action' => 'view_transaction',
233
-            'TXN_ID' => $transaction->ID(),
234
-        ), TXN_ADMIN_URL);
235
-        $txn_date     = '<a href="' . $view_lnk_url . '"'
236
-                        . ' title="'
237
-                        . esc_attr__('View Transaction Details for TXN #', 'event_espresso') . $transaction->ID() . '">'
238
-                        . $this->_get_txn_timestamp($transaction)
239
-                        . '</a>';
240
-        //status
241
-        $txn_date .= '<br><span class="ee-status-text-small">'
242
-                     . EEH_Template::pretty_status(
243
-                         $transaction->status_ID(),
244
-                         false,
245
-                         'sentence'
246
-                     )
247
-                     . '</span>';
248
-        return $txn_date;
249
-    }
250
-
251
-
252
-    /**
253
-     *    column_TXN_total
254
-     *
255
-     * @param \EE_Transaction $transaction
256
-     * @return string
257
-     * @throws \EE_Error
258
-     */
259
-    public function column_TXN_total(EE_Transaction $transaction)
260
-    {
261
-        if ($transaction->get('TXN_total') > 0) {
262
-            return '<span class="txn-pad-rght">'
263
-                   . apply_filters(
264
-                       'FHEE__EE_Admin_Transactions_List_Table__column_TXN_total__TXN_total',
265
-                       $transaction->get_pretty('TXN_total'),
266
-                       $transaction
267
-                   )
268
-                   . '</span>';
269
-        } else {
270
-            return '<span class="txn-overview-free-event-spn">' . esc_html__('free', 'event_espresso') . '</span>';
271
-        }
272
-    }
273
-
274
-
275
-    /**
276
-     *    column_TXN_paid
277
-     *
278
-     * @param \EE_Transaction $transaction
279
-     * @return mixed|string
280
-     * @throws \EE_Error
281
-     */
282
-    public function column_TXN_paid(EE_Transaction $transaction)
283
-    {
284
-        $transaction_total = $transaction->get('TXN_total');
285
-        $transaction_paid  = $transaction->get('TXN_paid');
286
-
287
-        if (\EEH_Money::compare_floats($transaction_total, 0, '>')) {
288
-            // monies owing
289
-            $span_class = 'txn-overview-part-payment-spn';
290
-            if (\EEH_Money::compare_floats($transaction_paid, $transaction_total, '>=')) {
291
-                // paid in full
292
-                $span_class = 'txn-overview-full-payment-spn';
293
-            } elseif (\EEH_Money::compare_floats($transaction_paid, 0, '==')) {
294
-                // no payments made
295
-                $span_class = 'txn-overview-no-payment-spn';
296
-            }
297
-        } else {
298
-            $span_class       = 'txn-overview-free-event-spn';
299
-            $transaction_paid = 0;
300
-        }
301
-
302
-        $payment_method      = $transaction->payment_method();
303
-        $payment_method_name = $payment_method instanceof EE_Payment_Method
304
-            ? $payment_method->admin_name()
305
-            : esc_html__('Unknown', 'event_espresso');
306
-        $transaction_paid_content = $transaction_paid !== 0 ? $transaction->get_pretty('TXN_paid') : $transaction_paid;
307
-
308
-        $content = '<span class="' . $span_class . ' txn-pad-rght">'
309
-                   . $transaction_paid_content
310
-                   . '</span>';
311
-        if ($transaction_paid > 0) {
312
-            $content .= '<br><span class="ee-status-text-small">'
313
-                        . sprintf(
314
-                            esc_html__('...via %s', 'event_espresso'),
315
-                            $payment_method_name
316
-                        )
317
-                        . '</span>';
318
-        }
319
-        return $content;
320
-    }
321
-
322
-
323
-    /**
324
-     *    column_ATT_fname
325
-     *
326
-     * @param \EE_Transaction $transaction
327
-     * @return string
328
-     * @throws EE_Error
329
-     * @throws InvalidArgumentException
330
-     * @throws InvalidDataTypeException
331
-     * @throws InvalidInterfaceException
332
-     */
333
-    public function column_ATT_fname(EE_Transaction $transaction)
334
-    {
335
-        $primary_reg = $transaction->primary_registration();
336
-        $attendee    = $primary_reg->get_first_related('Attendee');
337
-        if ($attendee instanceof EE_Attendee) {
338
-            $edit_lnk_url = EE_Admin_Page::add_query_args_and_nonce(array(
339
-                'action'  => 'view_registration',
340
-                '_REG_ID' => $primary_reg->ID(),
341
-            ), REG_ADMIN_URL);
342
-            $content      = EE_Registry::instance()->CAP->current_user_can(
343
-                'ee_read_registration',
344
-                'espresso_registrations_view_registration',
345
-                $primary_reg->ID()
346
-            )
347
-                ? '<a href="' . $edit_lnk_url . '"'
348
-                    . ' title="' . esc_attr__('View Registration Details', 'event_espresso') . '">'
349
-                    . $attendee->full_name()
350
-                    . '</a>'
351
-                : $attendee->full_name();
352
-            $content      .= '<br>' . $attendee->email();
353
-            return $content;
354
-        }
355
-        return $transaction->failed() || $transaction->is_abandoned()
356
-            ? esc_html__('no contact record.', 'event_espresso')
357
-            : esc_html__(
358
-                'No contact record, because the transaction was abandoned or the registration process failed.',
359
-                'event_espresso'
360
-            );
361
-    }
362
-
363
-
364
-    /**
365
-     *    column_ATT_email
366
-     *
367
-     * @param \EE_Transaction $transaction
368
-     * @return string
369
-     * @throws \EE_Error
370
-     */
371
-    public function column_ATT_email(EE_Transaction $transaction)
372
-    {
373
-        $attendee = $transaction->primary_registration()->get_first_related('Attendee');
374
-        if (! empty($attendee)) {
375
-            return '<a href="mailto:' . $attendee->get('ATT_email') . '">'
376
-                   . $attendee->get('ATT_email')
377
-                   . '</a>';
378
-        } else {
379
-            return $transaction->failed() || $transaction->is_abandoned()
380
-                ? esc_html__('no contact record.', 'event_espresso')
381
-                : esc_html__(
382
-                    'No contact record, because the transaction was abandoned or the registration process failed.',
383
-                    'event_espresso'
384
-                );
385
-        }
386
-    }
387
-
388
-
389
-    /**
390
-     *    column_event_name
391
-     *
392
-     * @param \EE_Transaction $transaction
393
-     * @return string
394
-     * @throws EE_Error
395
-     * @throws InvalidArgumentException
396
-     * @throws InvalidDataTypeException
397
-     * @throws InvalidInterfaceException
398
-     */
399
-    public function column_event_name(EE_Transaction $transaction)
400
-    {
401
-        $actions = array();
402
-        $event   = $transaction->primary_registration()->get_first_related('Event');
403
-        if (! empty($event)) {
404
-            $edit_event_url = EE_Admin_Page::add_query_args_and_nonce(
405
-                array('action' => 'edit', 'post' => $event->ID()),
406
-                EVENTS_ADMIN_URL
407
-            );
408
-            $event_name     = $event->get('EVT_name');
409
-
410
-            //filter this view by transactions for this event
411
-            $txn_by_event_lnk = EE_Admin_Page::add_query_args_and_nonce(array(
412
-                'action' => 'default',
413
-                'EVT_ID' => $event->ID(),
414
-            ));
415
-            if (empty($this->_req_data['EVT_ID'])
416
-                && EE_Registry::instance()->CAP->current_user_can(
417
-                    'ee_edit_event',
418
-                    'espresso_events_edit',
419
-                    $event->ID()
420
-                )
421
-            ) {
422
-                $actions['filter_by_event'] = '<a href="' . $txn_by_event_lnk . '"'
423
-                        . ' title="' . esc_attr__('Filter transactions by this event', 'event_espresso') . '">'
424
-                        . esc_html__('View Transactions for this event', 'event_espresso')
425
-                        . '</a>';
426
-            }
427
-
428
-            return sprintf(
429
-                '%1$s %2$s',
430
-                EE_Registry::instance()->CAP->current_user_can(
431
-                    'ee_edit_event',
432
-                    'espresso_events_edit',
433
-                    $event->ID()
434
-                )
435
-                    ? '<a href="' . $edit_event_url . '"'
436
-                        . ' title="'
437
-                        . sprintf(
438
-                            esc_attr__('Edit Event: %s', 'event_espresso'),
439
-                            $event->get('EVT_name')
440
-                        )
441
-                        . '">'
442
-                        . wp_trim_words(
443
-                            $event_name,
444
-                            30,
445
-                            '...'
446
-                        )
447
-                        . '</a>'
448
-                        : wp_trim_words($event_name, 30, '...'),
449
-                $this->row_actions($actions)
450
-            );
451
-        } else {
452
-            return esc_html__(
453
-                'The event associated with this transaction via the primary registration cannot be retrieved.',
454
-                'event_espresso'
455
-            );
456
-        }
457
-    }
458
-
459
-
460
-    /**
461
-     *    column_actions
462
-     *
463
-     * @param \EE_Transaction $transaction
464
-     * @return string
465
-     * @throws \EE_Error
466
-     */
467
-    public function column_actions(EE_Transaction $transaction)
468
-    {
469
-        return $this->_action_string(
470
-            $this->get_transaction_details_link($transaction)
471
-            . $this->get_invoice_link($transaction)
472
-            . $this->get_receipt_link($transaction)
473
-            . $this->get_primary_registration_details_link($transaction)
474
-            . $this->get_send_payment_reminder_trigger_link($transaction)
475
-            . $this->get_payment_overview_link($transaction)
476
-            . $this->get_related_messages_link($transaction),
477
-            $transaction,
478
-            'ul',
479
-            'txn-overview-actions-ul'
480
-        );
481
-    }
482
-
483
-
484
-    /**
485
-     * Get the transaction details link.
486
-     * @param EE_Transaction $transaction
487
-     * @return string
488
-     * @throws EE_Error
489
-     */
490
-    protected function get_transaction_details_link(EE_Transaction $transaction)
491
-    {
492
-        $url          = EE_Admin_Page::add_query_args_and_nonce(array(
493
-            'action' => 'view_transaction',
494
-            'TXN_ID' => $transaction->ID(),
495
-        ), TXN_ADMIN_URL);
496
-        return '
142
+		$filters[] = ob_get_contents();
143
+		ob_end_clean();
144
+		return $filters;
145
+	}
146
+
147
+
148
+	/**
149
+	 *_add_view_counts
150
+	 */
151
+	protected function _add_view_counts()
152
+	{
153
+		$this->_views['all']['count']       = $this->_admin_page->get_transactions($this->_per_page, true, 'all');
154
+		$this->_views['abandoned']['count'] = $this->_admin_page->get_transactions($this->_per_page, true, 'abandoned');
155
+		$this->_views['failed']['count']    = $this->_admin_page->get_transactions($this->_per_page, true, 'failed');
156
+	}
157
+
158
+
159
+	/**
160
+	 *    column TXN_ID
161
+	 *
162
+	 * @param \EE_Transaction $transaction
163
+	 * @return string
164
+	 * @throws \EE_Error
165
+	 */
166
+	public function column_TXN_ID(EE_Transaction $transaction)
167
+	{
168
+		$view_lnk_url = EE_Admin_Page::add_query_args_and_nonce(array(
169
+			'action' => 'view_transaction',
170
+			'TXN_ID' => $transaction->ID(),
171
+		), TXN_ADMIN_URL);
172
+		$content      = '<a href="' . $view_lnk_url . '"'
173
+						. ' title="' . esc_attr__('Go to Transaction Details', 'event_espresso') . '">'
174
+						. $transaction->ID()
175
+						. '</a>';
176
+
177
+		//txn timestamp
178
+		$content .= '  <span class="show-on-mobile-view-only">' . $this->_get_txn_timestamp($transaction) . '</span>';
179
+		return $content;
180
+	}
181
+
182
+
183
+	/**
184
+	 * @param \EE_Transaction $transaction
185
+	 * @return string
186
+	 * @throws EE_Error
187
+	 * @throws InvalidArgumentException
188
+	 * @throws InvalidDataTypeException
189
+	 * @throws InvalidInterfaceException
190
+	 */
191
+	protected function _get_txn_timestamp(EE_Transaction $transaction)
192
+	{
193
+		// is TXN less than 2 hours old ?
194
+		if (($transaction->failed() || $transaction->is_abandoned())
195
+			&& $this->session_lifespan->expiration() < $transaction->datetime(false, true)
196
+		) {
197
+			$timestamp = esc_html__('TXN in progress...', 'event_espresso');
198
+		} else {
199
+			$timestamp = $transaction->get_i18n_datetime('TXN_timestamp');
200
+		}
201
+		return $timestamp;
202
+	}
203
+
204
+
205
+	/**
206
+	 *    column_cb
207
+	 *
208
+	 * @param \EE_Transaction $transaction
209
+	 * @return string
210
+	 * @throws \EE_Error
211
+	 */
212
+	public function column_cb($transaction)
213
+	{
214
+		return sprintf(
215
+			'<input type="checkbox" name="%1$s[]" value="%2$s" />',
216
+			$this->_wp_list_args['singular'],
217
+			$transaction->ID()
218
+		);
219
+	}
220
+
221
+
222
+	/**
223
+	 *    column_TXN_timestamp
224
+	 *
225
+	 * @param \EE_Transaction $transaction
226
+	 * @return string
227
+	 * @throws \EE_Error
228
+	 */
229
+	public function column_TXN_timestamp(EE_Transaction $transaction)
230
+	{
231
+		$view_lnk_url = EE_Admin_Page::add_query_args_and_nonce(array(
232
+			'action' => 'view_transaction',
233
+			'TXN_ID' => $transaction->ID(),
234
+		), TXN_ADMIN_URL);
235
+		$txn_date     = '<a href="' . $view_lnk_url . '"'
236
+						. ' title="'
237
+						. esc_attr__('View Transaction Details for TXN #', 'event_espresso') . $transaction->ID() . '">'
238
+						. $this->_get_txn_timestamp($transaction)
239
+						. '</a>';
240
+		//status
241
+		$txn_date .= '<br><span class="ee-status-text-small">'
242
+					 . EEH_Template::pretty_status(
243
+						 $transaction->status_ID(),
244
+						 false,
245
+						 'sentence'
246
+					 )
247
+					 . '</span>';
248
+		return $txn_date;
249
+	}
250
+
251
+
252
+	/**
253
+	 *    column_TXN_total
254
+	 *
255
+	 * @param \EE_Transaction $transaction
256
+	 * @return string
257
+	 * @throws \EE_Error
258
+	 */
259
+	public function column_TXN_total(EE_Transaction $transaction)
260
+	{
261
+		if ($transaction->get('TXN_total') > 0) {
262
+			return '<span class="txn-pad-rght">'
263
+				   . apply_filters(
264
+					   'FHEE__EE_Admin_Transactions_List_Table__column_TXN_total__TXN_total',
265
+					   $transaction->get_pretty('TXN_total'),
266
+					   $transaction
267
+				   )
268
+				   . '</span>';
269
+		} else {
270
+			return '<span class="txn-overview-free-event-spn">' . esc_html__('free', 'event_espresso') . '</span>';
271
+		}
272
+	}
273
+
274
+
275
+	/**
276
+	 *    column_TXN_paid
277
+	 *
278
+	 * @param \EE_Transaction $transaction
279
+	 * @return mixed|string
280
+	 * @throws \EE_Error
281
+	 */
282
+	public function column_TXN_paid(EE_Transaction $transaction)
283
+	{
284
+		$transaction_total = $transaction->get('TXN_total');
285
+		$transaction_paid  = $transaction->get('TXN_paid');
286
+
287
+		if (\EEH_Money::compare_floats($transaction_total, 0, '>')) {
288
+			// monies owing
289
+			$span_class = 'txn-overview-part-payment-spn';
290
+			if (\EEH_Money::compare_floats($transaction_paid, $transaction_total, '>=')) {
291
+				// paid in full
292
+				$span_class = 'txn-overview-full-payment-spn';
293
+			} elseif (\EEH_Money::compare_floats($transaction_paid, 0, '==')) {
294
+				// no payments made
295
+				$span_class = 'txn-overview-no-payment-spn';
296
+			}
297
+		} else {
298
+			$span_class       = 'txn-overview-free-event-spn';
299
+			$transaction_paid = 0;
300
+		}
301
+
302
+		$payment_method      = $transaction->payment_method();
303
+		$payment_method_name = $payment_method instanceof EE_Payment_Method
304
+			? $payment_method->admin_name()
305
+			: esc_html__('Unknown', 'event_espresso');
306
+		$transaction_paid_content = $transaction_paid !== 0 ? $transaction->get_pretty('TXN_paid') : $transaction_paid;
307
+
308
+		$content = '<span class="' . $span_class . ' txn-pad-rght">'
309
+				   . $transaction_paid_content
310
+				   . '</span>';
311
+		if ($transaction_paid > 0) {
312
+			$content .= '<br><span class="ee-status-text-small">'
313
+						. sprintf(
314
+							esc_html__('...via %s', 'event_espresso'),
315
+							$payment_method_name
316
+						)
317
+						. '</span>';
318
+		}
319
+		return $content;
320
+	}
321
+
322
+
323
+	/**
324
+	 *    column_ATT_fname
325
+	 *
326
+	 * @param \EE_Transaction $transaction
327
+	 * @return string
328
+	 * @throws EE_Error
329
+	 * @throws InvalidArgumentException
330
+	 * @throws InvalidDataTypeException
331
+	 * @throws InvalidInterfaceException
332
+	 */
333
+	public function column_ATT_fname(EE_Transaction $transaction)
334
+	{
335
+		$primary_reg = $transaction->primary_registration();
336
+		$attendee    = $primary_reg->get_first_related('Attendee');
337
+		if ($attendee instanceof EE_Attendee) {
338
+			$edit_lnk_url = EE_Admin_Page::add_query_args_and_nonce(array(
339
+				'action'  => 'view_registration',
340
+				'_REG_ID' => $primary_reg->ID(),
341
+			), REG_ADMIN_URL);
342
+			$content      = EE_Registry::instance()->CAP->current_user_can(
343
+				'ee_read_registration',
344
+				'espresso_registrations_view_registration',
345
+				$primary_reg->ID()
346
+			)
347
+				? '<a href="' . $edit_lnk_url . '"'
348
+					. ' title="' . esc_attr__('View Registration Details', 'event_espresso') . '">'
349
+					. $attendee->full_name()
350
+					. '</a>'
351
+				: $attendee->full_name();
352
+			$content      .= '<br>' . $attendee->email();
353
+			return $content;
354
+		}
355
+		return $transaction->failed() || $transaction->is_abandoned()
356
+			? esc_html__('no contact record.', 'event_espresso')
357
+			: esc_html__(
358
+				'No contact record, because the transaction was abandoned or the registration process failed.',
359
+				'event_espresso'
360
+			);
361
+	}
362
+
363
+
364
+	/**
365
+	 *    column_ATT_email
366
+	 *
367
+	 * @param \EE_Transaction $transaction
368
+	 * @return string
369
+	 * @throws \EE_Error
370
+	 */
371
+	public function column_ATT_email(EE_Transaction $transaction)
372
+	{
373
+		$attendee = $transaction->primary_registration()->get_first_related('Attendee');
374
+		if (! empty($attendee)) {
375
+			return '<a href="mailto:' . $attendee->get('ATT_email') . '">'
376
+				   . $attendee->get('ATT_email')
377
+				   . '</a>';
378
+		} else {
379
+			return $transaction->failed() || $transaction->is_abandoned()
380
+				? esc_html__('no contact record.', 'event_espresso')
381
+				: esc_html__(
382
+					'No contact record, because the transaction was abandoned or the registration process failed.',
383
+					'event_espresso'
384
+				);
385
+		}
386
+	}
387
+
388
+
389
+	/**
390
+	 *    column_event_name
391
+	 *
392
+	 * @param \EE_Transaction $transaction
393
+	 * @return string
394
+	 * @throws EE_Error
395
+	 * @throws InvalidArgumentException
396
+	 * @throws InvalidDataTypeException
397
+	 * @throws InvalidInterfaceException
398
+	 */
399
+	public function column_event_name(EE_Transaction $transaction)
400
+	{
401
+		$actions = array();
402
+		$event   = $transaction->primary_registration()->get_first_related('Event');
403
+		if (! empty($event)) {
404
+			$edit_event_url = EE_Admin_Page::add_query_args_and_nonce(
405
+				array('action' => 'edit', 'post' => $event->ID()),
406
+				EVENTS_ADMIN_URL
407
+			);
408
+			$event_name     = $event->get('EVT_name');
409
+
410
+			//filter this view by transactions for this event
411
+			$txn_by_event_lnk = EE_Admin_Page::add_query_args_and_nonce(array(
412
+				'action' => 'default',
413
+				'EVT_ID' => $event->ID(),
414
+			));
415
+			if (empty($this->_req_data['EVT_ID'])
416
+				&& EE_Registry::instance()->CAP->current_user_can(
417
+					'ee_edit_event',
418
+					'espresso_events_edit',
419
+					$event->ID()
420
+				)
421
+			) {
422
+				$actions['filter_by_event'] = '<a href="' . $txn_by_event_lnk . '"'
423
+						. ' title="' . esc_attr__('Filter transactions by this event', 'event_espresso') . '">'
424
+						. esc_html__('View Transactions for this event', 'event_espresso')
425
+						. '</a>';
426
+			}
427
+
428
+			return sprintf(
429
+				'%1$s %2$s',
430
+				EE_Registry::instance()->CAP->current_user_can(
431
+					'ee_edit_event',
432
+					'espresso_events_edit',
433
+					$event->ID()
434
+				)
435
+					? '<a href="' . $edit_event_url . '"'
436
+						. ' title="'
437
+						. sprintf(
438
+							esc_attr__('Edit Event: %s', 'event_espresso'),
439
+							$event->get('EVT_name')
440
+						)
441
+						. '">'
442
+						. wp_trim_words(
443
+							$event_name,
444
+							30,
445
+							'...'
446
+						)
447
+						. '</a>'
448
+						: wp_trim_words($event_name, 30, '...'),
449
+				$this->row_actions($actions)
450
+			);
451
+		} else {
452
+			return esc_html__(
453
+				'The event associated with this transaction via the primary registration cannot be retrieved.',
454
+				'event_espresso'
455
+			);
456
+		}
457
+	}
458
+
459
+
460
+	/**
461
+	 *    column_actions
462
+	 *
463
+	 * @param \EE_Transaction $transaction
464
+	 * @return string
465
+	 * @throws \EE_Error
466
+	 */
467
+	public function column_actions(EE_Transaction $transaction)
468
+	{
469
+		return $this->_action_string(
470
+			$this->get_transaction_details_link($transaction)
471
+			. $this->get_invoice_link($transaction)
472
+			. $this->get_receipt_link($transaction)
473
+			. $this->get_primary_registration_details_link($transaction)
474
+			. $this->get_send_payment_reminder_trigger_link($transaction)
475
+			. $this->get_payment_overview_link($transaction)
476
+			. $this->get_related_messages_link($transaction),
477
+			$transaction,
478
+			'ul',
479
+			'txn-overview-actions-ul'
480
+		);
481
+	}
482
+
483
+
484
+	/**
485
+	 * Get the transaction details link.
486
+	 * @param EE_Transaction $transaction
487
+	 * @return string
488
+	 * @throws EE_Error
489
+	 */
490
+	protected function get_transaction_details_link(EE_Transaction $transaction)
491
+	{
492
+		$url          = EE_Admin_Page::add_query_args_and_nonce(array(
493
+			'action' => 'view_transaction',
494
+			'TXN_ID' => $transaction->ID(),
495
+		), TXN_ADMIN_URL);
496
+		return '
497 497
 			<li>
498 498
 				<a href="' . $url . '"'
499
-                    . ' title="' . esc_attr__('View Transaction Details', 'event_espresso') . '" class="tiny-text">
499
+					. ' title="' . esc_attr__('View Transaction Details', 'event_espresso') . '" class="tiny-text">
500 500
 					<span class="dashicons dashicons-cart"></span>
501 501
 				</a>
502 502
 			</li>';
503
-    }
504
-
505
-
506
-    /**
507
-     * Get the invoice link for the given registration.
508
-     * @param EE_Transaction $transaction
509
-     * @return string
510
-     * @throws EE_Error
511
-     */
512
-    protected function get_invoice_link(EE_Transaction $transaction)
513
-    {
514
-        $registration = $transaction->primary_registration();
515
-        if ($registration instanceof EE_Registration) {
516
-            $url = $registration->invoice_url();
517
-            //only show invoice link if message type is active.
518
-            if ($registration->attendee() instanceof EE_Attendee
519
-                && EEH_MSG_Template::is_mt_active('invoice')
520
-            ) {
521
-                return '
503
+	}
504
+
505
+
506
+	/**
507
+	 * Get the invoice link for the given registration.
508
+	 * @param EE_Transaction $transaction
509
+	 * @return string
510
+	 * @throws EE_Error
511
+	 */
512
+	protected function get_invoice_link(EE_Transaction $transaction)
513
+	{
514
+		$registration = $transaction->primary_registration();
515
+		if ($registration instanceof EE_Registration) {
516
+			$url = $registration->invoice_url();
517
+			//only show invoice link if message type is active.
518
+			if ($registration->attendee() instanceof EE_Attendee
519
+				&& EEH_MSG_Template::is_mt_active('invoice')
520
+			) {
521
+				return '
522 522
                 <li>
523 523
                     <a title="' . esc_attr__('View Transaction Invoice', 'event_espresso') . '"'
524
-                       . ' target="_blank" href="' . $url . '" class="tiny-text">
524
+					   . ' target="_blank" href="' . $url . '" class="tiny-text">
525 525
                         <span class="dashicons dashicons-media-spreadsheet ee-icon-size-18"></span>
526 526
                     </a>
527 527
                 </li>';
528
-            }
529
-        }
530
-        return '';
531
-    }
532
-
533
-
534
-    /**
535
-     * Get the receipt link for the transaction.
536
-     * @param EE_Transaction $transaction
537
-     * @return string
538
-     * @throws EE_Error
539
-     */
540
-    protected function get_receipt_link(EE_Transaction $transaction)
541
-    {
542
-        $registration = $transaction->primary_registration();
543
-        if ($registration instanceof EE_Registration) {
544
-            $url = $registration->receipt_url();
545
-            //only show receipt link if message type is active.
546
-            if ($registration->attendee() instanceof EE_Attendee
547
-                && EEH_MSG_Template::is_mt_active('receipt')) {
548
-                return '
528
+			}
529
+		}
530
+		return '';
531
+	}
532
+
533
+
534
+	/**
535
+	 * Get the receipt link for the transaction.
536
+	 * @param EE_Transaction $transaction
537
+	 * @return string
538
+	 * @throws EE_Error
539
+	 */
540
+	protected function get_receipt_link(EE_Transaction $transaction)
541
+	{
542
+		$registration = $transaction->primary_registration();
543
+		if ($registration instanceof EE_Registration) {
544
+			$url = $registration->receipt_url();
545
+			//only show receipt link if message type is active.
546
+			if ($registration->attendee() instanceof EE_Attendee
547
+				&& EEH_MSG_Template::is_mt_active('receipt')) {
548
+				return '
549 549
 			<li>
550 550
 				<a title="' . esc_attr__('View Transaction Receipt', 'event_espresso') . '"'
551
-                                  . ' target="_blank" href="' . $url . '" class="tiny-text">
551
+								  . ' target="_blank" href="' . $url . '" class="tiny-text">
552 552
 					<span class="dashicons dashicons-media-default ee-icon-size-18"></span>
553 553
 				</a>
554 554
 			</li>';
555
-            }
556
-        }
557
-        return '';
558
-    }
559
-
560
-
561
-    /**
562
-     * Get the link to view the details for the primary registration.
563
-     *
564
-     * @param EE_Transaction $transaction
565
-     * @return string
566
-     * @throws EE_Error
567
-     * @throws InvalidArgumentException
568
-     * @throws InvalidDataTypeException
569
-     * @throws InvalidInterfaceException
570
-     */
571
-    protected function get_primary_registration_details_link(EE_Transaction $transaction)
572
-    {
573
-        $registration = $transaction->primary_registration();
574
-        if ($registration instanceof EE_Registration) {
575
-            $url      = EE_Admin_Page::add_query_args_and_nonce(array(
576
-                'action'  => 'view_registration',
577
-                '_REG_ID' => $registration->ID(),
578
-            ), REG_ADMIN_URL);
579
-            return EE_Registry::instance()->CAP->current_user_can(
580
-                'ee_read_registration',
581
-                'espresso_registrations_view_registration',
582
-                $registration->ID()
583
-            )
584
-                ? '
555
+			}
556
+		}
557
+		return '';
558
+	}
559
+
560
+
561
+	/**
562
+	 * Get the link to view the details for the primary registration.
563
+	 *
564
+	 * @param EE_Transaction $transaction
565
+	 * @return string
566
+	 * @throws EE_Error
567
+	 * @throws InvalidArgumentException
568
+	 * @throws InvalidDataTypeException
569
+	 * @throws InvalidInterfaceException
570
+	 */
571
+	protected function get_primary_registration_details_link(EE_Transaction $transaction)
572
+	{
573
+		$registration = $transaction->primary_registration();
574
+		if ($registration instanceof EE_Registration) {
575
+			$url      = EE_Admin_Page::add_query_args_and_nonce(array(
576
+				'action'  => 'view_registration',
577
+				'_REG_ID' => $registration->ID(),
578
+			), REG_ADMIN_URL);
579
+			return EE_Registry::instance()->CAP->current_user_can(
580
+				'ee_read_registration',
581
+				'espresso_registrations_view_registration',
582
+				$registration->ID()
583
+			)
584
+				? '
585 585
 				<li>
586 586
 					<a href="' . $url . '"'
587
-                  . ' title="' . esc_attr__('View Registration Details', 'event_espresso') . '" class="tiny-text">
587
+				  . ' title="' . esc_attr__('View Registration Details', 'event_espresso') . '" class="tiny-text">
588 588
 						<span class="dashicons dashicons-clipboard"></span>
589 589
 					</a>
590 590
 				</li>'
591
-                : '';
592
-        }
593
-        return '';
594
-    }
595
-
596
-
597
-    /**
598
-     * Get send payment reminder trigger link
599
-     * @param EE_Transaction $transaction
600
-     * @return string
601
-     * @throws EE_Error
602
-     * @throws InvalidArgumentException
603
-     * @throws InvalidDataTypeException
604
-     * @throws InvalidInterfaceException
605
-     */
606
-    protected function get_send_payment_reminder_trigger_link(EE_Transaction $transaction)
607
-    {
608
-        $registration = $transaction->primary_registration();
609
-        if ($registration instanceof EE_Registration
610
-            && $registration->attendee() instanceof EE_Attendee
611
-            && EEH_MSG_Template::is_mt_active('payment_reminder')
612
-            && ! in_array(
613
-                $transaction->status_ID(),
614
-                array(EEM_Transaction::complete_status_code, EEM_Transaction::overpaid_status_code),
615
-                true
616
-            )
617
-            && EE_Registry::instance()->CAP->current_user_can(
618
-                'ee_send_message',
619
-                'espresso_transactions_send_payment_reminder'
620
-            )
621
-        ) {
622
-            $url = EE_Admin_Page::add_query_args_and_nonce(array(
623
-                'action' => 'send_payment_reminder',
624
-                'TXN_ID' => $transaction->ID(),
625
-            ), TXN_ADMIN_URL);
626
-            return  '
591
+				: '';
592
+		}
593
+		return '';
594
+	}
595
+
596
+
597
+	/**
598
+	 * Get send payment reminder trigger link
599
+	 * @param EE_Transaction $transaction
600
+	 * @return string
601
+	 * @throws EE_Error
602
+	 * @throws InvalidArgumentException
603
+	 * @throws InvalidDataTypeException
604
+	 * @throws InvalidInterfaceException
605
+	 */
606
+	protected function get_send_payment_reminder_trigger_link(EE_Transaction $transaction)
607
+	{
608
+		$registration = $transaction->primary_registration();
609
+		if ($registration instanceof EE_Registration
610
+			&& $registration->attendee() instanceof EE_Attendee
611
+			&& EEH_MSG_Template::is_mt_active('payment_reminder')
612
+			&& ! in_array(
613
+				$transaction->status_ID(),
614
+				array(EEM_Transaction::complete_status_code, EEM_Transaction::overpaid_status_code),
615
+				true
616
+			)
617
+			&& EE_Registry::instance()->CAP->current_user_can(
618
+				'ee_send_message',
619
+				'espresso_transactions_send_payment_reminder'
620
+			)
621
+		) {
622
+			$url = EE_Admin_Page::add_query_args_and_nonce(array(
623
+				'action' => 'send_payment_reminder',
624
+				'TXN_ID' => $transaction->ID(),
625
+			), TXN_ADMIN_URL);
626
+			return  '
627 627
             <li>
628 628
                 <a href="' . $url . '"'
629
-                  . ' title="' . esc_attr__('Send Payment Reminder', 'event_espresso') . '" class="tiny-text">
629
+				  . ' title="' . esc_attr__('Send Payment Reminder', 'event_espresso') . '" class="tiny-text">
630 630
                     <span class="dashicons dashicons-email-alt"></span>
631 631
                 </a>
632 632
             </li>';
633
-        }
634
-        return '';
635
-    }
636
-
637
-
638
-    /**
639
-     * Get link to filtered view in the message activity list table of messages for this transaction.
640
-     * @param EE_Transaction $transaction
641
-     * @return string
642
-     * @throws EE_Error
643
-     * @throws InvalidArgumentException
644
-     * @throws InvalidDataTypeException
645
-     * @throws InvalidInterfaceException
646
-     */
647
-    protected function get_related_messages_link(EE_Transaction $transaction)
648
-    {
649
-        $url = EEH_MSG_Template::get_message_action_link(
650
-            'see_notifications_for',
651
-            null,
652
-            array('TXN_ID' => $transaction->ID())
653
-        );
654
-        return EE_Registry::instance()->CAP->current_user_can(
655
-            'ee_read_global_messages',
656
-            'view_filtered_messages'
657
-        )
658
-            ? '<li>' . $url . '</li>'
659
-            : '';
660
-    }
661
-
662
-
663
-    /**
664
-     * Return the link to make a payment on the frontend
665
-     * @param EE_Transaction $transaction
666
-     * @return string
667
-     * @throws EE_Error
668
-     */
669
-    protected function get_payment_overview_link(EE_Transaction $transaction)
670
-    {
671
-        $registration = $transaction->primary_registration();
672
-        if ($registration instanceof EE_Registration
673
-            && $transaction->status_ID() !== EEM_Transaction::complete_status_code
674
-            && $registration->owes_monies_and_can_pay()
675
-        ) {
676
-            return '
633
+		}
634
+		return '';
635
+	}
636
+
637
+
638
+	/**
639
+	 * Get link to filtered view in the message activity list table of messages for this transaction.
640
+	 * @param EE_Transaction $transaction
641
+	 * @return string
642
+	 * @throws EE_Error
643
+	 * @throws InvalidArgumentException
644
+	 * @throws InvalidDataTypeException
645
+	 * @throws InvalidInterfaceException
646
+	 */
647
+	protected function get_related_messages_link(EE_Transaction $transaction)
648
+	{
649
+		$url = EEH_MSG_Template::get_message_action_link(
650
+			'see_notifications_for',
651
+			null,
652
+			array('TXN_ID' => $transaction->ID())
653
+		);
654
+		return EE_Registry::instance()->CAP->current_user_can(
655
+			'ee_read_global_messages',
656
+			'view_filtered_messages'
657
+		)
658
+			? '<li>' . $url . '</li>'
659
+			: '';
660
+	}
661
+
662
+
663
+	/**
664
+	 * Return the link to make a payment on the frontend
665
+	 * @param EE_Transaction $transaction
666
+	 * @return string
667
+	 * @throws EE_Error
668
+	 */
669
+	protected function get_payment_overview_link(EE_Transaction $transaction)
670
+	{
671
+		$registration = $transaction->primary_registration();
672
+		if ($registration instanceof EE_Registration
673
+			&& $transaction->status_ID() !== EEM_Transaction::complete_status_code
674
+			&& $registration->owes_monies_and_can_pay()
675
+		) {
676
+			return '
677 677
             <li>
678 678
                 <a title="' . esc_attr__('Make Payment from the Frontend.', 'event_espresso') . '"'
679
-                    . ' target="_blank" href="' . $registration->payment_overview_url(true) . '"'
680
-                    . ' class="tiny-text">
679
+					. ' target="_blank" href="' . $registration->payment_overview_url(true) . '"'
680
+					. ' class="tiny-text">
681 681
                     <span class="dashicons dashicons-money ee-icon-size-18"></span>
682 682
                 </a>
683 683
             </li>
684 684
             ';
685 685
 
686
-        }
687
-        return '';
688
-    }
686
+		}
687
+		return '';
688
+	}
689 689
 }
Please login to merge, or discard this patch.
core/domain/values/session/SessionLifespan.php 2 patches
Indentation   +95 added lines, -95 removed lines patch added patch discarded remove patch
@@ -24,99 +24,99 @@
 block discarded – undo
24 24
 class SessionLifespan
25 25
 {
26 26
 
27
-    /**
28
-     * how long an EE session lasts in seconds
29
-     * default session lifespan of 1 hour (for not so instant IPNs)
30
-     *
31
-     * @var int $lifespan
32
-     */
33
-    private $lifespan;
34
-
35
-
36
-    /**
37
-     * SessionLifespan constructor.
38
-     *
39
-     * @param int $lifespan
40
-     * @throws DomainException
41
-     */
42
-    public function __construct($lifespan = 0)
43
-    {
44
-        $lifespan = absint($lifespan);
45
-        $lifespan = $lifespan > 0 ? $lifespan : (int) HOUR_IN_SECONDS;
46
-        $this->setLifespan($lifespan);
47
-    }
48
-
49
-
50
-    /**
51
-     * @param int $lifespan
52
-     * @throws DomainException
53
-     */
54
-    protected function setLifespan($lifespan)
55
-    {
56
-        if($lifespan < 60) {
57
-            throw new DomainException(
58
-                esc_html__(
59
-                    'The session lifespan needs to be at least 60 seconds, and even that is extremely short',
60
-                    'event_espresso'
61
-                )
62
-            );
63
-
64
-        }
65
-        $this->lifespan = apply_filters(
66
-            'FHEE__EventEspresso_core_domain_values_session_SessionLifespan__setLifespan___lifespan',
67
-            // apply legacy filter for now but add doing it wrong notice in future
68
-            apply_filters(
69
-                'FHEE__EE_Session__construct___lifespan',
70
-                $lifespan
71
-            )
72
-        ) + 1;
73
-    }
74
-
75
-
76
-    /**
77
-     * @return int
78
-     */
79
-    public function inSeconds()
80
-    {
81
-        return $this->lifespan;
82
-    }
83
-
84
-
85
-    /**
86
-     * @param string $separator
87
-     * @return string
88
-     */
89
-    public function inHoursMinutesSeconds($separator = ':')
90
-    {
91
-        return sprintf(
92
-            '%02d%s%02d%s%02d',
93
-            floor($this->lifespan / 3600),
94
-            $separator,
95
-            ($this->lifespan / 60) % 60,
96
-            $separator,
97
-            $this->lifespan % 60
98
-        );
99
-    }
100
-
101
-
102
-    /**
103
-     * Returns a timestamp for when the session would expire based on this lifespan
104
-     *
105
-     * @param bool $utc If true, displays expiration in UTC
106
-     *                  If false, displays expiration in local time
107
-     * @return float
108
-     */
109
-    public function expiration($utc = true)
110
-    {
111
-        return current_time('timestamp', $utc) - $this->lifespan;
112
-    }
113
-
114
-
115
-    /**
116
-     * @return string
117
-     */
118
-    public function __toString()
119
-    {
120
-        return (string) $this->inSeconds();
121
-    }
27
+	/**
28
+	 * how long an EE session lasts in seconds
29
+	 * default session lifespan of 1 hour (for not so instant IPNs)
30
+	 *
31
+	 * @var int $lifespan
32
+	 */
33
+	private $lifespan;
34
+
35
+
36
+	/**
37
+	 * SessionLifespan constructor.
38
+	 *
39
+	 * @param int $lifespan
40
+	 * @throws DomainException
41
+	 */
42
+	public function __construct($lifespan = 0)
43
+	{
44
+		$lifespan = absint($lifespan);
45
+		$lifespan = $lifespan > 0 ? $lifespan : (int) HOUR_IN_SECONDS;
46
+		$this->setLifespan($lifespan);
47
+	}
48
+
49
+
50
+	/**
51
+	 * @param int $lifespan
52
+	 * @throws DomainException
53
+	 */
54
+	protected function setLifespan($lifespan)
55
+	{
56
+		if($lifespan < 60) {
57
+			throw new DomainException(
58
+				esc_html__(
59
+					'The session lifespan needs to be at least 60 seconds, and even that is extremely short',
60
+					'event_espresso'
61
+				)
62
+			);
63
+
64
+		}
65
+		$this->lifespan = apply_filters(
66
+			'FHEE__EventEspresso_core_domain_values_session_SessionLifespan__setLifespan___lifespan',
67
+			// apply legacy filter for now but add doing it wrong notice in future
68
+			apply_filters(
69
+				'FHEE__EE_Session__construct___lifespan',
70
+				$lifespan
71
+			)
72
+		) + 1;
73
+	}
74
+
75
+
76
+	/**
77
+	 * @return int
78
+	 */
79
+	public function inSeconds()
80
+	{
81
+		return $this->lifespan;
82
+	}
83
+
84
+
85
+	/**
86
+	 * @param string $separator
87
+	 * @return string
88
+	 */
89
+	public function inHoursMinutesSeconds($separator = ':')
90
+	{
91
+		return sprintf(
92
+			'%02d%s%02d%s%02d',
93
+			floor($this->lifespan / 3600),
94
+			$separator,
95
+			($this->lifespan / 60) % 60,
96
+			$separator,
97
+			$this->lifespan % 60
98
+		);
99
+	}
100
+
101
+
102
+	/**
103
+	 * Returns a timestamp for when the session would expire based on this lifespan
104
+	 *
105
+	 * @param bool $utc If true, displays expiration in UTC
106
+	 *                  If false, displays expiration in local time
107
+	 * @return float
108
+	 */
109
+	public function expiration($utc = true)
110
+	{
111
+		return current_time('timestamp', $utc) - $this->lifespan;
112
+	}
113
+
114
+
115
+	/**
116
+	 * @return string
117
+	 */
118
+	public function __toString()
119
+	{
120
+		return (string) $this->inSeconds();
121
+	}
122 122
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -53,7 +53,7 @@
 block discarded – undo
53 53
      */
54 54
     protected function setLifespan($lifespan)
55 55
     {
56
-        if($lifespan < 60) {
56
+        if ($lifespan < 60) {
57 57
             throw new DomainException(
58 58
                 esc_html__(
59 59
                     'The session lifespan needs to be at least 60 seconds, and even that is extremely short',
Please login to merge, or discard this patch.
core/admin/EE_Admin_Page.core.php 1 patch
Indentation   +4125 added lines, -4125 removed lines patch added patch discarded remove patch
@@ -21,4210 +21,4210 @@
 block discarded – undo
21 21
 {
22 22
 
23 23
 
24
-    //set in _init_page_props()
25
-    public $page_slug;
24
+	//set in _init_page_props()
25
+	public $page_slug;
26 26
 
27
-    public $page_label;
27
+	public $page_label;
28 28
 
29
-    public $page_folder;
29
+	public $page_folder;
30 30
 
31
-    //set in define_page_props()
32
-    protected $_admin_base_url;
31
+	//set in define_page_props()
32
+	protected $_admin_base_url;
33 33
 
34
-    protected $_admin_base_path;
34
+	protected $_admin_base_path;
35 35
 
36
-    protected $_admin_page_title;
36
+	protected $_admin_page_title;
37 37
 
38
-    protected $_labels;
38
+	protected $_labels;
39 39
 
40 40
 
41
-    //set early within EE_Admin_Init
42
-    protected $_wp_page_slug;
41
+	//set early within EE_Admin_Init
42
+	protected $_wp_page_slug;
43 43
 
44
-    //navtabs
45
-    protected $_nav_tabs;
44
+	//navtabs
45
+	protected $_nav_tabs;
46 46
 
47
-    protected $_default_nav_tab_name;
47
+	protected $_default_nav_tab_name;
48 48
 
49
-    /**
50
-     * @var array $_help_tour
51
-     */
52
-    protected $_help_tour = array();
49
+	/**
50
+	 * @var array $_help_tour
51
+	 */
52
+	protected $_help_tour = array();
53 53
 
54 54
 
55
-    //template variables (used by templates)
56
-    protected $_template_path;
55
+	//template variables (used by templates)
56
+	protected $_template_path;
57 57
 
58
-    protected $_column_template_path;
58
+	protected $_column_template_path;
59 59
 
60
-    /**
61
-     * @var array $_template_args
62
-     */
63
-    protected $_template_args = array();
60
+	/**
61
+	 * @var array $_template_args
62
+	 */
63
+	protected $_template_args = array();
64 64
 
65
-    /**
66
-     * this will hold the list table object for a given view.
67
-     *
68
-     * @var EE_Admin_List_Table $_list_table_object
69
-     */
70
-    protected $_list_table_object;
65
+	/**
66
+	 * this will hold the list table object for a given view.
67
+	 *
68
+	 * @var EE_Admin_List_Table $_list_table_object
69
+	 */
70
+	protected $_list_table_object;
71 71
 
72
-    //bools
73
-    protected $_is_UI_request = null; //this starts at null so we can have no header routes progress through two states.
72
+	//bools
73
+	protected $_is_UI_request = null; //this starts at null so we can have no header routes progress through two states.
74 74
 
75
-    protected $_routing;
75
+	protected $_routing;
76 76
 
77
-    //list table args
78
-    protected $_view;
77
+	//list table args
78
+	protected $_view;
79 79
 
80
-    protected $_views;
80
+	protected $_views;
81 81
 
82 82
 
83
-    //action => method pairs used for routing incoming requests
84
-    protected $_page_routes;
83
+	//action => method pairs used for routing incoming requests
84
+	protected $_page_routes;
85 85
 
86
-    /**
87
-     * @var array $_page_config
88
-     */
89
-    protected $_page_config;
86
+	/**
87
+	 * @var array $_page_config
88
+	 */
89
+	protected $_page_config;
90 90
 
91
-    /**
92
-     * the current page route and route config
93
-     *
94
-     * @var string $_route
95
-     */
96
-    protected $_route;
91
+	/**
92
+	 * the current page route and route config
93
+	 *
94
+	 * @var string $_route
95
+	 */
96
+	protected $_route;
97 97
 
98
-    /**
99
-     * @var string $_cpt_route
100
-     */
101
-    protected $_cpt_route;
98
+	/**
99
+	 * @var string $_cpt_route
100
+	 */
101
+	protected $_cpt_route;
102 102
 
103
-    /**
104
-     * @var array $_route_config
105
-     */
106
-    protected $_route_config;
103
+	/**
104
+	 * @var array $_route_config
105
+	 */
106
+	protected $_route_config;
107 107
 
108
-    /**
109
-     * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
110
-     * actions.
111
-     *
112
-     * @since 4.6.x
113
-     * @var array.
114
-     */
115
-    protected $_default_route_query_args;
116
-
117
-    //set via request page and action args.
118
-    protected $_current_page;
108
+	/**
109
+	 * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
110
+	 * actions.
111
+	 *
112
+	 * @since 4.6.x
113
+	 * @var array.
114
+	 */
115
+	protected $_default_route_query_args;
116
+
117
+	//set via request page and action args.
118
+	protected $_current_page;
119 119
 
120
-    protected $_current_view;
120
+	protected $_current_view;
121 121
 
122
-    protected $_current_page_view_url;
122
+	protected $_current_page_view_url;
123 123
 
124
-    //sanitized request action (and nonce)
124
+	//sanitized request action (and nonce)
125 125
 
126
-    /**
127
-     * @var string $_req_action
128
-     */
129
-    protected $_req_action;
130
-
131
-    /**
132
-     * @var string $_req_nonce
133
-     */
134
-    protected $_req_nonce;
135
-
136
-    //search related
137
-    protected $_search_btn_label;
138
-
139
-    protected $_search_box_callback;
140
-
141
-    /**
142
-     * WP Current Screen object
143
-     *
144
-     * @var WP_Screen
145
-     */
146
-    protected $_current_screen;
147
-
148
-    //for holding EE_Admin_Hooks object when needed (set via set_hook_object())
149
-    protected $_hook_obj;
150
-
151
-    //for holding incoming request data
152
-    protected $_req_data;
153
-
154
-    // yes / no array for admin form fields
155
-    protected $_yes_no_values = array();
156
-
157
-    //some default things shared by all child classes
158
-    protected $_default_espresso_metaboxes;
159
-
160
-    /**
161
-     *    EE_Registry Object
162
-     *
163
-     * @var    EE_Registry
164
-     */
165
-    protected $EE = null;
166
-
167
-
168
-
169
-    /**
170
-     * This is just a property that flags whether the given route is a caffeinated route or not.
171
-     *
172
-     * @var boolean
173
-     */
174
-    protected $_is_caf = false;
175
-
176
-
177
-
178
-    /**
179
-     * @Constructor
180
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
181
-     * @throws EE_Error
182
-     * @throws InvalidArgumentException
183
-     * @throws ReflectionException
184
-     * @throws InvalidDataTypeException
185
-     * @throws InvalidInterfaceException
186
-     */
187
-    public function __construct($routing = true)
188
-    {
189
-        if (strpos($this->_get_dir(), 'caffeinated') !== false) {
190
-            $this->_is_caf = true;
191
-        }
192
-        $this->_yes_no_values = array(
193
-            array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
194
-            array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
195
-        );
196
-        //set the _req_data property.
197
-        $this->_req_data = array_merge($_GET, $_POST);
198
-        //routing enabled?
199
-        $this->_routing = $routing;
200
-        //set initial page props (child method)
201
-        $this->_init_page_props();
202
-        //set global defaults
203
-        $this->_set_defaults();
204
-        //set early because incoming requests could be ajax related and we need to register those hooks.
205
-        $this->_global_ajax_hooks();
206
-        $this->_ajax_hooks();
207
-        //other_page_hooks have to be early too.
208
-        $this->_do_other_page_hooks();
209
-        //This just allows us to have extending classes do something specific
210
-        // before the parent constructor runs _page_setup().
211
-        if (method_exists($this, '_before_page_setup')) {
212
-            $this->_before_page_setup();
213
-        }
214
-        //set up page dependencies
215
-        $this->_page_setup();
216
-    }
217
-
218
-
219
-
220
-    /**
221
-     * _init_page_props
222
-     * Child classes use to set at least the following properties:
223
-     * $page_slug.
224
-     * $page_label.
225
-     *
226
-     * @abstract
227
-     * @return void
228
-     */
229
-    abstract protected function _init_page_props();
230
-
231
-
232
-
233
-    /**
234
-     * _ajax_hooks
235
-     * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
236
-     * Note: within the ajax callback methods.
237
-     *
238
-     * @abstract
239
-     * @return void
240
-     */
241
-    abstract protected function _ajax_hooks();
242
-
243
-
244
-
245
-    /**
246
-     * _define_page_props
247
-     * child classes define page properties in here.  Must include at least:
248
-     * $_admin_base_url = base_url for all admin pages
249
-     * $_admin_page_title = default admin_page_title for admin pages
250
-     * $_labels = array of default labels for various automatically generated elements:
251
-     *    array(
252
-     *        'buttons' => array(
253
-     *            'add' => esc_html__('label for add new button'),
254
-     *            'edit' => esc_html__('label for edit button'),
255
-     *            'delete' => esc_html__('label for delete button')
256
-     *            )
257
-     *        )
258
-     *
259
-     * @abstract
260
-     * @return void
261
-     */
262
-    abstract protected function _define_page_props();
263
-
264
-
265
-
266
-    /**
267
-     * _set_page_routes
268
-     * child classes use this to define the page routes for all subpages handled by the class.  Page routes are
269
-     * assigned to a action => method pairs in an array and to the $_page_routes property.  Each page route must also
270
-     * have a 'default' route. Here's the format
271
-     * $this->_page_routes = array(
272
-     *        'default' => array(
273
-     *            'func' => '_default_method_handling_route',
274
-     *            'args' => array('array','of','args'),
275
-     *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e.
276
-     *            ajax request, backend processing)
277
-     *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a
278
-     *            headers route after.  The string you enter here should match the defined route reference for a
279
-     *            headers sent route.
280
-     *            'capability' => 'route_capability', //indicate a string for minimum capability required to access
281
-     *            this route.
282
-     *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability
283
-     *            checks).
284
-     *        ),
285
-     *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a
286
-     *        handling method.
287
-     *        )
288
-     * )
289
-     *
290
-     * @abstract
291
-     * @return void
292
-     */
293
-    abstract protected function _set_page_routes();
294
-
295
-
296
-
297
-    /**
298
-     * _set_page_config
299
-     * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the
300
-     * array corresponds to the page_route for the loaded page. Format:
301
-     * $this->_page_config = array(
302
-     *        'default' => array(
303
-     *            'labels' => array(
304
-     *                'buttons' => array(
305
-     *                    'add' => esc_html__('label for adding item'),
306
-     *                    'edit' => esc_html__('label for editing item'),
307
-     *                    'delete' => esc_html__('label for deleting item')
308
-     *                ),
309
-     *                'publishbox' => esc_html__('Localized Title for Publish metabox', 'event_espresso')
310
-     *            ), //optional an array of custom labels for various automatically generated elements to use on the
311
-     *            page. If this isn't present then the defaults will be used as set for the $this->_labels in
312
-     *            _define_page_props() method
313
-     *            'nav' => array(
314
-     *                'label' => esc_html__('Label for Tab', 'event_espresso').
315
-     *                'url' => 'http://someurl', //automatically generated UNLESS you define
316
-     *                'css_class' => 'css-class', //automatically generated UNLESS you define
317
-     *                'order' => 10, //required to indicate tab position.
318
-     *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is
319
-     *                displayed then add this parameter.
320
-     *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
321
-     *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load
322
-     *            metaboxes set for eventespresso admin pages.
323
-     *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have
324
-     *            metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added
325
-     *            later.  We just use this flag to make sure the necessary js gets enqueued on page load.
326
-     *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the
327
-     *            given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
328
-     *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The
329
-     *            array indicates the max number of columns (4) and the default number of columns on page load (2).
330
-     *            There is an option in the "screen_options" dropdown that is setup so users can pick what columns they
331
-     *            want to display.
332
-     *            'help_tabs' => array( //this is used for adding help tabs to a page
333
-     *                'tab_id' => array(
334
-     *                    'title' => 'tab_title',
335
-     *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting
336
-     *                    help tab content.  The fallback if it isn't present is to try a the callback.  Filename
337
-     *                    should match a file in the admin folder's "help_tabs" dir (ie..
338
-     *                    events/help_tabs/name_of_file_containing_content.help_tab.php)
339
-     *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will
340
-     *                    attempt to use the callback which should match the name of a method in the class
341
-     *                    ),
342
-     *                'tab2_id' => array(
343
-     *                    'title' => 'tab2 title',
344
-     *                    'filename' => 'file_name_2'
345
-     *                    'callback' => 'callback_method_for_content',
346
-     *                 ),
347
-     *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the
348
-     *            help tab area on an admin page. @link
349
-     *            http://make.wordpress.org/core/2011/12/06/help-and-screen-api-changes-in-3-3/
350
-     *            'help_tour' => array(
351
-     *                'name_of_help_tour_class', //all help tours shoudl be a child class of EE_Help_Tour and located
352
-     *                in a folder for this admin page named "help_tours", a file name matching the key given here
353
-     *                (name_of_help_tour_class.class.php), and class matching key given here (name_of_help_tour_class)
354
-     *            ),
355
-     *            'require_nonce' => TRUE //this is used if you want to set a route to NOT require a nonce (default is
356
-     *            true if it isn't present).  To remove the requirement for a nonce check when this route is visited
357
-     *            just set
358
-     *            'require_nonce' to FALSE
359
-     *            )
360
-     * )
361
-     *
362
-     * @abstract
363
-     * @return void
364
-     */
365
-    abstract protected function _set_page_config();
366
-
367
-
368
-
369
-
370
-
371
-    /** end sample help_tour methods **/
372
-    /**
373
-     * _add_screen_options
374
-     * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for
375
-     * doing so. Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options
376
-     * to a particular view.
377
-     *
378
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
379
-     *         see also WP_Screen object documents...
380
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
381
-     * @abstract
382
-     * @return void
383
-     */
384
-    abstract protected function _add_screen_options();
385
-
386
-
387
-
388
-    /**
389
-     * _add_feature_pointers
390
-     * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
391
-     * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a
392
-     * particular view. Note: this is just a placeholder for now.  Implementation will come down the road See:
393
-     * WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
394
-     * extended) also see:
395
-     *
396
-     * @link   http://eamann.com/tech/wordpress-portland/
397
-     * @abstract
398
-     * @return void
399
-     */
400
-    abstract protected function _add_feature_pointers();
401
-
402
-
403
-
404
-    /**
405
-     * load_scripts_styles
406
-     * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for
407
-     * their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific
408
-     * scripts/styles per view by putting them in a dynamic function in this format
409
-     * (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
410
-     *
411
-     * @abstract
412
-     * @return void
413
-     */
414
-    abstract public function load_scripts_styles();
415
-
416
-
417
-
418
-    /**
419
-     * admin_init
420
-     * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to
421
-     * all pages/views loaded by child class.
422
-     *
423
-     * @abstract
424
-     * @return void
425
-     */
426
-    abstract public function admin_init();
427
-
428
-
429
-
430
-    /**
431
-     * admin_notices
432
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to
433
-     * all pages/views loaded by child class.
434
-     *
435
-     * @abstract
436
-     * @return void
437
-     */
438
-    abstract public function admin_notices();
439
-
440
-
441
-
442
-    /**
443
-     * admin_footer_scripts
444
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
445
-     * will apply to all pages/views loaded by child class.
446
-     *
447
-     * @return void
448
-     */
449
-    abstract public function admin_footer_scripts();
450
-
451
-
452
-
453
-    /**
454
-     * admin_footer
455
-     * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will
456
-     * apply to all pages/views loaded by child class.
457
-     *
458
-     * @return void
459
-     */
460
-    public function admin_footer()
461
-    {
462
-    }
463
-
464
-
465
-
466
-    /**
467
-     * _global_ajax_hooks
468
-     * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
469
-     * Note: within the ajax callback methods.
470
-     *
471
-     * @abstract
472
-     * @return void
473
-     */
474
-    protected function _global_ajax_hooks()
475
-    {
476
-        //for lazy loading of metabox content
477
-        add_action('wp_ajax_espresso-ajax-content', array($this, 'ajax_metabox_content'), 10);
478
-    }
479
-
480
-
481
-
482
-    public function ajax_metabox_content()
483
-    {
484
-        $contentid = isset($this->_req_data['contentid']) ? $this->_req_data['contentid'] : '';
485
-        $url       = isset($this->_req_data['contenturl']) ? $this->_req_data['contenturl'] : '';
486
-        self::cached_rss_display($contentid, $url);
487
-        wp_die();
488
-    }
489
-
490
-
491
-
492
-    /**
493
-     * _page_setup
494
-     * Makes sure any things that need to be loaded early get handled.  We also escape early here if the page requested
495
-     * doesn't match the object.
496
-     *
497
-     * @final
498
-     * @return void
499
-     * @throws EE_Error
500
-     * @throws InvalidArgumentException
501
-     * @throws ReflectionException
502
-     * @throws InvalidDataTypeException
503
-     * @throws InvalidInterfaceException
504
-     */
505
-    final protected function _page_setup()
506
-    {
507
-        //requires?
508
-        //admin_init stuff - global - we're setting this REALLY early so if EE_Admin pages have to hook into other WP pages they can.  But keep in mind, not everything is available from the EE_Admin Page object at this point.
509
-        add_action('admin_init', array($this, 'admin_init_global'), 5);
510
-        //next verify if we need to load anything...
511
-        $this->_current_page = ! empty($_GET['page']) ? sanitize_key($_GET['page']) : '';
512
-        $this->page_folder   = strtolower(
513
-            str_replace(array('_Admin_Page', 'Extend_'), '', get_class($this))
514
-        );
515
-        global $ee_menu_slugs;
516
-        $ee_menu_slugs = (array)$ee_menu_slugs;
517
-        if (! defined('DOING_AJAX') && (! $this->_current_page || ! isset($ee_menu_slugs[$this->_current_page]))) {
518
-            return;
519
-        }
520
-        // becuz WP List tables have two duplicate select inputs for choosing bulk actions, we need to copy the action from the second to the first
521
-        if (isset($this->_req_data['action2']) && $this->_req_data['action'] === '-1') {
522
-            $this->_req_data['action'] = ! empty($this->_req_data['action2']) && $this->_req_data['action2'] !== '-1'
523
-                ? $this->_req_data['action2']
524
-                : $this->_req_data['action'];
525
-        }
526
-        // then set blank or -1 action values to 'default'
527
-        $this->_req_action = isset($this->_req_data['action'])
528
-                             && ! empty($this->_req_data['action'])
529
-                             && $this->_req_data['action'] !== '-1'
530
-            ? sanitize_key($this->_req_data['action'])
531
-            : 'default';
532
-        // if action is 'default' after the above BUT we have  'route' var set, then let's use the route as the action.
533
-        //  This covers cases where we're coming in from a list table that isn't on the default route.
534
-        $this->_req_action = $this->_req_action === 'default' && isset($this->_req_data['route'])
535
-            ? $this->_req_data['route'] : $this->_req_action;
536
-        //however if we are doing_ajax and we've got a 'route' set then that's what the req_action will be
537
-        $this->_req_action   = defined('DOING_AJAX') && isset($this->_req_data['route'])
538
-            ? $this->_req_data['route']
539
-            : $this->_req_action;
540
-        $this->_current_view = $this->_req_action;
541
-        $this->_req_nonce    = $this->_req_action . '_nonce';
542
-        $this->_define_page_props();
543
-        $this->_current_page_view_url = add_query_arg(
544
-            array('page' => $this->_current_page, 'action' => $this->_current_view),
545
-            $this->_admin_base_url
546
-        );
547
-        //default things
548
-        $this->_default_espresso_metaboxes = array(
549
-            '_espresso_news_post_box',
550
-            '_espresso_links_post_box',
551
-            '_espresso_ratings_request',
552
-            '_espresso_sponsors_post_box',
553
-        );
554
-        //set page configs
555
-        $this->_set_page_routes();
556
-        $this->_set_page_config();
557
-        //let's include any referrer data in our default_query_args for this route for "stickiness".
558
-        if (isset($this->_req_data['wp_referer'])) {
559
-            $this->_default_route_query_args['wp_referer'] = $this->_req_data['wp_referer'];
560
-        }
561
-        //for caffeinated and other extended functionality.
562
-        //  If there is a _extend_page_config method
563
-        // then let's run that to modify the all the various page configuration arrays
564
-        if (method_exists($this, '_extend_page_config')) {
565
-            $this->_extend_page_config();
566
-        }
567
-        //for CPT and other extended functionality.
568
-        // If there is an _extend_page_config_for_cpt
569
-        // then let's run that to modify all the various page configuration arrays.
570
-        if (method_exists($this, '_extend_page_config_for_cpt')) {
571
-            $this->_extend_page_config_for_cpt();
572
-        }
573
-        //filter routes and page_config so addons can add their stuff. Filtering done per class
574
-        $this->_page_routes = apply_filters(
575
-            'FHEE__' . get_class($this) . '__page_setup__page_routes',
576
-            $this->_page_routes,
577
-            $this
578
-        );
579
-        $this->_page_config = apply_filters(
580
-            'FHEE__' . get_class($this) . '__page_setup__page_config',
581
-            $this->_page_config,
582
-            $this
583
-        );
584
-        //if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
585
-        // then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
586
-        if (
587
-            method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)
588
-        ) {
589
-            add_action(
590
-                'AHEE__EE_Admin_Page__route_admin_request',
591
-                array($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view),
592
-                10,
593
-                2
594
-            );
595
-        }
596
-        //next route only if routing enabled
597
-        if ($this->_routing && ! defined('DOING_AJAX')) {
598
-            $this->_verify_routes();
599
-            //next let's just check user_access and kill if no access
600
-            $this->check_user_access();
601
-            if ($this->_is_UI_request) {
602
-                //admin_init stuff - global, all views for this page class, specific view
603
-                add_action('admin_init', array($this, 'admin_init'), 10);
604
-                if (method_exists($this, 'admin_init_' . $this->_current_view)) {
605
-                    add_action('admin_init', array($this, 'admin_init_' . $this->_current_view), 15);
606
-                }
607
-            } else {
608
-                //hijack regular WP loading and route admin request immediately
609
-                @ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
610
-                $this->route_admin_request();
611
-            }
612
-        }
613
-    }
614
-
615
-
616
-
617
-    /**
618
-     * Provides a way for related child admin pages to load stuff on the loaded admin page.
619
-     *
620
-     * @return void
621
-     * @throws ReflectionException
622
-     * @throws EE_Error
623
-     */
624
-    private function _do_other_page_hooks()
625
-    {
626
-        $registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, array());
627
-        foreach ($registered_pages as $page) {
628
-            //now let's setup the file name and class that should be present
629
-            $classname = str_replace('.class.php', '', $page);
630
-            //autoloaders should take care of loading file
631
-            if (! class_exists($classname)) {
632
-                $error_msg[] = sprintf(
633
-                    esc_html__(
634
-                        'Something went wrong with loading the %s admin hooks page.',
635
-                        'event_espresso'
636
-                    ),
637
-                    $page
638
-                );
639
-                $error_msg[] = $error_msg[0]
640
-                               . "\r\n"
641
-                               . sprintf(
642
-                                   esc_html__(
643
-                                       'There is no class in place for the %1$s admin hooks page.%2$sMake sure you have %3$s defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class',
644
-                                       'event_espresso'
645
-                                   ),
646
-                                   $page,
647
-                                   '<br />',
648
-                                   '<strong>' . $classname . '</strong>'
649
-                               );
650
-                throw new EE_Error(implode('||', $error_msg));
651
-            }
652
-            $a = new ReflectionClass($classname);
653
-            //notice we are passing the instance of this class to the hook object.
654
-            $hookobj[] = $a->newInstance($this);
655
-        }
656
-    }
657
-
658
-
659
-
660
-    public function load_page_dependencies()
661
-    {
662
-        try {
663
-            $this->_load_page_dependencies();
664
-        } catch (EE_Error $e) {
665
-            $e->get_error();
666
-        }
667
-    }
668
-
669
-
670
-
671
-    /**
672
-     * load_page_dependencies
673
-     * loads things specific to this page class when its loaded.  Really helps with efficiency.
674
-     *
675
-     * @return void
676
-     * @throws DomainException
677
-     * @throws EE_Error
678
-     * @throws InvalidArgumentException
679
-     * @throws InvalidDataTypeException
680
-     * @throws InvalidInterfaceException
681
-     * @throws ReflectionException
682
-     */
683
-    protected function _load_page_dependencies()
684
-    {
685
-        //let's set the current_screen and screen options to override what WP set
686
-        $this->_current_screen = get_current_screen();
687
-        //load admin_notices - global, page class, and view specific
688
-        add_action('admin_notices', array($this, 'admin_notices_global'), 5);
689
-        add_action('admin_notices', array($this, 'admin_notices'), 10);
690
-        if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
691
-            add_action('admin_notices', array($this, 'admin_notices_' . $this->_current_view), 15);
692
-        }
693
-        //load network admin_notices - global, page class, and view specific
694
-        add_action('network_admin_notices', array($this, 'network_admin_notices_global'), 5);
695
-        if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
696
-            add_action('network_admin_notices', array($this, 'network_admin_notices_' . $this->_current_view));
697
-        }
698
-        //this will save any per_page screen options if they are present
699
-        $this->_set_per_page_screen_options();
700
-        //setup list table properties
701
-        $this->_set_list_table();
702
-        // child classes can "register" a metabox to be automatically handled via the _page_config array property.
703
-        // However in some cases the metaboxes will need to be added within a route handling callback.
704
-        $this->_add_registered_meta_boxes();
705
-        $this->_add_screen_columns();
706
-        //add screen options - global, page child class, and view specific
707
-        $this->_add_global_screen_options();
708
-        $this->_add_screen_options();
709
-        $add_screen_options  = "_add_screen_options_{$this->_current_view}";
710
-        if (method_exists($this, $add_screen_options )) {
711
-            $this->{$add_screen_options}();
712
-        }
713
-        //add help tab(s) and tours- set via page_config and qtips.
714
-        $this->_add_help_tour();
715
-        $this->_add_help_tabs();
716
-        $this->_add_qtips();
717
-        //add feature_pointers - global, page child class, and view specific
718
-        $this->_add_feature_pointers();
719
-        $this->_add_global_feature_pointers();
720
-        $add_feature_pointer = "_add_feature_pointer_{$this->_current_view}";
721
-        if (method_exists($this, $add_feature_pointer )) {
722
-            $this->{$add_feature_pointer}();
723
-        }
724
-        //enqueue scripts/styles - global, page class, and view specific
725
-        add_action('admin_enqueue_scripts', array($this, 'load_global_scripts_styles'), 5);
726
-        add_action('admin_enqueue_scripts', array($this, 'load_scripts_styles'), 10);
727
-        if (method_exists($this, "load_scripts_styles_{$this->_current_view}")) {
728
-            add_action('admin_enqueue_scripts', array($this, "load_scripts_styles_{$this->_current_view}"), 15);
729
-        }
730
-        add_action('admin_enqueue_scripts', array($this, 'admin_footer_scripts_eei18n_js_strings'), 100);
731
-        // admin_print_footer_scripts - global, page child class, and view specific.
732
-        // NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.
733
-        // In most cases that's doing_it_wrong().  But adding hidden container elements etc.
734
-        // is a good use case. Notice the late priority we're giving these
735
-        add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts_global'), 99);
736
-        add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts'), 100);
737
-        if (method_exists($this, "admin_footer_scripts_{$this->_current_view}")) {
738
-            add_action('admin_print_footer_scripts', array($this, "admin_footer_scripts_{$this->_current_view}"), 101);
739
-        }
740
-        //admin footer scripts
741
-        add_action('admin_footer', array($this, 'admin_footer_global'), 99);
742
-        add_action('admin_footer', array($this, 'admin_footer'), 100);
743
-        if (method_exists($this, "admin_footer_{$this->_current_view}")) {
744
-            add_action('admin_footer', array($this, "admin_footer_{$this->_current_view}"), 101);
745
-        }
746
-        do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
747
-        //targeted hook
748
-        do_action(
749
-            "FHEE__EE_Admin_Page___load_page_dependencies__after_load__{$this->page_slug}__{$this->_req_action}"
750
-
751
-        );
752
-    }
753
-
754
-
755
-
756
-    /**
757
-     * _set_defaults
758
-     * This sets some global defaults for class properties.
759
-     */
760
-    private function _set_defaults()
761
-    {
762
-        $this->_current_screen = $this->_admin_page_title = $this->_req_action = $this->_req_nonce = null;
763
-        $this->_event = $this->_template_path = $this->_column_template_path = null;
764
-        $this->_nav_tabs = $this->_views = $this->_page_routes = array();
765
-        $this->_page_config = $this->_default_route_query_args = array();
766
-        $this->_default_nav_tab_name = 'overview';
767
-        //init template args
768
-        $this->_template_args = array(
769
-            'admin_page_header'  => '',
770
-            'admin_page_content' => '',
771
-            'post_body_content'  => '',
772
-            'before_list_table'  => '',
773
-            'after_list_table'   => '',
774
-        );
775
-    }
776
-
777
-
778
-
779
-    /**
780
-     * route_admin_request
781
-     *
782
-     * @see    _route_admin_request()
783
-     * @return exception|void error
784
-     * @throws InvalidArgumentException
785
-     * @throws InvalidInterfaceException
786
-     * @throws InvalidDataTypeException
787
-     * @throws EE_Error
788
-     * @throws ReflectionException
789
-     */
790
-    public function route_admin_request()
791
-    {
792
-        try {
793
-            $this->_route_admin_request();
794
-        } catch (EE_Error $e) {
795
-            $e->get_error();
796
-        }
797
-    }
798
-
799
-
800
-
801
-    public function set_wp_page_slug($wp_page_slug)
802
-    {
803
-        $this->_wp_page_slug = $wp_page_slug;
804
-        //if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
805
-        if (is_network_admin()) {
806
-            $this->_wp_page_slug .= '-network';
807
-        }
808
-    }
809
-
810
-
811
-
812
-    /**
813
-     * _verify_routes
814
-     * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so
815
-     * we know if we need to drop out.
816
-     *
817
-     * @return bool
818
-     * @throws EE_Error
819
-     */
820
-    protected function _verify_routes()
821
-    {
822
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
823
-        if (! $this->_current_page && ! defined('DOING_AJAX')) {
824
-            return false;
825
-        }
826
-        $this->_route = false;
827
-        // check that the page_routes array is not empty
828
-        if (empty($this->_page_routes)) {
829
-            // user error msg
830
-            $error_msg = sprintf(
831
-                esc_html__('No page routes have been set for the %s admin page.', 'event_espresso'),
832
-                $this->_admin_page_title
833
-            );
834
-            // developer error msg
835
-            $error_msg .= '||' . $error_msg . esc_html__(
836
-                ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
837
-                'event_espresso'
838
-            );
839
-            throw new EE_Error($error_msg);
840
-        }
841
-        // and that the requested page route exists
842
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
843
-            $this->_route        = $this->_page_routes[$this->_req_action];
844
-            $this->_route_config = isset($this->_page_config[$this->_req_action])
845
-                ? $this->_page_config[$this->_req_action] : array();
846
-        } else {
847
-            // user error msg
848
-            $error_msg = sprintf(
849
-                esc_html__(
850
-                        'The requested page route does not exist for the %s admin page.',
851
-                        'event_espresso'
852
-                ),
853
-                $this->_admin_page_title
854
-            );
855
-            // developer error msg
856
-            $error_msg .= '||' . $error_msg . sprintf(
857
-                    esc_html__(
858
-                        ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
859
-                        'event_espresso'
860
-                    ),
861
-                    $this->_req_action
862
-                );
863
-            throw new EE_Error($error_msg);
864
-        }
865
-        // and that a default route exists
866
-        if (! array_key_exists('default', $this->_page_routes)) {
867
-            // user error msg
868
-            $error_msg = sprintf(
869
-                esc_html__(
870
-                        'A default page route has not been set for the % admin page.',
871
-                        'event_espresso'
872
-                ),
873
-                $this->_admin_page_title
874
-            );
875
-            // developer error msg
876
-            $error_msg .= '||' . $error_msg . esc_html__(
877
-                ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
878
-                'event_espresso'
879
-            );
880
-            throw new EE_Error($error_msg);
881
-        }
882
-        //first lets' catch if the UI request has EVER been set.
883
-        if ($this->_is_UI_request === null) {
884
-            //lets set if this is a UI request or not.
885
-            $this->_is_UI_request = ! isset($this->_req_data['noheader']) || $this->_req_data['noheader'] !== true;
886
-            //wait a minute... we might have a noheader in the route array
887
-            $this->_is_UI_request = is_array($this->_route)
888
-                                    && isset($this->_route['noheader'])
889
-                                    && $this->_route['noheader'] ? false : $this->_is_UI_request;
890
-        }
891
-        $this->_set_current_labels();
892
-        return true;
893
-    }
894
-
895
-
896
-
897
-    /**
898
-     * this method simply verifies a given route and makes sure its an actual route available for the loaded page
899
-     *
900
-     * @param  string $route the route name we're verifying
901
-     * @return mixed (bool|Exception)      we'll throw an exception if this isn't a valid route.
902
-     * @throws EE_Error
903
-     */
904
-    protected function _verify_route($route)
905
-    {
906
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
907
-            return true;
908
-        }
909
-        // user error msg
910
-        $error_msg = sprintf(
911
-            esc_html__('The given page route does not exist for the %s admin page.', 'event_espresso'),
912
-            $this->_admin_page_title
913
-        );
914
-        // developer error msg
915
-        $error_msg .= '||' . $error_msg . sprintf(
916
-                esc_html__(
917
-                    ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
918
-                    'event_espresso'
919
-                ),
920
-                $route
921
-            );
922
-        throw new EE_Error($error_msg);
923
-    }
924
-
925
-
926
-
927
-    /**
928
-     * perform nonce verification
929
-     * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces
930
-     * using this method (and save retyping!)
931
-     *
932
-     * @param  string $nonce     The nonce sent
933
-     * @param  string $nonce_ref The nonce reference string (name0)
934
-     * @return void
935
-     * @throws EE_Error
936
-     */
937
-    protected function _verify_nonce($nonce, $nonce_ref)
938
-    {
939
-        // verify nonce against expected value
940
-        if (! wp_verify_nonce($nonce, $nonce_ref)) {
941
-            // these are not the droids you are looking for !!!
942
-            $msg = sprintf(
943
-                esc_html__('%sNonce Fail.%s', 'event_espresso'),
944
-                '<a href="http://www.youtube.com/watch?v=56_S0WeTkzs">',
945
-                '</a>'
946
-            );
947
-            if (WP_DEBUG) {
948
-                $msg .= "\n  " . sprintf(
949
-                        esc_html__(
950
-                            'In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!',
951
-                            'event_espresso'
952
-                        ),
953
-                        __CLASS__
954
-                    );
955
-            }
956
-            if (! defined('DOING_AJAX')) {
957
-                wp_die($msg);
958
-            } else {
959
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
960
-                $this->_return_json();
961
-            }
962
-        }
963
-    }
964
-
965
-
966
-
967
-    /**
968
-     * _route_admin_request()
969
-     * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if theres are
970
-     * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
971
-     * in the page routes and then will try to load the corresponding method.
972
-     *
973
-     * @return void
974
-     * @throws EE_Error
975
-     * @throws InvalidArgumentException
976
-     * @throws InvalidDataTypeException
977
-     * @throws InvalidInterfaceException
978
-     * @throws ReflectionException
979
-     */
980
-    protected function _route_admin_request()
981
-    {
982
-        if (! $this->_is_UI_request) {
983
-            $this->_verify_routes();
984
-        }
985
-        $nonce_check = isset($this->_route_config['require_nonce'])
986
-            ? $this->_route_config['require_nonce']
987
-            : true;
988
-        if ($this->_req_action !== 'default' && $nonce_check) {
989
-            // set nonce from post data
990
-            $nonce = isset($this->_req_data[$this->_req_nonce])
991
-                ? sanitize_text_field($this->_req_data[$this->_req_nonce])
992
-                : '';
993
-            $this->_verify_nonce($nonce, $this->_req_nonce);
994
-        }
995
-        //set the nav_tabs array but ONLY if this is  UI_request
996
-        if ($this->_is_UI_request) {
997
-            $this->_set_nav_tabs();
998
-        }
999
-        // grab callback function
1000
-        $func = is_array($this->_route) ? $this->_route['func'] : $this->_route;
1001
-        // check if callback has args
1002
-        $args      = is_array($this->_route) && isset($this->_route['args']) ? $this->_route['args'] : array();
1003
-        $error_msg = '';
1004
-        // action right before calling route
1005
-        // (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1006
-        if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1007
-            do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1008
-        }
1009
-        // right before calling the route, let's remove _wp_http_referer from the
1010
-        // $_SERVER[REQUEST_URI] global (its now in _req_data for route processing).
1011
-        $_SERVER['REQUEST_URI'] = remove_query_arg(
1012
-                '_wp_http_referer',
1013
-                wp_unslash($_SERVER['REQUEST_URI'])
1014
-        );
1015
-        if (! empty($func)) {
1016
-            if (is_array($func)) {
1017
-                list($class, $method) = $func;
1018
-            } elseif (strpos($func, '::') !== false) {
1019
-                list($class, $method) = explode('::', $func);
1020
-            } else {
1021
-                $class  = $this;
1022
-                $method = $func;
1023
-            }
1024
-            if (! (is_object($class) && $class === $this)) {
1025
-                // send along this admin page object for access by addons.
1026
-                $args['admin_page_object'] = $this;
1027
-            }
1028
-            if (
1029
-                //is it a method on a class that doesn't work?
1030
-                (
1031
-                    (
1032
-                        method_exists($class, $method)
1033
-                        && call_user_func_array(array($class, $method), $args) === false
1034
-                    )
1035
-                    && (
1036
-                        //is it a standalone function that doesn't work?
1037
-                        function_exists($method)
1038
-                        && call_user_func_array(
1039
-                            $func,
1040
-                            array_merge(array('admin_page_object' => $this), $args)
1041
-                           ) === false
1042
-                    )
1043
-                )
1044
-                || (
1045
-                    //is it neither a class method NOR a standalone function?
1046
-                    ! method_exists($class, $method)
1047
-                    && ! function_exists($method)
1048
-                )
1049
-            ) {
1050
-                // user error msg
1051
-                $error_msg = esc_html__(
1052
-                    'An error occurred. The  requested page route could not be found.',
1053
-                    'event_espresso'
1054
-                );
1055
-                // developer error msg
1056
-                $error_msg .= '||';
1057
-                $error_msg .= sprintf(
1058
-                    esc_html__(
1059
-                        'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
1060
-                        'event_espresso'
1061
-                    ),
1062
-                    $method
1063
-                );
1064
-            }
1065
-            if (! empty($error_msg)) {
1066
-                throw new EE_Error($error_msg);
1067
-            }
1068
-        }
1069
-        // if we've routed and this route has a no headers route AND a sent_headers_route,
1070
-        // then we need to reset the routing properties to the new route.
1071
-        //now if UI request is FALSE and noheader is true AND we have a headers_sent_route in the route array then let's set UI_request to true because the no header route has a second func after headers have been sent.
1072
-        if ($this->_is_UI_request === false
1073
-            && is_array($this->_route)
1074
-            && ! empty($this->_route['headers_sent_route'])
1075
-        ) {
1076
-            $this->_reset_routing_properties($this->_route['headers_sent_route']);
1077
-        }
1078
-    }
1079
-
1080
-
1081
-
1082
-    /**
1083
-     * This method just allows the resetting of page properties in the case where a no headers
1084
-     * route redirects to a headers route in its route config.
1085
-     *
1086
-     * @since   4.3.0
1087
-     * @param  string $new_route New (non header) route to redirect to.
1088
-     * @return   void
1089
-     * @throws ReflectionException
1090
-     * @throws InvalidArgumentException
1091
-     * @throws InvalidInterfaceException
1092
-     * @throws InvalidDataTypeException
1093
-     * @throws EE_Error
1094
-     */
1095
-    protected function _reset_routing_properties($new_route)
1096
-    {
1097
-        $this->_is_UI_request = true;
1098
-        //now we set the current route to whatever the headers_sent_route is set at
1099
-        $this->_req_data['action'] = $new_route;
1100
-        //rerun page setup
1101
-        $this->_page_setup();
1102
-    }
1103
-
1104
-
1105
-
1106
-    /**
1107
-     * _add_query_arg
1108
-     * adds nonce to array of arguments then calls WP add_query_arg function
1109
-     *(internally just uses EEH_URL's function with the same name)
1110
-     *
1111
-     * @param array  $args
1112
-     * @param string $url
1113
-     * @param bool   $sticky                  if true, then the existing Request params will be appended to the
1114
-     *                                        generated url in an associative array indexed by the key 'wp_referer';
1115
-     *                                        Example usage: If the current page is:
1116
-     *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
1117
-     *                                        &action=default&event_id=20&month_range=March%202015
1118
-     *                                        &_wpnonce=5467821
1119
-     *                                        and you call:
1120
-     *                                        EE_Admin_Page::add_query_args_and_nonce(
1121
-     *                                        array(
1122
-     *                                        'action' => 'resend_something',
1123
-     *                                        'page=>espresso_registrations'
1124
-     *                                        ),
1125
-     *                                        $some_url,
1126
-     *                                        true
1127
-     *                                        );
1128
-     *                                        It will produce a url in this structure:
1129
-     *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
1130
-     *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
1131
-     *                                        month_range]=March%202015
1132
-     * @param   bool $exclude_nonce           If true, the the nonce will be excluded from the generated nonce.
1133
-     * @return string
1134
-     */
1135
-    public static function add_query_args_and_nonce(
1136
-        $args = array(),
1137
-        $url = false,
1138
-        $sticky = false,
1139
-        $exclude_nonce = false
1140
-    ) {
1141
-        //if there is a _wp_http_referer include the values from the request but only if sticky = true
1142
-        if ($sticky) {
1143
-            $request = $_REQUEST;
1144
-            unset($request['_wp_http_referer']);
1145
-            unset($request['wp_referer']);
1146
-            foreach ($request as $key => $value) {
1147
-                //do not add nonces
1148
-                if (strpos($key, 'nonce') !== false) {
1149
-                    continue;
1150
-                }
1151
-                $args['wp_referer[' . $key . ']'] = $value;
1152
-            }
1153
-        }
1154
-        return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
1155
-    }
1156
-
1157
-
1158
-
1159
-    /**
1160
-     * This returns a generated link that will load the related help tab.
1161
-     *
1162
-     * @param  string $help_tab_id the id for the connected help tab
1163
-     * @param  string $icon_style  (optional) include css class for the style you want to use for the help icon.
1164
-     * @param  string $help_text   (optional) send help text you want to use for the link if default not to be used
1165
-     * @uses EEH_Template::get_help_tab_link()
1166
-     * @return string              generated link
1167
-     */
1168
-    protected function _get_help_tab_link($help_tab_id, $icon_style = '', $help_text = '')
1169
-    {
1170
-        return EEH_Template::get_help_tab_link(
1171
-            $help_tab_id,
1172
-            $this->page_slug,
1173
-            $this->_req_action,
1174
-            $icon_style,
1175
-            $help_text
1176
-        );
1177
-    }
1178
-
1179
-
1180
-
1181
-    /**
1182
-     * _add_help_tabs
1183
-     * Note child classes define their help tabs within the page_config array.
1184
-     *
1185
-     * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1186
-     * @return void
1187
-     * @throws DomainException
1188
-     * @throws EE_Error
1189
-     */
1190
-    protected function _add_help_tabs()
1191
-    {
1192
-        $tour_buttons = '';
1193
-        if (isset($this->_page_config[$this->_req_action])) {
1194
-            $config = $this->_page_config[$this->_req_action];
1195
-            //is there a help tour for the current route?  if there is let's setup the tour buttons
1196
-            if (isset($this->_help_tour[$this->_req_action])) {
1197
-                $tb           = array();
1198
-                $tour_buttons = '<div class="ee-abs-container"><div class="ee-help-tour-restart-buttons">';
1199
-                foreach ($this->_help_tour['tours'] as $tour) {
1200
-                    //if this is the end tour then we don't need to setup a button
1201
-                    if ($tour instanceof EE_Help_Tour_final_stop || ! $tour instanceof EE_Help_Tour) {
1202
-                        continue;
1203
-                    }
1204
-                    $tb[] = '<button id="trigger-tour-'
1205
-                            . $tour->get_slug()
1206
-                            . '" class="button-primary trigger-ee-help-tour">'
1207
-                            . $tour->get_label()
1208
-                            . '</button>';
1209
-                }
1210
-                $tour_buttons .= implode('<br />', $tb);
1211
-                $tour_buttons .= '</div></div>';
1212
-            }
1213
-            // let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1214
-            if (is_array($config) && isset($config['help_sidebar'])) {
1215
-                //check that the callback given is valid
1216
-                if (! method_exists($this, $config['help_sidebar'])) {
1217
-                    throw new EE_Error(
1218
-                        sprintf(
1219
-                            esc_html__(
1220
-                                'The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Doublecheck the spelling and make sure this method exists for the class %s',
1221
-                                'event_espresso'
1222
-                            ),
1223
-                            $config['help_sidebar'],
1224
-                            get_class($this)
1225
-                        )
1226
-                    );
1227
-                }
1228
-                $content = apply_filters(
1229
-                    'FHEE__' . get_class($this) . '__add_help_tabs__help_sidebar',
1230
-                    $this->{$config['help_sidebar']}()
1231
-                );
1232
-                $content .= $tour_buttons; //add help tour buttons.
1233
-                //do we have any help tours setup?  Cause if we do we want to add the buttons
1234
-                $this->_current_screen->set_help_sidebar($content);
1235
-            }
1236
-            //if we DON'T have config help sidebar and there ARE tour buttons then we'll just add the tour buttons to the sidebar.
1237
-            if (! isset($config['help_sidebar']) && ! empty($tour_buttons)) {
1238
-                $this->_current_screen->set_help_sidebar($tour_buttons);
1239
-            }
1240
-            //handle if no help_tabs are set so the sidebar will still show for the help tour buttons
1241
-            if (! isset($config['help_tabs']) && ! empty($tour_buttons)) {
1242
-                $_ht['id']      = $this->page_slug;
1243
-                $_ht['title']   = esc_html__('Help Tours', 'event_espresso');
1244
-                $_ht['content'] = '<p>' . esc_html__(
1245
-                        'The buttons to the right allow you to start/restart any help tours available for this page',
1246
-                        'event_espresso'
1247
-                    ) . '</p>';
1248
-                $this->_current_screen->add_help_tab($_ht);
1249
-            }
1250
-            if (! isset($config['help_tabs'])) {
1251
-                return;
1252
-            } //no help tabs for this route
1253
-            foreach ((array)$config['help_tabs'] as $tab_id => $cfg) {
1254
-                //we're here so there ARE help tabs!
1255
-                //make sure we've got what we need
1256
-                if (! isset($cfg['title'])) {
1257
-                    throw new EE_Error(
1258
-                        esc_html__(
1259
-                            'The _page_config array is not set up properly for help tabs.  It is missing a title',
1260
-                            'event_espresso'
1261
-                        )
1262
-                    );
1263
-                }
1264
-                if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1265
-                    throw new EE_Error(
1266
-                        esc_html__(
1267
-                            'The _page_config array is not setup properly for help tabs. It is missing a either a filename reference, or a callback reference or a content reference so there is no way to know the content for the help tab',
1268
-                            'event_espresso'
1269
-                        )
1270
-                    );
1271
-                }
1272
-                //first priority goes to content.
1273
-                if (! empty($cfg['content'])) {
1274
-                    $content = ! empty($cfg['content']) ? $cfg['content'] : null;
1275
-                    //second priority goes to filename
1276
-                } elseif (! empty($cfg['filename'])) {
1277
-                    $file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1278
-                    //it's possible that the file is located on decaf route (and above sets up for caf route, if this is the case then lets check decaf route too)
1279
-                    $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1280
-                                                             . basename($this->_get_dir())
1281
-                                                             . '/help_tabs/'
1282
-                                                             . $cfg['filename']
1283
-                                                             . '.help_tab.php' : $file_path;
1284
-                    //if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1285
-                    if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1286
-                        EE_Error::add_error(
1287
-                            sprintf(
1288
-                                esc_html__(
1289
-                                    'The filename given for the help tab %s is not a valid file and there is no other configuration for the tab content.  Please check that the string you set for the help tab on this route (%s) is the correct spelling.  The file should be in %s',
1290
-                                    'event_espresso'
1291
-                                ),
1292
-                                $tab_id,
1293
-                                key($config),
1294
-                                $file_path
1295
-                            ),
1296
-                            __FILE__,
1297
-                            __FUNCTION__,
1298
-                            __LINE__
1299
-                        );
1300
-                        return;
1301
-                    }
1302
-                    $template_args['admin_page_obj'] = $this;
1303
-                    $content = EEH_Template::display_template(
1304
-                        $file_path,
1305
-                        $template_args,
1306
-                        true
1307
-                    );
1308
-                } else {
1309
-                    $content = '';
1310
-                }
1311
-                //check if callback is valid
1312
-                if (
1313
-                    empty($content) && (
1314
-                        ! isset($cfg['callback']) || ! method_exists($this, $cfg['callback'])
1315
-                    )
1316
-                ) {
1317
-                    EE_Error::add_error(
1318
-                        sprintf(
1319
-                            esc_html__(
1320
-                                'The callback given for a %s help tab on this page does not content OR a corresponding method for generating the content.  Check the spelling or make sure the method is present.',
1321
-                                'event_espresso'
1322
-                            ),
1323
-                            $cfg['title']
1324
-                        ),
1325
-                        __FILE__,
1326
-                        __FUNCTION__,
1327
-                        __LINE__
1328
-                    );
1329
-                    return;
1330
-                }
1331
-                //setup config array for help tab method
1332
-                $id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1333
-                $_ht = array(
1334
-                    'id'       => $id,
1335
-                    'title'    => $cfg['title'],
1336
-                    'callback' => isset($cfg['callback']) && empty($content) ? array($this, $cfg['callback']) : null,
1337
-                    'content'  => $content,
1338
-                );
1339
-                $this->_current_screen->add_help_tab($_ht);
1340
-            }
1341
-        }
1342
-    }
1343
-
1344
-
1345
-
1346
-    /**
1347
-     * This basically checks loaded $_page_config property to see if there are any help_tours defined.  "help_tours" is
1348
-     * an array with properties for setting up usage of the joyride plugin
1349
-     *
1350
-     * @link   http://zurb.com/playground/jquery-joyride-feature-tour-plugin
1351
-     * @see    instructions regarding the format and construction of the "help_tour" array element is found in the
1352
-     *         _set_page_config() comments
1353
-     * @return void
1354
-     * @throws EE_Error
1355
-     * @throws InvalidArgumentException
1356
-     * @throws InvalidDataTypeException
1357
-     * @throws InvalidInterfaceException
1358
-     */
1359
-    protected function _add_help_tour()
1360
-    {
1361
-        $tours            = array();
1362
-        $this->_help_tour = array();
1363
-        //exit early if help tours are turned off globally
1364
-        if ((defined('EE_DISABLE_HELP_TOURS') && EE_DISABLE_HELP_TOURS)
1365
-            || ! EE_Registry::instance()->CFG->admin->help_tour_activation
1366
-        ) {
1367
-            return;
1368
-        }
1369
-        //loop through _page_config to find any help_tour defined
1370
-        foreach ($this->_page_config as $route => $config) {
1371
-            //we're only going to set things up for this route
1372
-            if ($route !== $this->_req_action) {
1373
-                continue;
1374
-            }
1375
-            if (isset($config['help_tour'])) {
1376
-                foreach ($config['help_tour'] as $tour) {
1377
-                    $file_path = $this->_get_dir() . '/help_tours/' . $tour . '.class.php';
1378
-                    // let's see if we can get that file...
1379
-                    // if not its possible this is a decaf route not set in caffeinated
1380
-                    // so lets try and get the caffeinated equivalent
1381
-                    $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1382
-                                                             . basename($this->_get_dir())
1383
-                                                             . '/help_tours/'
1384
-                                                             . $tour
1385
-                                                             . '.class.php' : $file_path;
1386
-                    //if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1387
-                    if (! is_readable($file_path)) {
1388
-                        EE_Error::add_error(
1389
-                            sprintf(
1390
-                                esc_html__(
1391
-                                    'The file path given for the help tour (%s) is not a valid path.  Please check that the string you set for the help tour on this route (%s) is the correct spelling',
1392
-                                    'event_espresso'
1393
-                                ),
1394
-                                $file_path,
1395
-                                $tour
1396
-                            ),
1397
-                            __FILE__,
1398
-                            __FUNCTION__,
1399
-                            __LINE__
1400
-                        );
1401
-                        return;
1402
-                    }
1403
-                    require_once $file_path;
1404
-                    if (! class_exists($tour)) {
1405
-                        $error_msg[] = sprintf(
1406
-                            esc_html__('Something went wrong with loading the %s Help Tour Class.', 'event_espresso'),
1407
-                            $tour
1408
-                        );
1409
-                        $error_msg[] = $error_msg[0] . "\r\n" . sprintf(
1410
-                                esc_html__(
1411
-                                    'There is no class in place for the %s help tour.%s Make sure you have <strong>%s</strong> defined in the "help_tour" array for the %s route of the % admin page.',
1412
-                                    'event_espresso'
1413
-                                ),
1414
-                                $tour,
1415
-                                '<br />',
1416
-                                $tour,
1417
-                                $this->_req_action,
1418
-                                get_class($this)
1419
-                            );
1420
-                        throw new EE_Error(implode('||', $error_msg));
1421
-                    }
1422
-                    $tour_obj                   = new $tour($this->_is_caf);
1423
-                    $tours[]                    = $tour_obj;
1424
-                    $this->_help_tour[$route][] = EEH_Template::help_tour_stops_generator($tour_obj);
1425
-                }
1426
-                //let's inject the end tour stop element common to all pages... this will only get seen once per machine.
1427
-                $end_stop_tour              = new EE_Help_Tour_final_stop($this->_is_caf);
1428
-                $tours[]                    = $end_stop_tour;
1429
-                $this->_help_tour[$route][] = EEH_Template::help_tour_stops_generator($end_stop_tour);
1430
-            }
1431
-        }
1432
-        if (! empty($tours)) {
1433
-            $this->_help_tour['tours'] = $tours;
1434
-        }
1435
-        // that's it!  Now that the $_help_tours property is set (or not)
1436
-        // the scripts and html should be taken care of automatically.
1437
-    }
1438
-
1439
-
1440
-
1441
-    /**
1442
-     * This simply sets up any qtips that have been defined in the page config
1443
-     *
1444
-     * @return void
1445
-     */
1446
-    protected function _add_qtips()
1447
-    {
1448
-        if (isset($this->_route_config['qtips'])) {
1449
-            $qtips = (array)$this->_route_config['qtips'];
1450
-            //load qtip loader
1451
-            $path = array(
1452
-                $this->_get_dir() . '/qtips/',
1453
-                EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1454
-            );
1455
-            EEH_Qtip_Loader::instance()->register($qtips, $path);
1456
-        }
1457
-    }
1458
-
1459
-
1460
-
1461
-    /**
1462
-     * _set_nav_tabs
1463
-     * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you
1464
-     * wish to add additional tabs or modify accordingly.
1465
-     *
1466
-     * @return void
1467
-     * @throws InvalidArgumentException
1468
-     * @throws InvalidInterfaceException
1469
-     * @throws InvalidDataTypeException
1470
-     */
1471
-    protected function _set_nav_tabs()
1472
-    {
1473
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1474
-        $i = 0;
1475
-        foreach ($this->_page_config as $slug => $config) {
1476
-            if (
1477
-                ! is_array($config)
1478
-                || (
1479
-                    is_array($config)
1480
-                    && (
1481
-                        (isset($config['nav']) && ! $config['nav'])
1482
-                        || ! isset($config['nav'])
1483
-                    )
1484
-                )
1485
-            ) {
1486
-                continue;
1487
-            }
1488
-            //no nav tab for this config
1489
-            //check for persistent flag
1490
-            if ($slug !== $this->_req_action && isset($config['nav']['persistent']) && ! $config['nav']['persistent']) {
1491
-                // nav tab is only to appear when route requested.
1492
-                continue;
1493
-            }
1494
-            if (! $this->check_user_access($slug, true)) {
1495
-                // no nav tab because current user does not have access.
1496
-                continue;
1497
-            }
1498
-            $css_class              = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1499
-            $this->_nav_tabs[$slug] = array(
1500
-                'url'       => isset($config['nav']['url'])
1501
-                    ? $config['nav']['url']
1502
-                    : self::add_query_args_and_nonce(
1503
-                        array('action' => $slug),
1504
-                        $this->_admin_base_url
1505
-                    ),
1506
-                'link_text' => isset($config['nav']['label'])
1507
-                    ? $config['nav']['label']
1508
-                    : ucwords(
1509
-                        str_replace('_', ' ', $slug)
1510
-                    ),
1511
-                'css_class' => $this->_req_action === $slug ? $css_class . 'nav-tab-active' : $css_class,
1512
-                'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1513
-            );
1514
-            $i++;
1515
-        }
1516
-        //if $this->_nav_tabs is empty then lets set the default
1517
-        if (empty($this->_nav_tabs)) {
1518
-            $this->_nav_tabs[$this->_default_nav_tab_name] = array(
1519
-                'url'       => $this->_admin_base_url,
1520
-                'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1521
-                'css_class' => 'nav-tab-active',
1522
-                'order'     => 10,
1523
-            );
1524
-        }
1525
-        //now let's sort the tabs according to order
1526
-        usort($this->_nav_tabs, array($this, '_sort_nav_tabs'));
1527
-    }
1528
-
1529
-
1530
-
1531
-    /**
1532
-     * _set_current_labels
1533
-     * This method modifies the _labels property with any optional specific labels indicated in the _page_routes
1534
-     * property array
1535
-     *
1536
-     * @return void
1537
-     */
1538
-    private function _set_current_labels()
1539
-    {
1540
-        if (is_array($this->_route_config) && isset($this->_route_config['labels'])) {
1541
-            foreach ($this->_route_config['labels'] as $label => $text) {
1542
-                if (is_array($text)) {
1543
-                    foreach ($text as $sublabel => $subtext) {
1544
-                        $this->_labels[$label][$sublabel] = $subtext;
1545
-                    }
1546
-                } else {
1547
-                    $this->_labels[$label] = $text;
1548
-                }
1549
-            }
1550
-        }
1551
-    }
1552
-
1553
-
1554
-
1555
-    /**
1556
-     *        verifies user access for this admin page
1557
-     *
1558
-     * @param string $route_to_check if present then the capability for the route matching this string is checked.
1559
-     * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just
1560
-     *                               return false if verify fail.
1561
-     * @return bool
1562
-     * @throws InvalidArgumentException
1563
-     * @throws InvalidDataTypeException
1564
-     * @throws InvalidInterfaceException
1565
-     */
1566
-    public function check_user_access($route_to_check = '', $verify_only = false)
1567
-    {
1568
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1569
-        $route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1570
-        $capability     = ! empty($route_to_check) && isset($this->_page_routes[$route_to_check])
1571
-                          && is_array(
1572
-                              $this->_page_routes[$route_to_check]
1573
-                          )
1574
-                          && ! empty($this->_page_routes[$route_to_check]['capability'])
1575
-            ? $this->_page_routes[$route_to_check]['capability'] : null;
1576
-        if (empty($capability) && empty($route_to_check)) {
1577
-            $capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options'
1578
-                : $this->_route['capability'];
1579
-        } else {
1580
-            $capability = empty($capability) ? 'manage_options' : $capability;
1581
-        }
1582
-        $id = is_array($this->_route) && ! empty($this->_route['obj_id']) ? $this->_route['obj_id'] : 0;
1583
-        if (
1584
-            ! defined('DOING_AJAX')
1585
-            && (
1586
-                ! function_exists('is_admin')
1587
-                || ! EE_Registry::instance()->CAP->current_user_can(
1588
-                    $capability,
1589
-                    $this->page_slug
1590
-                    . '_'
1591
-                    . $route_to_check,
1592
-                    $id
1593
-                )
1594
-            )
1595
-        ) {
1596
-            if ($verify_only) {
1597
-                return false;
1598
-            }
1599
-            if (is_user_logged_in()) {
1600
-                wp_die(__('You do not have access to this route.', 'event_espresso'));
1601
-            } else {
1602
-                return false;
1603
-            }
1604
-        }
1605
-        return true;
1606
-    }
1607
-
1608
-
1609
-
1610
-    /**
1611
-     * admin_init_global
1612
-     * This runs all the code that we want executed within the WP admin_init hook.
1613
-     * This method executes for ALL EE Admin pages.
1614
-     *
1615
-     * @return void
1616
-     */
1617
-    public function admin_init_global()
1618
-    {
1619
-    }
1620
-
1621
-
1622
-
1623
-    /**
1624
-     * wp_loaded_global
1625
-     * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an
1626
-     * EE_Admin page and will execute on every EE Admin Page load
1627
-     *
1628
-     * @return void
1629
-     */
1630
-    public function wp_loaded()
1631
-    {
1632
-    }
1633
-
1634
-
1635
-
1636
-    /**
1637
-     * admin_notices
1638
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on
1639
-     * ALL EE_Admin pages.
1640
-     *
1641
-     * @return void
1642
-     */
1643
-    public function admin_notices_global()
1644
-    {
1645
-        $this->_display_no_javascript_warning();
1646
-        $this->_display_espresso_notices();
1647
-    }
1648
-
1649
-
1650
-
1651
-    public function network_admin_notices_global()
1652
-    {
1653
-        $this->_display_no_javascript_warning();
1654
-        $this->_display_espresso_notices();
1655
-    }
1656
-
1657
-
1658
-
1659
-    /**
1660
-     * admin_footer_scripts_global
1661
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
1662
-     * will apply on ALL EE_Admin pages.
1663
-     *
1664
-     * @return void
1665
-     */
1666
-    public function admin_footer_scripts_global()
1667
-    {
1668
-        $this->_add_admin_page_ajax_loading_img();
1669
-        $this->_add_admin_page_overlay();
1670
-        //if metaboxes are present we need to add the nonce field
1671
-        if (
1672
-             isset($this->_route_config['metaboxes'])
1673
-             || isset($this->_route_config['list_table'])
1674
-             || (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes'])
1675
-        ) {
1676
-            wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1677
-            wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1678
-        }
1679
-    }
1680
-
1681
-
1682
-
1683
-    /**
1684
-     * admin_footer_global
1685
-     * Anything triggered by the wp 'admin_footer' wp hook should be put in here. This particular method will apply on
1686
-     * ALL EE_Admin Pages.
1687
-     *
1688
-     * @return void
1689
-     * @throws EE_Error
1690
-     */
1691
-    public function admin_footer_global()
1692
-    {
1693
-        //dialog container for dialog helper
1694
-        $d_cont = '<div class="ee-admin-dialog-container auto-hide hidden">' . "\n";
1695
-        $d_cont .= '<div class="ee-notices"></div>';
1696
-        $d_cont .= '<div class="ee-admin-dialog-container-inner-content"></div>';
1697
-        $d_cont .= '</div>';
1698
-        echo $d_cont;
1699
-        //help tour stuff?
1700
-        if (isset($this->_help_tour[$this->_req_action])) {
1701
-            echo implode('<br />', $this->_help_tour[$this->_req_action]);
1702
-        }
1703
-        //current set timezone for timezone js
1704
-        echo '<span id="current_timezone" class="hidden">' . EEH_DTT_Helper::get_timezone() . '</span>';
1705
-    }
1706
-
1707
-
1708
-
1709
-    /**
1710
-     * This function sees if there is a method for help popup content existing for the given route.  If there is then
1711
-     * we'll use the retrieved array to output the content using the template. For child classes: If you want to have
1712
-     * help popups then in your templates or your content you set "triggers" for the content using the
1713
-     * "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method
1714
-     * for the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup
1715
-     * method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content
1716
-     * for the
1717
-     * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined
1718
-     * "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1719
-     *    'help_trigger_id' => array(
1720
-     *        'title' => esc_html__('localized title for popup', 'event_espresso'),
1721
-     *        'content' => esc_html__('localized content for popup', 'event_espresso')
1722
-     *    )
1723
-     * );
1724
-     * Then the EE_Admin_Parent will take care of making sure that is setup properly on the correct route.
1725
-     *
1726
-     * @param array $help_array
1727
-     * @param bool  $display
1728
-     * @return string content
1729
-     * @throws DomainException
1730
-     * @throws EE_Error
1731
-     */
1732
-    protected function _set_help_popup_content($help_array = array(), $display = false)
1733
-    {
1734
-        $content       = '';
1735
-        $help_array    = empty($help_array) ? $this->_get_help_content() : $help_array;
1736
-        //loop through the array and setup content
1737
-        foreach ($help_array as $trigger => $help) {
1738
-            //make sure the array is setup properly
1739
-            if (! isset($help['title']) || ! isset($help['content'])) {
1740
-                throw new EE_Error(
1741
-                    esc_html__(
1742
-                        'Does not look like the popup content array has been setup correctly.  Might want to double check that.  Read the comments for the _get_help_popup_content method found in "EE_Admin_Page" class',
1743
-                        'event_espresso'
1744
-                    )
1745
-                );
1746
-            }
1747
-            //we're good so let'd setup the template vars and then assign parsed template content to our content.
1748
-            $template_args = array(
1749
-                'help_popup_id'      => $trigger,
1750
-                'help_popup_title'   => $help['title'],
1751
-                'help_popup_content' => $help['content'],
1752
-            );
1753
-            $content       .= EEH_Template::display_template(
1754
-                EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1755
-                $template_args,
1756
-                true
1757
-            );
1758
-        }
1759
-        if ($display) {
1760
-            echo $content;
1761
-            return '';
1762
-        }
1763
-        return $content;
1764
-    }
1765
-
1766
-
1767
-
1768
-    /**
1769
-     * All this does is retrieve the help content array if set by the EE_Admin_Page child
1770
-     *
1771
-     * @return array properly formatted array for help popup content
1772
-     * @throws EE_Error
1773
-     */
1774
-    private function _get_help_content()
1775
-    {
1776
-        //what is the method we're looking for?
1777
-        $method_name = '_help_popup_content_' . $this->_req_action;
1778
-        //if method doesn't exist let's get out.
1779
-        if (! method_exists($this, $method_name)) {
1780
-            return array();
1781
-        }
1782
-        //k we're good to go let's retrieve the help array
1783
-        $help_array = call_user_func(array($this, $method_name));
1784
-        //make sure we've got an array!
1785
-        if (! is_array($help_array)) {
1786
-            throw new EE_Error(
1787
-                esc_html__(
1788
-                    'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
1789
-                    'event_espresso'
1790
-                )
1791
-            );
1792
-        }
1793
-        return $help_array;
1794
-    }
1795
-
1796
-
1797
-
1798
-    /**
1799
-     * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1800
-     * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1801
-     * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1802
-     *
1803
-     * @param string  $trigger_id reference for retrieving the trigger content for the popup
1804
-     * @param boolean $display    if false then we return the trigger string
1805
-     * @param array   $dimensions an array of dimensions for the box (array(h,w))
1806
-     * @return string
1807
-     * @throws DomainException
1808
-     * @throws EE_Error
1809
-     */
1810
-    protected function _set_help_trigger($trigger_id, $display = true, $dimensions = array('400', '640'))
1811
-    {
1812
-        if (defined('DOING_AJAX')) {
1813
-            return '';
1814
-        }
1815
-        //let's check and see if there is any content set for this popup.  If there isn't then we'll include a default title and content so that developers know something needs to be corrected
1816
-        $help_array   = $this->_get_help_content();
1817
-        $help_content = '';
1818
-        if (empty($help_array) || ! isset($help_array[$trigger_id])) {
1819
-            $help_array[$trigger_id] = array(
1820
-                'title'   => esc_html__('Missing Content', 'event_espresso'),
1821
-                'content' => esc_html__(
1822
-                    'A trigger has been set that doesn\'t have any corresponding content. Make sure you have set the help content. (see the "_set_help_popup_content" method in the EE_Admin_Page for instructions.)',
1823
-                    'event_espresso'
1824
-                ),
1825
-            );
1826
-            $help_content            = $this->_set_help_popup_content($help_array, false);
1827
-        }
1828
-        //let's setup the trigger
1829
-        $content = '<a class="ee-dialog" href="?height='
1830
-                   . $dimensions[0]
1831
-                   . '&width='
1832
-                   . $dimensions[1]
1833
-                   . '&inlineId='
1834
-                   . $trigger_id
1835
-                   . '" target="_blank"><span class="question ee-help-popup-question"></span></a>';
1836
-        $content .= $help_content;
1837
-        if ($display) {
1838
-            echo $content;
1839
-            return  '';
1840
-        }
1841
-        return $content;
1842
-    }
1843
-
1844
-
1845
-
1846
-    /**
1847
-     * _add_global_screen_options
1848
-     * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1849
-     * This particular method will add_screen_options on ALL EE_Admin Pages
1850
-     *
1851
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1852
-     *         see also WP_Screen object documents...
1853
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1854
-     * @abstract
1855
-     * @return void
1856
-     */
1857
-    private function _add_global_screen_options()
1858
-    {
1859
-    }
1860
-
1861
-
1862
-
1863
-    /**
1864
-     * _add_global_feature_pointers
1865
-     * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1866
-     * This particular method will implement feature pointers for ALL EE_Admin pages.
1867
-     * Note: this is just a placeholder for now.  Implementation will come down the road
1868
-     *
1869
-     * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
1870
-     *         extended) also see:
1871
-     * @link   http://eamann.com/tech/wordpress-portland/
1872
-     * @abstract
1873
-     * @return void
1874
-     */
1875
-    private function _add_global_feature_pointers()
1876
-    {
1877
-    }
1878
-
1879
-
1880
-
1881
-    /**
1882
-     * load_global_scripts_styles
1883
-     * The scripts and styles enqueued in here will be loaded on every EE Admin page
1884
-     *
1885
-     * @return void
1886
-     * @throws EE_Error
1887
-     */
1888
-    public function load_global_scripts_styles()
1889
-    {
1890
-        /** STYLES **/
1891
-        // add debugging styles
1892
-        if (WP_DEBUG) {
1893
-            add_action('admin_head', array($this, 'add_xdebug_style'));
1894
-        }
1895
-        // register all styles
1896
-        wp_register_style(
1897
-            'espresso-ui-theme',
1898
-            EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
1899
-            array(),
1900
-            EVENT_ESPRESSO_VERSION
1901
-        );
1902
-        wp_register_style('ee-admin-css', EE_ADMIN_URL . 'assets/ee-admin-page.css', array(), EVENT_ESPRESSO_VERSION);
1903
-        //helpers styles
1904
-        wp_register_style(
1905
-            'ee-text-links',
1906
-            EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.css',
1907
-            array(),
1908
-            EVENT_ESPRESSO_VERSION
1909
-        );
1910
-        /** SCRIPTS **/
1911
-        //register all scripts
1912
-        wp_register_script(
1913
-            'ee-dialog',
1914
-            EE_ADMIN_URL . 'assets/ee-dialog-helper.js',
1915
-            array('jquery', 'jquery-ui-draggable'),
1916
-            EVENT_ESPRESSO_VERSION,
1917
-            true
1918
-        );
1919
-        wp_register_script(
1920
-            'ee_admin_js',
1921
-            EE_ADMIN_URL . 'assets/ee-admin-page.js',
1922
-            array('espresso_core', 'ee-parse-uri', 'ee-dialog'),
1923
-            EVENT_ESPRESSO_VERSION,
1924
-            true
1925
-        );
1926
-        wp_register_script(
1927
-            'jquery-ui-timepicker-addon',
1928
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery-ui-timepicker-addon.js',
1929
-            array('jquery-ui-datepicker', 'jquery-ui-slider'),
1930
-            EVENT_ESPRESSO_VERSION,
1931
-            true
1932
-        );
1933
-        add_filter('FHEE_load_joyride', '__return_true');
1934
-        //script for sorting tables
1935
-        wp_register_script(
1936
-            'espresso_ajax_table_sorting',
1937
-            EE_ADMIN_URL . 'assets/espresso_ajax_table_sorting.js',
1938
-            array('ee_admin_js', 'jquery-ui-sortable'),
1939
-            EVENT_ESPRESSO_VERSION,
1940
-            true
1941
-        );
1942
-        //script for parsing uri's
1943
-        wp_register_script(
1944
-            'ee-parse-uri',
1945
-            EE_GLOBAL_ASSETS_URL . 'scripts/parseuri.js',
1946
-            array(),
1947
-            EVENT_ESPRESSO_VERSION,
1948
-            true
1949
-        );
1950
-        //and parsing associative serialized form elements
1951
-        wp_register_script(
1952
-            'ee-serialize-full-array',
1953
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery.serializefullarray.js',
1954
-            array('jquery'),
1955
-            EVENT_ESPRESSO_VERSION,
1956
-            true
1957
-        );
1958
-        //helpers scripts
1959
-        wp_register_script(
1960
-            'ee-text-links',
1961
-            EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.js',
1962
-            array('jquery'),
1963
-            EVENT_ESPRESSO_VERSION,
1964
-            true
1965
-        );
1966
-        wp_register_script(
1967
-            'ee-moment-core',
1968
-            EE_THIRD_PARTY_URL . 'moment/moment-with-locales.min.js',
1969
-            array(),
1970
-            EVENT_ESPRESSO_VERSION,
1971
-            true
1972
-        );
1973
-        wp_register_script(
1974
-            'ee-moment',
1975
-            EE_THIRD_PARTY_URL . 'moment/moment-timezone-with-data.min.js',
1976
-            array('ee-moment-core'),
1977
-            EVENT_ESPRESSO_VERSION,
1978
-            true
1979
-        );
1980
-        wp_register_script(
1981
-            'ee-datepicker',
1982
-            EE_ADMIN_URL . 'assets/ee-datepicker.js',
1983
-            array('jquery-ui-timepicker-addon', 'ee-moment'),
1984
-            EVENT_ESPRESSO_VERSION,
1985
-            true
1986
-        );
1987
-        //google charts
1988
-        wp_register_script(
1989
-            'google-charts',
1990
-            'https://www.gstatic.com/charts/loader.js',
1991
-            array(),
1992
-            EVENT_ESPRESSO_VERSION,
1993
-            false
1994
-        );
1995
-        // ENQUEUE ALL BASICS BY DEFAULT
1996
-        wp_enqueue_style('ee-admin-css');
1997
-        wp_enqueue_script('ee_admin_js');
1998
-        wp_enqueue_script('ee-accounting');
1999
-        wp_enqueue_script('jquery-validate');
2000
-        //taking care of metaboxes
2001
-        if (
2002
-            empty($this->_cpt_route)
2003
-            && (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
2004
-        ) {
2005
-            wp_enqueue_script('dashboard');
2006
-        }
2007
-        // LOCALIZED DATA
2008
-        //localize script for ajax lazy loading
2009
-        $lazy_loader_container_ids = apply_filters(
2010
-            'FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers',
2011
-            array('espresso_news_post_box_content')
2012
-        );
2013
-        wp_localize_script('ee_admin_js', 'eeLazyLoadingContainers', $lazy_loader_container_ids);
2014
-        /**
2015
-         * help tour stuff
2016
-         */
2017
-        if (! empty($this->_help_tour)) {
2018
-            //register the js for kicking things off
2019
-            wp_enqueue_script(
2020
-                'ee-help-tour',
2021
-                EE_ADMIN_URL . 'assets/ee-help-tour.js',
2022
-                array('jquery-joyride'),
2023
-                EVENT_ESPRESSO_VERSION,
2024
-                true
2025
-            );
2026
-            $tours = array();
2027
-            //setup tours for the js tour object
2028
-            foreach ($this->_help_tour['tours'] as $tour) {
2029
-                if ($tour instanceof EE_Help_Tour) {
2030
-                    $tours[] = array(
2031
-                        'id'      => $tour->get_slug(),
2032
-                        'options' => $tour->get_options(),
2033
-                    );
2034
-                }
2035
-            }
2036
-            wp_localize_script('ee-help-tour', 'EE_HELP_TOUR', array('tours' => $tours));
2037
-            //admin_footer_global will take care of making sure our help_tour skeleton gets printed via the info stored in $this->_help_tour
2038
-        }
2039
-    }
2040
-
2041
-
2042
-
2043
-    /**
2044
-     *        admin_footer_scripts_eei18n_js_strings
2045
-     *
2046
-     * @return        void
2047
-     */
2048
-    public function admin_footer_scripts_eei18n_js_strings()
2049
-    {
2050
-        EE_Registry::$i18n_js_strings['ajax_url']       = WP_AJAX_URL;
2051
-        EE_Registry::$i18n_js_strings['confirm_delete'] = esc_html__(
2052
-            'Are you absolutely sure you want to delete this item?\nThis action will delete ALL DATA associated with this item!!!\nThis can NOT be undone!!!',
2053
-            'event_espresso'
2054
-        );
2055
-        EE_Registry::$i18n_js_strings['January']        = esc_html__('January', 'event_espresso');
2056
-        EE_Registry::$i18n_js_strings['February']       = esc_html__('February', 'event_espresso');
2057
-        EE_Registry::$i18n_js_strings['March']          = esc_html__('March', 'event_espresso');
2058
-        EE_Registry::$i18n_js_strings['April']          = esc_html__('April', 'event_espresso');
2059
-        EE_Registry::$i18n_js_strings['May']            = esc_html__('May', 'event_espresso');
2060
-        EE_Registry::$i18n_js_strings['June']           = esc_html__('June', 'event_espresso');
2061
-        EE_Registry::$i18n_js_strings['July']           = esc_html__('July', 'event_espresso');
2062
-        EE_Registry::$i18n_js_strings['August']         = esc_html__('August', 'event_espresso');
2063
-        EE_Registry::$i18n_js_strings['September']      = esc_html__('September', 'event_espresso');
2064
-        EE_Registry::$i18n_js_strings['October']        = esc_html__('October', 'event_espresso');
2065
-        EE_Registry::$i18n_js_strings['November']       = esc_html__('November', 'event_espresso');
2066
-        EE_Registry::$i18n_js_strings['December']       = esc_html__('December', 'event_espresso');
2067
-        EE_Registry::$i18n_js_strings['Jan']            = esc_html__('Jan', 'event_espresso');
2068
-        EE_Registry::$i18n_js_strings['Feb']            = esc_html__('Feb', 'event_espresso');
2069
-        EE_Registry::$i18n_js_strings['Mar']            = esc_html__('Mar', 'event_espresso');
2070
-        EE_Registry::$i18n_js_strings['Apr']            = esc_html__('Apr', 'event_espresso');
2071
-        EE_Registry::$i18n_js_strings['May']            = esc_html__('May', 'event_espresso');
2072
-        EE_Registry::$i18n_js_strings['Jun']            = esc_html__('Jun', 'event_espresso');
2073
-        EE_Registry::$i18n_js_strings['Jul']            = esc_html__('Jul', 'event_espresso');
2074
-        EE_Registry::$i18n_js_strings['Aug']            = esc_html__('Aug', 'event_espresso');
2075
-        EE_Registry::$i18n_js_strings['Sep']            = esc_html__('Sep', 'event_espresso');
2076
-        EE_Registry::$i18n_js_strings['Oct']            = esc_html__('Oct', 'event_espresso');
2077
-        EE_Registry::$i18n_js_strings['Nov']            = esc_html__('Nov', 'event_espresso');
2078
-        EE_Registry::$i18n_js_strings['Dec']            = esc_html__('Dec', 'event_espresso');
2079
-        EE_Registry::$i18n_js_strings['Sunday']         = esc_html__('Sunday', 'event_espresso');
2080
-        EE_Registry::$i18n_js_strings['Monday']         = esc_html__('Monday', 'event_espresso');
2081
-        EE_Registry::$i18n_js_strings['Tuesday']        = esc_html__('Tuesday', 'event_espresso');
2082
-        EE_Registry::$i18n_js_strings['Wednesday']      = esc_html__('Wednesday', 'event_espresso');
2083
-        EE_Registry::$i18n_js_strings['Thursday']       = esc_html__('Thursday', 'event_espresso');
2084
-        EE_Registry::$i18n_js_strings['Friday']         = esc_html__('Friday', 'event_espresso');
2085
-        EE_Registry::$i18n_js_strings['Saturday']       = esc_html__('Saturday', 'event_espresso');
2086
-        EE_Registry::$i18n_js_strings['Sun']            = esc_html__('Sun', 'event_espresso');
2087
-        EE_Registry::$i18n_js_strings['Mon']            = esc_html__('Mon', 'event_espresso');
2088
-        EE_Registry::$i18n_js_strings['Tue']            = esc_html__('Tue', 'event_espresso');
2089
-        EE_Registry::$i18n_js_strings['Wed']            = esc_html__('Wed', 'event_espresso');
2090
-        EE_Registry::$i18n_js_strings['Thu']            = esc_html__('Thu', 'event_espresso');
2091
-        EE_Registry::$i18n_js_strings['Fri']            = esc_html__('Fri', 'event_espresso');
2092
-        EE_Registry::$i18n_js_strings['Sat']            = esc_html__('Sat', 'event_espresso');
2093
-    }
2094
-
2095
-
2096
-
2097
-    /**
2098
-     *        load enhanced xdebug styles for ppl with failing eyesight
2099
-     *
2100
-     * @return        void
2101
-     */
2102
-    public function add_xdebug_style()
2103
-    {
2104
-        echo '<style>.xdebug-error { font-size:1.5em; }</style>';
2105
-    }
2106
-
2107
-
2108
-    /************************/
2109
-    /** LIST TABLE METHODS **/
2110
-    /************************/
2111
-    /**
2112
-     * this sets up the list table if the current view requires it.
2113
-     *
2114
-     * @return void
2115
-     * @throws EE_Error
2116
-     */
2117
-    protected function _set_list_table()
2118
-    {
2119
-        //first is this a list_table view?
2120
-        if (! isset($this->_route_config['list_table'])) {
2121
-            return;
2122
-        } //not a list_table view so get out.
2123
-        // list table functions are per view specific (because some admin pages might have more than one list table!)
2124
-        $list_table_view = '_set_list_table_views_' . $this->_req_action;
2125
-        if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2126
-            //user error msg
2127
-            $error_msg = esc_html__(
2128
-                'An error occurred. The requested list table views could not be found.',
2129
-                'event_espresso'
2130
-            );
2131
-            //developer error msg
2132
-            $error_msg .= '||' . sprintf(
2133
-                    esc_html__(
2134
-                        'List table views for "%s" route could not be setup. Check that you have the corresponding method, "%s" set up for defining list_table_views for this route.',
2135
-                        'event_espresso'
2136
-                    ),
2137
-                    $this->_req_action,
2138
-                    $list_table_view
2139
-                );
2140
-            throw new EE_Error($error_msg);
2141
-        }
2142
-        //let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2143
-        $this->_views = apply_filters(
2144
-            'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2145
-            $this->_views
2146
-        );
2147
-        $this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2148
-        $this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2149
-        $this->_set_list_table_view();
2150
-        $this->_set_list_table_object();
2151
-    }
2152
-
2153
-
2154
-
2155
-    /**
2156
-     * set current view for List Table
2157
-     *
2158
-     * @return void
2159
-     */
2160
-    protected function _set_list_table_view()
2161
-    {
2162
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2163
-        // looking at active items or dumpster diving ?
2164
-        if (! isset($this->_req_data['status']) || ! array_key_exists($this->_req_data['status'], $this->_views)) {
2165
-            $this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
2166
-        } else {
2167
-            $this->_view = sanitize_key($this->_req_data['status']);
2168
-        }
2169
-    }
2170
-
2171
-
2172
-    /**
2173
-     * _set_list_table_object
2174
-     * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
2175
-     *
2176
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2177
-     * @throws \InvalidArgumentException
2178
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2179
-     * @throws EE_Error
2180
-     * @throws InvalidInterfaceException
2181
-     */
2182
-    protected function _set_list_table_object()
2183
-    {
2184
-        if (isset($this->_route_config['list_table'])) {
2185
-            if (! class_exists($this->_route_config['list_table'])) {
2186
-                throw new EE_Error(
2187
-                    sprintf(
2188
-                        esc_html__(
2189
-                            'The %s class defined for the list table does not exist.  Please check the spelling of the class ref in the $_page_config property on %s.',
2190
-                            'event_espresso'
2191
-                        ),
2192
-                        $this->_route_config['list_table'],
2193
-                        get_class($this)
2194
-                    )
2195
-                );
2196
-            }
2197
-            $this->_list_table_object = LoaderFactory::getLoader()->getShared(
2198
-                $this->_route_config['list_table'],
2199
-                array($this)
2200
-            );
2201
-        }
2202
-    }
2203
-
2204
-
2205
-
2206
-    /**
2207
-     * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
2208
-     *
2209
-     * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
2210
-     *                                                    urls.  The array should be indexed by the view it is being
2211
-     *                                                    added to.
2212
-     * @return array
2213
-     */
2214
-    public function get_list_table_view_RLs($extra_query_args = array())
2215
-    {
2216
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2217
-        if (empty($this->_views)) {
2218
-            $this->_views = array();
2219
-        }
2220
-        // cycle thru views
2221
-        foreach ($this->_views as $key => $view) {
2222
-            $query_args = array();
2223
-            // check for current view
2224
-            $this->_views[$key]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2225
-            $query_args['action']                      = $this->_req_action;
2226
-            $query_args[$this->_req_action . '_nonce'] = wp_create_nonce($query_args['action'] . '_nonce');
2227
-            $query_args['status']                      = $view['slug'];
2228
-            //merge any other arguments sent in.
2229
-            if (isset($extra_query_args[$view['slug']])) {
2230
-                $query_args = array_merge($query_args, $extra_query_args[$view['slug']]);
2231
-            }
2232
-            $this->_views[$key]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2233
-        }
2234
-        return $this->_views;
2235
-    }
2236
-
2237
-
2238
-
2239
-    /**
2240
-     * _entries_per_page_dropdown
2241
-     * generates a drop down box for selecting the number of visible rows in an admin page list table
2242
-     *
2243
-     * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how
2244
-     *         WP does it.
2245
-     * @param int $max_entries total number of rows in the table
2246
-     * @return string
2247
-     */
2248
-    protected function _entries_per_page_dropdown($max_entries = 0)
2249
-    {
2250
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2251
-        $values   = array(10, 25, 50, 100);
2252
-        $per_page = (! empty($this->_req_data['per_page'])) ? absint($this->_req_data['per_page']) : 10;
2253
-        if ($max_entries) {
2254
-            $values[] = $max_entries;
2255
-            sort($values);
2256
-        }
2257
-        $entries_per_page_dropdown = '
126
+	/**
127
+	 * @var string $_req_action
128
+	 */
129
+	protected $_req_action;
130
+
131
+	/**
132
+	 * @var string $_req_nonce
133
+	 */
134
+	protected $_req_nonce;
135
+
136
+	//search related
137
+	protected $_search_btn_label;
138
+
139
+	protected $_search_box_callback;
140
+
141
+	/**
142
+	 * WP Current Screen object
143
+	 *
144
+	 * @var WP_Screen
145
+	 */
146
+	protected $_current_screen;
147
+
148
+	//for holding EE_Admin_Hooks object when needed (set via set_hook_object())
149
+	protected $_hook_obj;
150
+
151
+	//for holding incoming request data
152
+	protected $_req_data;
153
+
154
+	// yes / no array for admin form fields
155
+	protected $_yes_no_values = array();
156
+
157
+	//some default things shared by all child classes
158
+	protected $_default_espresso_metaboxes;
159
+
160
+	/**
161
+	 *    EE_Registry Object
162
+	 *
163
+	 * @var    EE_Registry
164
+	 */
165
+	protected $EE = null;
166
+
167
+
168
+
169
+	/**
170
+	 * This is just a property that flags whether the given route is a caffeinated route or not.
171
+	 *
172
+	 * @var boolean
173
+	 */
174
+	protected $_is_caf = false;
175
+
176
+
177
+
178
+	/**
179
+	 * @Constructor
180
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
181
+	 * @throws EE_Error
182
+	 * @throws InvalidArgumentException
183
+	 * @throws ReflectionException
184
+	 * @throws InvalidDataTypeException
185
+	 * @throws InvalidInterfaceException
186
+	 */
187
+	public function __construct($routing = true)
188
+	{
189
+		if (strpos($this->_get_dir(), 'caffeinated') !== false) {
190
+			$this->_is_caf = true;
191
+		}
192
+		$this->_yes_no_values = array(
193
+			array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
194
+			array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
195
+		);
196
+		//set the _req_data property.
197
+		$this->_req_data = array_merge($_GET, $_POST);
198
+		//routing enabled?
199
+		$this->_routing = $routing;
200
+		//set initial page props (child method)
201
+		$this->_init_page_props();
202
+		//set global defaults
203
+		$this->_set_defaults();
204
+		//set early because incoming requests could be ajax related and we need to register those hooks.
205
+		$this->_global_ajax_hooks();
206
+		$this->_ajax_hooks();
207
+		//other_page_hooks have to be early too.
208
+		$this->_do_other_page_hooks();
209
+		//This just allows us to have extending classes do something specific
210
+		// before the parent constructor runs _page_setup().
211
+		if (method_exists($this, '_before_page_setup')) {
212
+			$this->_before_page_setup();
213
+		}
214
+		//set up page dependencies
215
+		$this->_page_setup();
216
+	}
217
+
218
+
219
+
220
+	/**
221
+	 * _init_page_props
222
+	 * Child classes use to set at least the following properties:
223
+	 * $page_slug.
224
+	 * $page_label.
225
+	 *
226
+	 * @abstract
227
+	 * @return void
228
+	 */
229
+	abstract protected function _init_page_props();
230
+
231
+
232
+
233
+	/**
234
+	 * _ajax_hooks
235
+	 * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
236
+	 * Note: within the ajax callback methods.
237
+	 *
238
+	 * @abstract
239
+	 * @return void
240
+	 */
241
+	abstract protected function _ajax_hooks();
242
+
243
+
244
+
245
+	/**
246
+	 * _define_page_props
247
+	 * child classes define page properties in here.  Must include at least:
248
+	 * $_admin_base_url = base_url for all admin pages
249
+	 * $_admin_page_title = default admin_page_title for admin pages
250
+	 * $_labels = array of default labels for various automatically generated elements:
251
+	 *    array(
252
+	 *        'buttons' => array(
253
+	 *            'add' => esc_html__('label for add new button'),
254
+	 *            'edit' => esc_html__('label for edit button'),
255
+	 *            'delete' => esc_html__('label for delete button')
256
+	 *            )
257
+	 *        )
258
+	 *
259
+	 * @abstract
260
+	 * @return void
261
+	 */
262
+	abstract protected function _define_page_props();
263
+
264
+
265
+
266
+	/**
267
+	 * _set_page_routes
268
+	 * child classes use this to define the page routes for all subpages handled by the class.  Page routes are
269
+	 * assigned to a action => method pairs in an array and to the $_page_routes property.  Each page route must also
270
+	 * have a 'default' route. Here's the format
271
+	 * $this->_page_routes = array(
272
+	 *        'default' => array(
273
+	 *            'func' => '_default_method_handling_route',
274
+	 *            'args' => array('array','of','args'),
275
+	 *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e.
276
+	 *            ajax request, backend processing)
277
+	 *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a
278
+	 *            headers route after.  The string you enter here should match the defined route reference for a
279
+	 *            headers sent route.
280
+	 *            'capability' => 'route_capability', //indicate a string for minimum capability required to access
281
+	 *            this route.
282
+	 *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability
283
+	 *            checks).
284
+	 *        ),
285
+	 *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a
286
+	 *        handling method.
287
+	 *        )
288
+	 * )
289
+	 *
290
+	 * @abstract
291
+	 * @return void
292
+	 */
293
+	abstract protected function _set_page_routes();
294
+
295
+
296
+
297
+	/**
298
+	 * _set_page_config
299
+	 * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the
300
+	 * array corresponds to the page_route for the loaded page. Format:
301
+	 * $this->_page_config = array(
302
+	 *        'default' => array(
303
+	 *            'labels' => array(
304
+	 *                'buttons' => array(
305
+	 *                    'add' => esc_html__('label for adding item'),
306
+	 *                    'edit' => esc_html__('label for editing item'),
307
+	 *                    'delete' => esc_html__('label for deleting item')
308
+	 *                ),
309
+	 *                'publishbox' => esc_html__('Localized Title for Publish metabox', 'event_espresso')
310
+	 *            ), //optional an array of custom labels for various automatically generated elements to use on the
311
+	 *            page. If this isn't present then the defaults will be used as set for the $this->_labels in
312
+	 *            _define_page_props() method
313
+	 *            'nav' => array(
314
+	 *                'label' => esc_html__('Label for Tab', 'event_espresso').
315
+	 *                'url' => 'http://someurl', //automatically generated UNLESS you define
316
+	 *                'css_class' => 'css-class', //automatically generated UNLESS you define
317
+	 *                'order' => 10, //required to indicate tab position.
318
+	 *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is
319
+	 *                displayed then add this parameter.
320
+	 *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
321
+	 *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load
322
+	 *            metaboxes set for eventespresso admin pages.
323
+	 *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have
324
+	 *            metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added
325
+	 *            later.  We just use this flag to make sure the necessary js gets enqueued on page load.
326
+	 *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the
327
+	 *            given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
328
+	 *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The
329
+	 *            array indicates the max number of columns (4) and the default number of columns on page load (2).
330
+	 *            There is an option in the "screen_options" dropdown that is setup so users can pick what columns they
331
+	 *            want to display.
332
+	 *            'help_tabs' => array( //this is used for adding help tabs to a page
333
+	 *                'tab_id' => array(
334
+	 *                    'title' => 'tab_title',
335
+	 *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting
336
+	 *                    help tab content.  The fallback if it isn't present is to try a the callback.  Filename
337
+	 *                    should match a file in the admin folder's "help_tabs" dir (ie..
338
+	 *                    events/help_tabs/name_of_file_containing_content.help_tab.php)
339
+	 *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will
340
+	 *                    attempt to use the callback which should match the name of a method in the class
341
+	 *                    ),
342
+	 *                'tab2_id' => array(
343
+	 *                    'title' => 'tab2 title',
344
+	 *                    'filename' => 'file_name_2'
345
+	 *                    'callback' => 'callback_method_for_content',
346
+	 *                 ),
347
+	 *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the
348
+	 *            help tab area on an admin page. @link
349
+	 *            http://make.wordpress.org/core/2011/12/06/help-and-screen-api-changes-in-3-3/
350
+	 *            'help_tour' => array(
351
+	 *                'name_of_help_tour_class', //all help tours shoudl be a child class of EE_Help_Tour and located
352
+	 *                in a folder for this admin page named "help_tours", a file name matching the key given here
353
+	 *                (name_of_help_tour_class.class.php), and class matching key given here (name_of_help_tour_class)
354
+	 *            ),
355
+	 *            'require_nonce' => TRUE //this is used if you want to set a route to NOT require a nonce (default is
356
+	 *            true if it isn't present).  To remove the requirement for a nonce check when this route is visited
357
+	 *            just set
358
+	 *            'require_nonce' to FALSE
359
+	 *            )
360
+	 * )
361
+	 *
362
+	 * @abstract
363
+	 * @return void
364
+	 */
365
+	abstract protected function _set_page_config();
366
+
367
+
368
+
369
+
370
+
371
+	/** end sample help_tour methods **/
372
+	/**
373
+	 * _add_screen_options
374
+	 * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for
375
+	 * doing so. Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options
376
+	 * to a particular view.
377
+	 *
378
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
379
+	 *         see also WP_Screen object documents...
380
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
381
+	 * @abstract
382
+	 * @return void
383
+	 */
384
+	abstract protected function _add_screen_options();
385
+
386
+
387
+
388
+	/**
389
+	 * _add_feature_pointers
390
+	 * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
391
+	 * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a
392
+	 * particular view. Note: this is just a placeholder for now.  Implementation will come down the road See:
393
+	 * WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
394
+	 * extended) also see:
395
+	 *
396
+	 * @link   http://eamann.com/tech/wordpress-portland/
397
+	 * @abstract
398
+	 * @return void
399
+	 */
400
+	abstract protected function _add_feature_pointers();
401
+
402
+
403
+
404
+	/**
405
+	 * load_scripts_styles
406
+	 * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for
407
+	 * their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific
408
+	 * scripts/styles per view by putting them in a dynamic function in this format
409
+	 * (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
410
+	 *
411
+	 * @abstract
412
+	 * @return void
413
+	 */
414
+	abstract public function load_scripts_styles();
415
+
416
+
417
+
418
+	/**
419
+	 * admin_init
420
+	 * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to
421
+	 * all pages/views loaded by child class.
422
+	 *
423
+	 * @abstract
424
+	 * @return void
425
+	 */
426
+	abstract public function admin_init();
427
+
428
+
429
+
430
+	/**
431
+	 * admin_notices
432
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to
433
+	 * all pages/views loaded by child class.
434
+	 *
435
+	 * @abstract
436
+	 * @return void
437
+	 */
438
+	abstract public function admin_notices();
439
+
440
+
441
+
442
+	/**
443
+	 * admin_footer_scripts
444
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
445
+	 * will apply to all pages/views loaded by child class.
446
+	 *
447
+	 * @return void
448
+	 */
449
+	abstract public function admin_footer_scripts();
450
+
451
+
452
+
453
+	/**
454
+	 * admin_footer
455
+	 * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will
456
+	 * apply to all pages/views loaded by child class.
457
+	 *
458
+	 * @return void
459
+	 */
460
+	public function admin_footer()
461
+	{
462
+	}
463
+
464
+
465
+
466
+	/**
467
+	 * _global_ajax_hooks
468
+	 * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
469
+	 * Note: within the ajax callback methods.
470
+	 *
471
+	 * @abstract
472
+	 * @return void
473
+	 */
474
+	protected function _global_ajax_hooks()
475
+	{
476
+		//for lazy loading of metabox content
477
+		add_action('wp_ajax_espresso-ajax-content', array($this, 'ajax_metabox_content'), 10);
478
+	}
479
+
480
+
481
+
482
+	public function ajax_metabox_content()
483
+	{
484
+		$contentid = isset($this->_req_data['contentid']) ? $this->_req_data['contentid'] : '';
485
+		$url       = isset($this->_req_data['contenturl']) ? $this->_req_data['contenturl'] : '';
486
+		self::cached_rss_display($contentid, $url);
487
+		wp_die();
488
+	}
489
+
490
+
491
+
492
+	/**
493
+	 * _page_setup
494
+	 * Makes sure any things that need to be loaded early get handled.  We also escape early here if the page requested
495
+	 * doesn't match the object.
496
+	 *
497
+	 * @final
498
+	 * @return void
499
+	 * @throws EE_Error
500
+	 * @throws InvalidArgumentException
501
+	 * @throws ReflectionException
502
+	 * @throws InvalidDataTypeException
503
+	 * @throws InvalidInterfaceException
504
+	 */
505
+	final protected function _page_setup()
506
+	{
507
+		//requires?
508
+		//admin_init stuff - global - we're setting this REALLY early so if EE_Admin pages have to hook into other WP pages they can.  But keep in mind, not everything is available from the EE_Admin Page object at this point.
509
+		add_action('admin_init', array($this, 'admin_init_global'), 5);
510
+		//next verify if we need to load anything...
511
+		$this->_current_page = ! empty($_GET['page']) ? sanitize_key($_GET['page']) : '';
512
+		$this->page_folder   = strtolower(
513
+			str_replace(array('_Admin_Page', 'Extend_'), '', get_class($this))
514
+		);
515
+		global $ee_menu_slugs;
516
+		$ee_menu_slugs = (array)$ee_menu_slugs;
517
+		if (! defined('DOING_AJAX') && (! $this->_current_page || ! isset($ee_menu_slugs[$this->_current_page]))) {
518
+			return;
519
+		}
520
+		// becuz WP List tables have two duplicate select inputs for choosing bulk actions, we need to copy the action from the second to the first
521
+		if (isset($this->_req_data['action2']) && $this->_req_data['action'] === '-1') {
522
+			$this->_req_data['action'] = ! empty($this->_req_data['action2']) && $this->_req_data['action2'] !== '-1'
523
+				? $this->_req_data['action2']
524
+				: $this->_req_data['action'];
525
+		}
526
+		// then set blank or -1 action values to 'default'
527
+		$this->_req_action = isset($this->_req_data['action'])
528
+							 && ! empty($this->_req_data['action'])
529
+							 && $this->_req_data['action'] !== '-1'
530
+			? sanitize_key($this->_req_data['action'])
531
+			: 'default';
532
+		// if action is 'default' after the above BUT we have  'route' var set, then let's use the route as the action.
533
+		//  This covers cases where we're coming in from a list table that isn't on the default route.
534
+		$this->_req_action = $this->_req_action === 'default' && isset($this->_req_data['route'])
535
+			? $this->_req_data['route'] : $this->_req_action;
536
+		//however if we are doing_ajax and we've got a 'route' set then that's what the req_action will be
537
+		$this->_req_action   = defined('DOING_AJAX') && isset($this->_req_data['route'])
538
+			? $this->_req_data['route']
539
+			: $this->_req_action;
540
+		$this->_current_view = $this->_req_action;
541
+		$this->_req_nonce    = $this->_req_action . '_nonce';
542
+		$this->_define_page_props();
543
+		$this->_current_page_view_url = add_query_arg(
544
+			array('page' => $this->_current_page, 'action' => $this->_current_view),
545
+			$this->_admin_base_url
546
+		);
547
+		//default things
548
+		$this->_default_espresso_metaboxes = array(
549
+			'_espresso_news_post_box',
550
+			'_espresso_links_post_box',
551
+			'_espresso_ratings_request',
552
+			'_espresso_sponsors_post_box',
553
+		);
554
+		//set page configs
555
+		$this->_set_page_routes();
556
+		$this->_set_page_config();
557
+		//let's include any referrer data in our default_query_args for this route for "stickiness".
558
+		if (isset($this->_req_data['wp_referer'])) {
559
+			$this->_default_route_query_args['wp_referer'] = $this->_req_data['wp_referer'];
560
+		}
561
+		//for caffeinated and other extended functionality.
562
+		//  If there is a _extend_page_config method
563
+		// then let's run that to modify the all the various page configuration arrays
564
+		if (method_exists($this, '_extend_page_config')) {
565
+			$this->_extend_page_config();
566
+		}
567
+		//for CPT and other extended functionality.
568
+		// If there is an _extend_page_config_for_cpt
569
+		// then let's run that to modify all the various page configuration arrays.
570
+		if (method_exists($this, '_extend_page_config_for_cpt')) {
571
+			$this->_extend_page_config_for_cpt();
572
+		}
573
+		//filter routes and page_config so addons can add their stuff. Filtering done per class
574
+		$this->_page_routes = apply_filters(
575
+			'FHEE__' . get_class($this) . '__page_setup__page_routes',
576
+			$this->_page_routes,
577
+			$this
578
+		);
579
+		$this->_page_config = apply_filters(
580
+			'FHEE__' . get_class($this) . '__page_setup__page_config',
581
+			$this->_page_config,
582
+			$this
583
+		);
584
+		//if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
585
+		// then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
586
+		if (
587
+			method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)
588
+		) {
589
+			add_action(
590
+				'AHEE__EE_Admin_Page__route_admin_request',
591
+				array($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view),
592
+				10,
593
+				2
594
+			);
595
+		}
596
+		//next route only if routing enabled
597
+		if ($this->_routing && ! defined('DOING_AJAX')) {
598
+			$this->_verify_routes();
599
+			//next let's just check user_access and kill if no access
600
+			$this->check_user_access();
601
+			if ($this->_is_UI_request) {
602
+				//admin_init stuff - global, all views for this page class, specific view
603
+				add_action('admin_init', array($this, 'admin_init'), 10);
604
+				if (method_exists($this, 'admin_init_' . $this->_current_view)) {
605
+					add_action('admin_init', array($this, 'admin_init_' . $this->_current_view), 15);
606
+				}
607
+			} else {
608
+				//hijack regular WP loading and route admin request immediately
609
+				@ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
610
+				$this->route_admin_request();
611
+			}
612
+		}
613
+	}
614
+
615
+
616
+
617
+	/**
618
+	 * Provides a way for related child admin pages to load stuff on the loaded admin page.
619
+	 *
620
+	 * @return void
621
+	 * @throws ReflectionException
622
+	 * @throws EE_Error
623
+	 */
624
+	private function _do_other_page_hooks()
625
+	{
626
+		$registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, array());
627
+		foreach ($registered_pages as $page) {
628
+			//now let's setup the file name and class that should be present
629
+			$classname = str_replace('.class.php', '', $page);
630
+			//autoloaders should take care of loading file
631
+			if (! class_exists($classname)) {
632
+				$error_msg[] = sprintf(
633
+					esc_html__(
634
+						'Something went wrong with loading the %s admin hooks page.',
635
+						'event_espresso'
636
+					),
637
+					$page
638
+				);
639
+				$error_msg[] = $error_msg[0]
640
+							   . "\r\n"
641
+							   . sprintf(
642
+								   esc_html__(
643
+									   'There is no class in place for the %1$s admin hooks page.%2$sMake sure you have %3$s defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class',
644
+									   'event_espresso'
645
+								   ),
646
+								   $page,
647
+								   '<br />',
648
+								   '<strong>' . $classname . '</strong>'
649
+							   );
650
+				throw new EE_Error(implode('||', $error_msg));
651
+			}
652
+			$a = new ReflectionClass($classname);
653
+			//notice we are passing the instance of this class to the hook object.
654
+			$hookobj[] = $a->newInstance($this);
655
+		}
656
+	}
657
+
658
+
659
+
660
+	public function load_page_dependencies()
661
+	{
662
+		try {
663
+			$this->_load_page_dependencies();
664
+		} catch (EE_Error $e) {
665
+			$e->get_error();
666
+		}
667
+	}
668
+
669
+
670
+
671
+	/**
672
+	 * load_page_dependencies
673
+	 * loads things specific to this page class when its loaded.  Really helps with efficiency.
674
+	 *
675
+	 * @return void
676
+	 * @throws DomainException
677
+	 * @throws EE_Error
678
+	 * @throws InvalidArgumentException
679
+	 * @throws InvalidDataTypeException
680
+	 * @throws InvalidInterfaceException
681
+	 * @throws ReflectionException
682
+	 */
683
+	protected function _load_page_dependencies()
684
+	{
685
+		//let's set the current_screen and screen options to override what WP set
686
+		$this->_current_screen = get_current_screen();
687
+		//load admin_notices - global, page class, and view specific
688
+		add_action('admin_notices', array($this, 'admin_notices_global'), 5);
689
+		add_action('admin_notices', array($this, 'admin_notices'), 10);
690
+		if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
691
+			add_action('admin_notices', array($this, 'admin_notices_' . $this->_current_view), 15);
692
+		}
693
+		//load network admin_notices - global, page class, and view specific
694
+		add_action('network_admin_notices', array($this, 'network_admin_notices_global'), 5);
695
+		if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
696
+			add_action('network_admin_notices', array($this, 'network_admin_notices_' . $this->_current_view));
697
+		}
698
+		//this will save any per_page screen options if they are present
699
+		$this->_set_per_page_screen_options();
700
+		//setup list table properties
701
+		$this->_set_list_table();
702
+		// child classes can "register" a metabox to be automatically handled via the _page_config array property.
703
+		// However in some cases the metaboxes will need to be added within a route handling callback.
704
+		$this->_add_registered_meta_boxes();
705
+		$this->_add_screen_columns();
706
+		//add screen options - global, page child class, and view specific
707
+		$this->_add_global_screen_options();
708
+		$this->_add_screen_options();
709
+		$add_screen_options  = "_add_screen_options_{$this->_current_view}";
710
+		if (method_exists($this, $add_screen_options )) {
711
+			$this->{$add_screen_options}();
712
+		}
713
+		//add help tab(s) and tours- set via page_config and qtips.
714
+		$this->_add_help_tour();
715
+		$this->_add_help_tabs();
716
+		$this->_add_qtips();
717
+		//add feature_pointers - global, page child class, and view specific
718
+		$this->_add_feature_pointers();
719
+		$this->_add_global_feature_pointers();
720
+		$add_feature_pointer = "_add_feature_pointer_{$this->_current_view}";
721
+		if (method_exists($this, $add_feature_pointer )) {
722
+			$this->{$add_feature_pointer}();
723
+		}
724
+		//enqueue scripts/styles - global, page class, and view specific
725
+		add_action('admin_enqueue_scripts', array($this, 'load_global_scripts_styles'), 5);
726
+		add_action('admin_enqueue_scripts', array($this, 'load_scripts_styles'), 10);
727
+		if (method_exists($this, "load_scripts_styles_{$this->_current_view}")) {
728
+			add_action('admin_enqueue_scripts', array($this, "load_scripts_styles_{$this->_current_view}"), 15);
729
+		}
730
+		add_action('admin_enqueue_scripts', array($this, 'admin_footer_scripts_eei18n_js_strings'), 100);
731
+		// admin_print_footer_scripts - global, page child class, and view specific.
732
+		// NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.
733
+		// In most cases that's doing_it_wrong().  But adding hidden container elements etc.
734
+		// is a good use case. Notice the late priority we're giving these
735
+		add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts_global'), 99);
736
+		add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts'), 100);
737
+		if (method_exists($this, "admin_footer_scripts_{$this->_current_view}")) {
738
+			add_action('admin_print_footer_scripts', array($this, "admin_footer_scripts_{$this->_current_view}"), 101);
739
+		}
740
+		//admin footer scripts
741
+		add_action('admin_footer', array($this, 'admin_footer_global'), 99);
742
+		add_action('admin_footer', array($this, 'admin_footer'), 100);
743
+		if (method_exists($this, "admin_footer_{$this->_current_view}")) {
744
+			add_action('admin_footer', array($this, "admin_footer_{$this->_current_view}"), 101);
745
+		}
746
+		do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
747
+		//targeted hook
748
+		do_action(
749
+			"FHEE__EE_Admin_Page___load_page_dependencies__after_load__{$this->page_slug}__{$this->_req_action}"
750
+
751
+		);
752
+	}
753
+
754
+
755
+
756
+	/**
757
+	 * _set_defaults
758
+	 * This sets some global defaults for class properties.
759
+	 */
760
+	private function _set_defaults()
761
+	{
762
+		$this->_current_screen = $this->_admin_page_title = $this->_req_action = $this->_req_nonce = null;
763
+		$this->_event = $this->_template_path = $this->_column_template_path = null;
764
+		$this->_nav_tabs = $this->_views = $this->_page_routes = array();
765
+		$this->_page_config = $this->_default_route_query_args = array();
766
+		$this->_default_nav_tab_name = 'overview';
767
+		//init template args
768
+		$this->_template_args = array(
769
+			'admin_page_header'  => '',
770
+			'admin_page_content' => '',
771
+			'post_body_content'  => '',
772
+			'before_list_table'  => '',
773
+			'after_list_table'   => '',
774
+		);
775
+	}
776
+
777
+
778
+
779
+	/**
780
+	 * route_admin_request
781
+	 *
782
+	 * @see    _route_admin_request()
783
+	 * @return exception|void error
784
+	 * @throws InvalidArgumentException
785
+	 * @throws InvalidInterfaceException
786
+	 * @throws InvalidDataTypeException
787
+	 * @throws EE_Error
788
+	 * @throws ReflectionException
789
+	 */
790
+	public function route_admin_request()
791
+	{
792
+		try {
793
+			$this->_route_admin_request();
794
+		} catch (EE_Error $e) {
795
+			$e->get_error();
796
+		}
797
+	}
798
+
799
+
800
+
801
+	public function set_wp_page_slug($wp_page_slug)
802
+	{
803
+		$this->_wp_page_slug = $wp_page_slug;
804
+		//if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
805
+		if (is_network_admin()) {
806
+			$this->_wp_page_slug .= '-network';
807
+		}
808
+	}
809
+
810
+
811
+
812
+	/**
813
+	 * _verify_routes
814
+	 * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so
815
+	 * we know if we need to drop out.
816
+	 *
817
+	 * @return bool
818
+	 * @throws EE_Error
819
+	 */
820
+	protected function _verify_routes()
821
+	{
822
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
823
+		if (! $this->_current_page && ! defined('DOING_AJAX')) {
824
+			return false;
825
+		}
826
+		$this->_route = false;
827
+		// check that the page_routes array is not empty
828
+		if (empty($this->_page_routes)) {
829
+			// user error msg
830
+			$error_msg = sprintf(
831
+				esc_html__('No page routes have been set for the %s admin page.', 'event_espresso'),
832
+				$this->_admin_page_title
833
+			);
834
+			// developer error msg
835
+			$error_msg .= '||' . $error_msg . esc_html__(
836
+				' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
837
+				'event_espresso'
838
+			);
839
+			throw new EE_Error($error_msg);
840
+		}
841
+		// and that the requested page route exists
842
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
843
+			$this->_route        = $this->_page_routes[$this->_req_action];
844
+			$this->_route_config = isset($this->_page_config[$this->_req_action])
845
+				? $this->_page_config[$this->_req_action] : array();
846
+		} else {
847
+			// user error msg
848
+			$error_msg = sprintf(
849
+				esc_html__(
850
+						'The requested page route does not exist for the %s admin page.',
851
+						'event_espresso'
852
+				),
853
+				$this->_admin_page_title
854
+			);
855
+			// developer error msg
856
+			$error_msg .= '||' . $error_msg . sprintf(
857
+					esc_html__(
858
+						' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
859
+						'event_espresso'
860
+					),
861
+					$this->_req_action
862
+				);
863
+			throw new EE_Error($error_msg);
864
+		}
865
+		// and that a default route exists
866
+		if (! array_key_exists('default', $this->_page_routes)) {
867
+			// user error msg
868
+			$error_msg = sprintf(
869
+				esc_html__(
870
+						'A default page route has not been set for the % admin page.',
871
+						'event_espresso'
872
+				),
873
+				$this->_admin_page_title
874
+			);
875
+			// developer error msg
876
+			$error_msg .= '||' . $error_msg . esc_html__(
877
+				' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
878
+				'event_espresso'
879
+			);
880
+			throw new EE_Error($error_msg);
881
+		}
882
+		//first lets' catch if the UI request has EVER been set.
883
+		if ($this->_is_UI_request === null) {
884
+			//lets set if this is a UI request or not.
885
+			$this->_is_UI_request = ! isset($this->_req_data['noheader']) || $this->_req_data['noheader'] !== true;
886
+			//wait a minute... we might have a noheader in the route array
887
+			$this->_is_UI_request = is_array($this->_route)
888
+									&& isset($this->_route['noheader'])
889
+									&& $this->_route['noheader'] ? false : $this->_is_UI_request;
890
+		}
891
+		$this->_set_current_labels();
892
+		return true;
893
+	}
894
+
895
+
896
+
897
+	/**
898
+	 * this method simply verifies a given route and makes sure its an actual route available for the loaded page
899
+	 *
900
+	 * @param  string $route the route name we're verifying
901
+	 * @return mixed (bool|Exception)      we'll throw an exception if this isn't a valid route.
902
+	 * @throws EE_Error
903
+	 */
904
+	protected function _verify_route($route)
905
+	{
906
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
907
+			return true;
908
+		}
909
+		// user error msg
910
+		$error_msg = sprintf(
911
+			esc_html__('The given page route does not exist for the %s admin page.', 'event_espresso'),
912
+			$this->_admin_page_title
913
+		);
914
+		// developer error msg
915
+		$error_msg .= '||' . $error_msg . sprintf(
916
+				esc_html__(
917
+					' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
918
+					'event_espresso'
919
+				),
920
+				$route
921
+			);
922
+		throw new EE_Error($error_msg);
923
+	}
924
+
925
+
926
+
927
+	/**
928
+	 * perform nonce verification
929
+	 * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces
930
+	 * using this method (and save retyping!)
931
+	 *
932
+	 * @param  string $nonce     The nonce sent
933
+	 * @param  string $nonce_ref The nonce reference string (name0)
934
+	 * @return void
935
+	 * @throws EE_Error
936
+	 */
937
+	protected function _verify_nonce($nonce, $nonce_ref)
938
+	{
939
+		// verify nonce against expected value
940
+		if (! wp_verify_nonce($nonce, $nonce_ref)) {
941
+			// these are not the droids you are looking for !!!
942
+			$msg = sprintf(
943
+				esc_html__('%sNonce Fail.%s', 'event_espresso'),
944
+				'<a href="http://www.youtube.com/watch?v=56_S0WeTkzs">',
945
+				'</a>'
946
+			);
947
+			if (WP_DEBUG) {
948
+				$msg .= "\n  " . sprintf(
949
+						esc_html__(
950
+							'In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!',
951
+							'event_espresso'
952
+						),
953
+						__CLASS__
954
+					);
955
+			}
956
+			if (! defined('DOING_AJAX')) {
957
+				wp_die($msg);
958
+			} else {
959
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
960
+				$this->_return_json();
961
+			}
962
+		}
963
+	}
964
+
965
+
966
+
967
+	/**
968
+	 * _route_admin_request()
969
+	 * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if theres are
970
+	 * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
971
+	 * in the page routes and then will try to load the corresponding method.
972
+	 *
973
+	 * @return void
974
+	 * @throws EE_Error
975
+	 * @throws InvalidArgumentException
976
+	 * @throws InvalidDataTypeException
977
+	 * @throws InvalidInterfaceException
978
+	 * @throws ReflectionException
979
+	 */
980
+	protected function _route_admin_request()
981
+	{
982
+		if (! $this->_is_UI_request) {
983
+			$this->_verify_routes();
984
+		}
985
+		$nonce_check = isset($this->_route_config['require_nonce'])
986
+			? $this->_route_config['require_nonce']
987
+			: true;
988
+		if ($this->_req_action !== 'default' && $nonce_check) {
989
+			// set nonce from post data
990
+			$nonce = isset($this->_req_data[$this->_req_nonce])
991
+				? sanitize_text_field($this->_req_data[$this->_req_nonce])
992
+				: '';
993
+			$this->_verify_nonce($nonce, $this->_req_nonce);
994
+		}
995
+		//set the nav_tabs array but ONLY if this is  UI_request
996
+		if ($this->_is_UI_request) {
997
+			$this->_set_nav_tabs();
998
+		}
999
+		// grab callback function
1000
+		$func = is_array($this->_route) ? $this->_route['func'] : $this->_route;
1001
+		// check if callback has args
1002
+		$args      = is_array($this->_route) && isset($this->_route['args']) ? $this->_route['args'] : array();
1003
+		$error_msg = '';
1004
+		// action right before calling route
1005
+		// (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1006
+		if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1007
+			do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1008
+		}
1009
+		// right before calling the route, let's remove _wp_http_referer from the
1010
+		// $_SERVER[REQUEST_URI] global (its now in _req_data for route processing).
1011
+		$_SERVER['REQUEST_URI'] = remove_query_arg(
1012
+				'_wp_http_referer',
1013
+				wp_unslash($_SERVER['REQUEST_URI'])
1014
+		);
1015
+		if (! empty($func)) {
1016
+			if (is_array($func)) {
1017
+				list($class, $method) = $func;
1018
+			} elseif (strpos($func, '::') !== false) {
1019
+				list($class, $method) = explode('::', $func);
1020
+			} else {
1021
+				$class  = $this;
1022
+				$method = $func;
1023
+			}
1024
+			if (! (is_object($class) && $class === $this)) {
1025
+				// send along this admin page object for access by addons.
1026
+				$args['admin_page_object'] = $this;
1027
+			}
1028
+			if (
1029
+				//is it a method on a class that doesn't work?
1030
+				(
1031
+					(
1032
+						method_exists($class, $method)
1033
+						&& call_user_func_array(array($class, $method), $args) === false
1034
+					)
1035
+					&& (
1036
+						//is it a standalone function that doesn't work?
1037
+						function_exists($method)
1038
+						&& call_user_func_array(
1039
+							$func,
1040
+							array_merge(array('admin_page_object' => $this), $args)
1041
+						   ) === false
1042
+					)
1043
+				)
1044
+				|| (
1045
+					//is it neither a class method NOR a standalone function?
1046
+					! method_exists($class, $method)
1047
+					&& ! function_exists($method)
1048
+				)
1049
+			) {
1050
+				// user error msg
1051
+				$error_msg = esc_html__(
1052
+					'An error occurred. The  requested page route could not be found.',
1053
+					'event_espresso'
1054
+				);
1055
+				// developer error msg
1056
+				$error_msg .= '||';
1057
+				$error_msg .= sprintf(
1058
+					esc_html__(
1059
+						'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
1060
+						'event_espresso'
1061
+					),
1062
+					$method
1063
+				);
1064
+			}
1065
+			if (! empty($error_msg)) {
1066
+				throw new EE_Error($error_msg);
1067
+			}
1068
+		}
1069
+		// if we've routed and this route has a no headers route AND a sent_headers_route,
1070
+		// then we need to reset the routing properties to the new route.
1071
+		//now if UI request is FALSE and noheader is true AND we have a headers_sent_route in the route array then let's set UI_request to true because the no header route has a second func after headers have been sent.
1072
+		if ($this->_is_UI_request === false
1073
+			&& is_array($this->_route)
1074
+			&& ! empty($this->_route['headers_sent_route'])
1075
+		) {
1076
+			$this->_reset_routing_properties($this->_route['headers_sent_route']);
1077
+		}
1078
+	}
1079
+
1080
+
1081
+
1082
+	/**
1083
+	 * This method just allows the resetting of page properties in the case where a no headers
1084
+	 * route redirects to a headers route in its route config.
1085
+	 *
1086
+	 * @since   4.3.0
1087
+	 * @param  string $new_route New (non header) route to redirect to.
1088
+	 * @return   void
1089
+	 * @throws ReflectionException
1090
+	 * @throws InvalidArgumentException
1091
+	 * @throws InvalidInterfaceException
1092
+	 * @throws InvalidDataTypeException
1093
+	 * @throws EE_Error
1094
+	 */
1095
+	protected function _reset_routing_properties($new_route)
1096
+	{
1097
+		$this->_is_UI_request = true;
1098
+		//now we set the current route to whatever the headers_sent_route is set at
1099
+		$this->_req_data['action'] = $new_route;
1100
+		//rerun page setup
1101
+		$this->_page_setup();
1102
+	}
1103
+
1104
+
1105
+
1106
+	/**
1107
+	 * _add_query_arg
1108
+	 * adds nonce to array of arguments then calls WP add_query_arg function
1109
+	 *(internally just uses EEH_URL's function with the same name)
1110
+	 *
1111
+	 * @param array  $args
1112
+	 * @param string $url
1113
+	 * @param bool   $sticky                  if true, then the existing Request params will be appended to the
1114
+	 *                                        generated url in an associative array indexed by the key 'wp_referer';
1115
+	 *                                        Example usage: If the current page is:
1116
+	 *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
1117
+	 *                                        &action=default&event_id=20&month_range=March%202015
1118
+	 *                                        &_wpnonce=5467821
1119
+	 *                                        and you call:
1120
+	 *                                        EE_Admin_Page::add_query_args_and_nonce(
1121
+	 *                                        array(
1122
+	 *                                        'action' => 'resend_something',
1123
+	 *                                        'page=>espresso_registrations'
1124
+	 *                                        ),
1125
+	 *                                        $some_url,
1126
+	 *                                        true
1127
+	 *                                        );
1128
+	 *                                        It will produce a url in this structure:
1129
+	 *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
1130
+	 *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
1131
+	 *                                        month_range]=March%202015
1132
+	 * @param   bool $exclude_nonce           If true, the the nonce will be excluded from the generated nonce.
1133
+	 * @return string
1134
+	 */
1135
+	public static function add_query_args_and_nonce(
1136
+		$args = array(),
1137
+		$url = false,
1138
+		$sticky = false,
1139
+		$exclude_nonce = false
1140
+	) {
1141
+		//if there is a _wp_http_referer include the values from the request but only if sticky = true
1142
+		if ($sticky) {
1143
+			$request = $_REQUEST;
1144
+			unset($request['_wp_http_referer']);
1145
+			unset($request['wp_referer']);
1146
+			foreach ($request as $key => $value) {
1147
+				//do not add nonces
1148
+				if (strpos($key, 'nonce') !== false) {
1149
+					continue;
1150
+				}
1151
+				$args['wp_referer[' . $key . ']'] = $value;
1152
+			}
1153
+		}
1154
+		return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
1155
+	}
1156
+
1157
+
1158
+
1159
+	/**
1160
+	 * This returns a generated link that will load the related help tab.
1161
+	 *
1162
+	 * @param  string $help_tab_id the id for the connected help tab
1163
+	 * @param  string $icon_style  (optional) include css class for the style you want to use for the help icon.
1164
+	 * @param  string $help_text   (optional) send help text you want to use for the link if default not to be used
1165
+	 * @uses EEH_Template::get_help_tab_link()
1166
+	 * @return string              generated link
1167
+	 */
1168
+	protected function _get_help_tab_link($help_tab_id, $icon_style = '', $help_text = '')
1169
+	{
1170
+		return EEH_Template::get_help_tab_link(
1171
+			$help_tab_id,
1172
+			$this->page_slug,
1173
+			$this->_req_action,
1174
+			$icon_style,
1175
+			$help_text
1176
+		);
1177
+	}
1178
+
1179
+
1180
+
1181
+	/**
1182
+	 * _add_help_tabs
1183
+	 * Note child classes define their help tabs within the page_config array.
1184
+	 *
1185
+	 * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1186
+	 * @return void
1187
+	 * @throws DomainException
1188
+	 * @throws EE_Error
1189
+	 */
1190
+	protected function _add_help_tabs()
1191
+	{
1192
+		$tour_buttons = '';
1193
+		if (isset($this->_page_config[$this->_req_action])) {
1194
+			$config = $this->_page_config[$this->_req_action];
1195
+			//is there a help tour for the current route?  if there is let's setup the tour buttons
1196
+			if (isset($this->_help_tour[$this->_req_action])) {
1197
+				$tb           = array();
1198
+				$tour_buttons = '<div class="ee-abs-container"><div class="ee-help-tour-restart-buttons">';
1199
+				foreach ($this->_help_tour['tours'] as $tour) {
1200
+					//if this is the end tour then we don't need to setup a button
1201
+					if ($tour instanceof EE_Help_Tour_final_stop || ! $tour instanceof EE_Help_Tour) {
1202
+						continue;
1203
+					}
1204
+					$tb[] = '<button id="trigger-tour-'
1205
+							. $tour->get_slug()
1206
+							. '" class="button-primary trigger-ee-help-tour">'
1207
+							. $tour->get_label()
1208
+							. '</button>';
1209
+				}
1210
+				$tour_buttons .= implode('<br />', $tb);
1211
+				$tour_buttons .= '</div></div>';
1212
+			}
1213
+			// let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1214
+			if (is_array($config) && isset($config['help_sidebar'])) {
1215
+				//check that the callback given is valid
1216
+				if (! method_exists($this, $config['help_sidebar'])) {
1217
+					throw new EE_Error(
1218
+						sprintf(
1219
+							esc_html__(
1220
+								'The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Doublecheck the spelling and make sure this method exists for the class %s',
1221
+								'event_espresso'
1222
+							),
1223
+							$config['help_sidebar'],
1224
+							get_class($this)
1225
+						)
1226
+					);
1227
+				}
1228
+				$content = apply_filters(
1229
+					'FHEE__' . get_class($this) . '__add_help_tabs__help_sidebar',
1230
+					$this->{$config['help_sidebar']}()
1231
+				);
1232
+				$content .= $tour_buttons; //add help tour buttons.
1233
+				//do we have any help tours setup?  Cause if we do we want to add the buttons
1234
+				$this->_current_screen->set_help_sidebar($content);
1235
+			}
1236
+			//if we DON'T have config help sidebar and there ARE tour buttons then we'll just add the tour buttons to the sidebar.
1237
+			if (! isset($config['help_sidebar']) && ! empty($tour_buttons)) {
1238
+				$this->_current_screen->set_help_sidebar($tour_buttons);
1239
+			}
1240
+			//handle if no help_tabs are set so the sidebar will still show for the help tour buttons
1241
+			if (! isset($config['help_tabs']) && ! empty($tour_buttons)) {
1242
+				$_ht['id']      = $this->page_slug;
1243
+				$_ht['title']   = esc_html__('Help Tours', 'event_espresso');
1244
+				$_ht['content'] = '<p>' . esc_html__(
1245
+						'The buttons to the right allow you to start/restart any help tours available for this page',
1246
+						'event_espresso'
1247
+					) . '</p>';
1248
+				$this->_current_screen->add_help_tab($_ht);
1249
+			}
1250
+			if (! isset($config['help_tabs'])) {
1251
+				return;
1252
+			} //no help tabs for this route
1253
+			foreach ((array)$config['help_tabs'] as $tab_id => $cfg) {
1254
+				//we're here so there ARE help tabs!
1255
+				//make sure we've got what we need
1256
+				if (! isset($cfg['title'])) {
1257
+					throw new EE_Error(
1258
+						esc_html__(
1259
+							'The _page_config array is not set up properly for help tabs.  It is missing a title',
1260
+							'event_espresso'
1261
+						)
1262
+					);
1263
+				}
1264
+				if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1265
+					throw new EE_Error(
1266
+						esc_html__(
1267
+							'The _page_config array is not setup properly for help tabs. It is missing a either a filename reference, or a callback reference or a content reference so there is no way to know the content for the help tab',
1268
+							'event_espresso'
1269
+						)
1270
+					);
1271
+				}
1272
+				//first priority goes to content.
1273
+				if (! empty($cfg['content'])) {
1274
+					$content = ! empty($cfg['content']) ? $cfg['content'] : null;
1275
+					//second priority goes to filename
1276
+				} elseif (! empty($cfg['filename'])) {
1277
+					$file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1278
+					//it's possible that the file is located on decaf route (and above sets up for caf route, if this is the case then lets check decaf route too)
1279
+					$file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1280
+															 . basename($this->_get_dir())
1281
+															 . '/help_tabs/'
1282
+															 . $cfg['filename']
1283
+															 . '.help_tab.php' : $file_path;
1284
+					//if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1285
+					if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1286
+						EE_Error::add_error(
1287
+							sprintf(
1288
+								esc_html__(
1289
+									'The filename given for the help tab %s is not a valid file and there is no other configuration for the tab content.  Please check that the string you set for the help tab on this route (%s) is the correct spelling.  The file should be in %s',
1290
+									'event_espresso'
1291
+								),
1292
+								$tab_id,
1293
+								key($config),
1294
+								$file_path
1295
+							),
1296
+							__FILE__,
1297
+							__FUNCTION__,
1298
+							__LINE__
1299
+						);
1300
+						return;
1301
+					}
1302
+					$template_args['admin_page_obj'] = $this;
1303
+					$content = EEH_Template::display_template(
1304
+						$file_path,
1305
+						$template_args,
1306
+						true
1307
+					);
1308
+				} else {
1309
+					$content = '';
1310
+				}
1311
+				//check if callback is valid
1312
+				if (
1313
+					empty($content) && (
1314
+						! isset($cfg['callback']) || ! method_exists($this, $cfg['callback'])
1315
+					)
1316
+				) {
1317
+					EE_Error::add_error(
1318
+						sprintf(
1319
+							esc_html__(
1320
+								'The callback given for a %s help tab on this page does not content OR a corresponding method for generating the content.  Check the spelling or make sure the method is present.',
1321
+								'event_espresso'
1322
+							),
1323
+							$cfg['title']
1324
+						),
1325
+						__FILE__,
1326
+						__FUNCTION__,
1327
+						__LINE__
1328
+					);
1329
+					return;
1330
+				}
1331
+				//setup config array for help tab method
1332
+				$id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1333
+				$_ht = array(
1334
+					'id'       => $id,
1335
+					'title'    => $cfg['title'],
1336
+					'callback' => isset($cfg['callback']) && empty($content) ? array($this, $cfg['callback']) : null,
1337
+					'content'  => $content,
1338
+				);
1339
+				$this->_current_screen->add_help_tab($_ht);
1340
+			}
1341
+		}
1342
+	}
1343
+
1344
+
1345
+
1346
+	/**
1347
+	 * This basically checks loaded $_page_config property to see if there are any help_tours defined.  "help_tours" is
1348
+	 * an array with properties for setting up usage of the joyride plugin
1349
+	 *
1350
+	 * @link   http://zurb.com/playground/jquery-joyride-feature-tour-plugin
1351
+	 * @see    instructions regarding the format and construction of the "help_tour" array element is found in the
1352
+	 *         _set_page_config() comments
1353
+	 * @return void
1354
+	 * @throws EE_Error
1355
+	 * @throws InvalidArgumentException
1356
+	 * @throws InvalidDataTypeException
1357
+	 * @throws InvalidInterfaceException
1358
+	 */
1359
+	protected function _add_help_tour()
1360
+	{
1361
+		$tours            = array();
1362
+		$this->_help_tour = array();
1363
+		//exit early if help tours are turned off globally
1364
+		if ((defined('EE_DISABLE_HELP_TOURS') && EE_DISABLE_HELP_TOURS)
1365
+			|| ! EE_Registry::instance()->CFG->admin->help_tour_activation
1366
+		) {
1367
+			return;
1368
+		}
1369
+		//loop through _page_config to find any help_tour defined
1370
+		foreach ($this->_page_config as $route => $config) {
1371
+			//we're only going to set things up for this route
1372
+			if ($route !== $this->_req_action) {
1373
+				continue;
1374
+			}
1375
+			if (isset($config['help_tour'])) {
1376
+				foreach ($config['help_tour'] as $tour) {
1377
+					$file_path = $this->_get_dir() . '/help_tours/' . $tour . '.class.php';
1378
+					// let's see if we can get that file...
1379
+					// if not its possible this is a decaf route not set in caffeinated
1380
+					// so lets try and get the caffeinated equivalent
1381
+					$file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1382
+															 . basename($this->_get_dir())
1383
+															 . '/help_tours/'
1384
+															 . $tour
1385
+															 . '.class.php' : $file_path;
1386
+					//if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1387
+					if (! is_readable($file_path)) {
1388
+						EE_Error::add_error(
1389
+							sprintf(
1390
+								esc_html__(
1391
+									'The file path given for the help tour (%s) is not a valid path.  Please check that the string you set for the help tour on this route (%s) is the correct spelling',
1392
+									'event_espresso'
1393
+								),
1394
+								$file_path,
1395
+								$tour
1396
+							),
1397
+							__FILE__,
1398
+							__FUNCTION__,
1399
+							__LINE__
1400
+						);
1401
+						return;
1402
+					}
1403
+					require_once $file_path;
1404
+					if (! class_exists($tour)) {
1405
+						$error_msg[] = sprintf(
1406
+							esc_html__('Something went wrong with loading the %s Help Tour Class.', 'event_espresso'),
1407
+							$tour
1408
+						);
1409
+						$error_msg[] = $error_msg[0] . "\r\n" . sprintf(
1410
+								esc_html__(
1411
+									'There is no class in place for the %s help tour.%s Make sure you have <strong>%s</strong> defined in the "help_tour" array for the %s route of the % admin page.',
1412
+									'event_espresso'
1413
+								),
1414
+								$tour,
1415
+								'<br />',
1416
+								$tour,
1417
+								$this->_req_action,
1418
+								get_class($this)
1419
+							);
1420
+						throw new EE_Error(implode('||', $error_msg));
1421
+					}
1422
+					$tour_obj                   = new $tour($this->_is_caf);
1423
+					$tours[]                    = $tour_obj;
1424
+					$this->_help_tour[$route][] = EEH_Template::help_tour_stops_generator($tour_obj);
1425
+				}
1426
+				//let's inject the end tour stop element common to all pages... this will only get seen once per machine.
1427
+				$end_stop_tour              = new EE_Help_Tour_final_stop($this->_is_caf);
1428
+				$tours[]                    = $end_stop_tour;
1429
+				$this->_help_tour[$route][] = EEH_Template::help_tour_stops_generator($end_stop_tour);
1430
+			}
1431
+		}
1432
+		if (! empty($tours)) {
1433
+			$this->_help_tour['tours'] = $tours;
1434
+		}
1435
+		// that's it!  Now that the $_help_tours property is set (or not)
1436
+		// the scripts and html should be taken care of automatically.
1437
+	}
1438
+
1439
+
1440
+
1441
+	/**
1442
+	 * This simply sets up any qtips that have been defined in the page config
1443
+	 *
1444
+	 * @return void
1445
+	 */
1446
+	protected function _add_qtips()
1447
+	{
1448
+		if (isset($this->_route_config['qtips'])) {
1449
+			$qtips = (array)$this->_route_config['qtips'];
1450
+			//load qtip loader
1451
+			$path = array(
1452
+				$this->_get_dir() . '/qtips/',
1453
+				EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1454
+			);
1455
+			EEH_Qtip_Loader::instance()->register($qtips, $path);
1456
+		}
1457
+	}
1458
+
1459
+
1460
+
1461
+	/**
1462
+	 * _set_nav_tabs
1463
+	 * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you
1464
+	 * wish to add additional tabs or modify accordingly.
1465
+	 *
1466
+	 * @return void
1467
+	 * @throws InvalidArgumentException
1468
+	 * @throws InvalidInterfaceException
1469
+	 * @throws InvalidDataTypeException
1470
+	 */
1471
+	protected function _set_nav_tabs()
1472
+	{
1473
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1474
+		$i = 0;
1475
+		foreach ($this->_page_config as $slug => $config) {
1476
+			if (
1477
+				! is_array($config)
1478
+				|| (
1479
+					is_array($config)
1480
+					&& (
1481
+						(isset($config['nav']) && ! $config['nav'])
1482
+						|| ! isset($config['nav'])
1483
+					)
1484
+				)
1485
+			) {
1486
+				continue;
1487
+			}
1488
+			//no nav tab for this config
1489
+			//check for persistent flag
1490
+			if ($slug !== $this->_req_action && isset($config['nav']['persistent']) && ! $config['nav']['persistent']) {
1491
+				// nav tab is only to appear when route requested.
1492
+				continue;
1493
+			}
1494
+			if (! $this->check_user_access($slug, true)) {
1495
+				// no nav tab because current user does not have access.
1496
+				continue;
1497
+			}
1498
+			$css_class              = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1499
+			$this->_nav_tabs[$slug] = array(
1500
+				'url'       => isset($config['nav']['url'])
1501
+					? $config['nav']['url']
1502
+					: self::add_query_args_and_nonce(
1503
+						array('action' => $slug),
1504
+						$this->_admin_base_url
1505
+					),
1506
+				'link_text' => isset($config['nav']['label'])
1507
+					? $config['nav']['label']
1508
+					: ucwords(
1509
+						str_replace('_', ' ', $slug)
1510
+					),
1511
+				'css_class' => $this->_req_action === $slug ? $css_class . 'nav-tab-active' : $css_class,
1512
+				'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1513
+			);
1514
+			$i++;
1515
+		}
1516
+		//if $this->_nav_tabs is empty then lets set the default
1517
+		if (empty($this->_nav_tabs)) {
1518
+			$this->_nav_tabs[$this->_default_nav_tab_name] = array(
1519
+				'url'       => $this->_admin_base_url,
1520
+				'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1521
+				'css_class' => 'nav-tab-active',
1522
+				'order'     => 10,
1523
+			);
1524
+		}
1525
+		//now let's sort the tabs according to order
1526
+		usort($this->_nav_tabs, array($this, '_sort_nav_tabs'));
1527
+	}
1528
+
1529
+
1530
+
1531
+	/**
1532
+	 * _set_current_labels
1533
+	 * This method modifies the _labels property with any optional specific labels indicated in the _page_routes
1534
+	 * property array
1535
+	 *
1536
+	 * @return void
1537
+	 */
1538
+	private function _set_current_labels()
1539
+	{
1540
+		if (is_array($this->_route_config) && isset($this->_route_config['labels'])) {
1541
+			foreach ($this->_route_config['labels'] as $label => $text) {
1542
+				if (is_array($text)) {
1543
+					foreach ($text as $sublabel => $subtext) {
1544
+						$this->_labels[$label][$sublabel] = $subtext;
1545
+					}
1546
+				} else {
1547
+					$this->_labels[$label] = $text;
1548
+				}
1549
+			}
1550
+		}
1551
+	}
1552
+
1553
+
1554
+
1555
+	/**
1556
+	 *        verifies user access for this admin page
1557
+	 *
1558
+	 * @param string $route_to_check if present then the capability for the route matching this string is checked.
1559
+	 * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just
1560
+	 *                               return false if verify fail.
1561
+	 * @return bool
1562
+	 * @throws InvalidArgumentException
1563
+	 * @throws InvalidDataTypeException
1564
+	 * @throws InvalidInterfaceException
1565
+	 */
1566
+	public function check_user_access($route_to_check = '', $verify_only = false)
1567
+	{
1568
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1569
+		$route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1570
+		$capability     = ! empty($route_to_check) && isset($this->_page_routes[$route_to_check])
1571
+						  && is_array(
1572
+							  $this->_page_routes[$route_to_check]
1573
+						  )
1574
+						  && ! empty($this->_page_routes[$route_to_check]['capability'])
1575
+			? $this->_page_routes[$route_to_check]['capability'] : null;
1576
+		if (empty($capability) && empty($route_to_check)) {
1577
+			$capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options'
1578
+				: $this->_route['capability'];
1579
+		} else {
1580
+			$capability = empty($capability) ? 'manage_options' : $capability;
1581
+		}
1582
+		$id = is_array($this->_route) && ! empty($this->_route['obj_id']) ? $this->_route['obj_id'] : 0;
1583
+		if (
1584
+			! defined('DOING_AJAX')
1585
+			&& (
1586
+				! function_exists('is_admin')
1587
+				|| ! EE_Registry::instance()->CAP->current_user_can(
1588
+					$capability,
1589
+					$this->page_slug
1590
+					. '_'
1591
+					. $route_to_check,
1592
+					$id
1593
+				)
1594
+			)
1595
+		) {
1596
+			if ($verify_only) {
1597
+				return false;
1598
+			}
1599
+			if (is_user_logged_in()) {
1600
+				wp_die(__('You do not have access to this route.', 'event_espresso'));
1601
+			} else {
1602
+				return false;
1603
+			}
1604
+		}
1605
+		return true;
1606
+	}
1607
+
1608
+
1609
+
1610
+	/**
1611
+	 * admin_init_global
1612
+	 * This runs all the code that we want executed within the WP admin_init hook.
1613
+	 * This method executes for ALL EE Admin pages.
1614
+	 *
1615
+	 * @return void
1616
+	 */
1617
+	public function admin_init_global()
1618
+	{
1619
+	}
1620
+
1621
+
1622
+
1623
+	/**
1624
+	 * wp_loaded_global
1625
+	 * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an
1626
+	 * EE_Admin page and will execute on every EE Admin Page load
1627
+	 *
1628
+	 * @return void
1629
+	 */
1630
+	public function wp_loaded()
1631
+	{
1632
+	}
1633
+
1634
+
1635
+
1636
+	/**
1637
+	 * admin_notices
1638
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on
1639
+	 * ALL EE_Admin pages.
1640
+	 *
1641
+	 * @return void
1642
+	 */
1643
+	public function admin_notices_global()
1644
+	{
1645
+		$this->_display_no_javascript_warning();
1646
+		$this->_display_espresso_notices();
1647
+	}
1648
+
1649
+
1650
+
1651
+	public function network_admin_notices_global()
1652
+	{
1653
+		$this->_display_no_javascript_warning();
1654
+		$this->_display_espresso_notices();
1655
+	}
1656
+
1657
+
1658
+
1659
+	/**
1660
+	 * admin_footer_scripts_global
1661
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
1662
+	 * will apply on ALL EE_Admin pages.
1663
+	 *
1664
+	 * @return void
1665
+	 */
1666
+	public function admin_footer_scripts_global()
1667
+	{
1668
+		$this->_add_admin_page_ajax_loading_img();
1669
+		$this->_add_admin_page_overlay();
1670
+		//if metaboxes are present we need to add the nonce field
1671
+		if (
1672
+			 isset($this->_route_config['metaboxes'])
1673
+			 || isset($this->_route_config['list_table'])
1674
+			 || (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes'])
1675
+		) {
1676
+			wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1677
+			wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1678
+		}
1679
+	}
1680
+
1681
+
1682
+
1683
+	/**
1684
+	 * admin_footer_global
1685
+	 * Anything triggered by the wp 'admin_footer' wp hook should be put in here. This particular method will apply on
1686
+	 * ALL EE_Admin Pages.
1687
+	 *
1688
+	 * @return void
1689
+	 * @throws EE_Error
1690
+	 */
1691
+	public function admin_footer_global()
1692
+	{
1693
+		//dialog container for dialog helper
1694
+		$d_cont = '<div class="ee-admin-dialog-container auto-hide hidden">' . "\n";
1695
+		$d_cont .= '<div class="ee-notices"></div>';
1696
+		$d_cont .= '<div class="ee-admin-dialog-container-inner-content"></div>';
1697
+		$d_cont .= '</div>';
1698
+		echo $d_cont;
1699
+		//help tour stuff?
1700
+		if (isset($this->_help_tour[$this->_req_action])) {
1701
+			echo implode('<br />', $this->_help_tour[$this->_req_action]);
1702
+		}
1703
+		//current set timezone for timezone js
1704
+		echo '<span id="current_timezone" class="hidden">' . EEH_DTT_Helper::get_timezone() . '</span>';
1705
+	}
1706
+
1707
+
1708
+
1709
+	/**
1710
+	 * This function sees if there is a method for help popup content existing for the given route.  If there is then
1711
+	 * we'll use the retrieved array to output the content using the template. For child classes: If you want to have
1712
+	 * help popups then in your templates or your content you set "triggers" for the content using the
1713
+	 * "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method
1714
+	 * for the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup
1715
+	 * method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content
1716
+	 * for the
1717
+	 * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined
1718
+	 * "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1719
+	 *    'help_trigger_id' => array(
1720
+	 *        'title' => esc_html__('localized title for popup', 'event_espresso'),
1721
+	 *        'content' => esc_html__('localized content for popup', 'event_espresso')
1722
+	 *    )
1723
+	 * );
1724
+	 * Then the EE_Admin_Parent will take care of making sure that is setup properly on the correct route.
1725
+	 *
1726
+	 * @param array $help_array
1727
+	 * @param bool  $display
1728
+	 * @return string content
1729
+	 * @throws DomainException
1730
+	 * @throws EE_Error
1731
+	 */
1732
+	protected function _set_help_popup_content($help_array = array(), $display = false)
1733
+	{
1734
+		$content       = '';
1735
+		$help_array    = empty($help_array) ? $this->_get_help_content() : $help_array;
1736
+		//loop through the array and setup content
1737
+		foreach ($help_array as $trigger => $help) {
1738
+			//make sure the array is setup properly
1739
+			if (! isset($help['title']) || ! isset($help['content'])) {
1740
+				throw new EE_Error(
1741
+					esc_html__(
1742
+						'Does not look like the popup content array has been setup correctly.  Might want to double check that.  Read the comments for the _get_help_popup_content method found in "EE_Admin_Page" class',
1743
+						'event_espresso'
1744
+					)
1745
+				);
1746
+			}
1747
+			//we're good so let'd setup the template vars and then assign parsed template content to our content.
1748
+			$template_args = array(
1749
+				'help_popup_id'      => $trigger,
1750
+				'help_popup_title'   => $help['title'],
1751
+				'help_popup_content' => $help['content'],
1752
+			);
1753
+			$content       .= EEH_Template::display_template(
1754
+				EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1755
+				$template_args,
1756
+				true
1757
+			);
1758
+		}
1759
+		if ($display) {
1760
+			echo $content;
1761
+			return '';
1762
+		}
1763
+		return $content;
1764
+	}
1765
+
1766
+
1767
+
1768
+	/**
1769
+	 * All this does is retrieve the help content array if set by the EE_Admin_Page child
1770
+	 *
1771
+	 * @return array properly formatted array for help popup content
1772
+	 * @throws EE_Error
1773
+	 */
1774
+	private function _get_help_content()
1775
+	{
1776
+		//what is the method we're looking for?
1777
+		$method_name = '_help_popup_content_' . $this->_req_action;
1778
+		//if method doesn't exist let's get out.
1779
+		if (! method_exists($this, $method_name)) {
1780
+			return array();
1781
+		}
1782
+		//k we're good to go let's retrieve the help array
1783
+		$help_array = call_user_func(array($this, $method_name));
1784
+		//make sure we've got an array!
1785
+		if (! is_array($help_array)) {
1786
+			throw new EE_Error(
1787
+				esc_html__(
1788
+					'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
1789
+					'event_espresso'
1790
+				)
1791
+			);
1792
+		}
1793
+		return $help_array;
1794
+	}
1795
+
1796
+
1797
+
1798
+	/**
1799
+	 * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1800
+	 * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1801
+	 * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1802
+	 *
1803
+	 * @param string  $trigger_id reference for retrieving the trigger content for the popup
1804
+	 * @param boolean $display    if false then we return the trigger string
1805
+	 * @param array   $dimensions an array of dimensions for the box (array(h,w))
1806
+	 * @return string
1807
+	 * @throws DomainException
1808
+	 * @throws EE_Error
1809
+	 */
1810
+	protected function _set_help_trigger($trigger_id, $display = true, $dimensions = array('400', '640'))
1811
+	{
1812
+		if (defined('DOING_AJAX')) {
1813
+			return '';
1814
+		}
1815
+		//let's check and see if there is any content set for this popup.  If there isn't then we'll include a default title and content so that developers know something needs to be corrected
1816
+		$help_array   = $this->_get_help_content();
1817
+		$help_content = '';
1818
+		if (empty($help_array) || ! isset($help_array[$trigger_id])) {
1819
+			$help_array[$trigger_id] = array(
1820
+				'title'   => esc_html__('Missing Content', 'event_espresso'),
1821
+				'content' => esc_html__(
1822
+					'A trigger has been set that doesn\'t have any corresponding content. Make sure you have set the help content. (see the "_set_help_popup_content" method in the EE_Admin_Page for instructions.)',
1823
+					'event_espresso'
1824
+				),
1825
+			);
1826
+			$help_content            = $this->_set_help_popup_content($help_array, false);
1827
+		}
1828
+		//let's setup the trigger
1829
+		$content = '<a class="ee-dialog" href="?height='
1830
+				   . $dimensions[0]
1831
+				   . '&width='
1832
+				   . $dimensions[1]
1833
+				   . '&inlineId='
1834
+				   . $trigger_id
1835
+				   . '" target="_blank"><span class="question ee-help-popup-question"></span></a>';
1836
+		$content .= $help_content;
1837
+		if ($display) {
1838
+			echo $content;
1839
+			return  '';
1840
+		}
1841
+		return $content;
1842
+	}
1843
+
1844
+
1845
+
1846
+	/**
1847
+	 * _add_global_screen_options
1848
+	 * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1849
+	 * This particular method will add_screen_options on ALL EE_Admin Pages
1850
+	 *
1851
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1852
+	 *         see also WP_Screen object documents...
1853
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1854
+	 * @abstract
1855
+	 * @return void
1856
+	 */
1857
+	private function _add_global_screen_options()
1858
+	{
1859
+	}
1860
+
1861
+
1862
+
1863
+	/**
1864
+	 * _add_global_feature_pointers
1865
+	 * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1866
+	 * This particular method will implement feature pointers for ALL EE_Admin pages.
1867
+	 * Note: this is just a placeholder for now.  Implementation will come down the road
1868
+	 *
1869
+	 * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
1870
+	 *         extended) also see:
1871
+	 * @link   http://eamann.com/tech/wordpress-portland/
1872
+	 * @abstract
1873
+	 * @return void
1874
+	 */
1875
+	private function _add_global_feature_pointers()
1876
+	{
1877
+	}
1878
+
1879
+
1880
+
1881
+	/**
1882
+	 * load_global_scripts_styles
1883
+	 * The scripts and styles enqueued in here will be loaded on every EE Admin page
1884
+	 *
1885
+	 * @return void
1886
+	 * @throws EE_Error
1887
+	 */
1888
+	public function load_global_scripts_styles()
1889
+	{
1890
+		/** STYLES **/
1891
+		// add debugging styles
1892
+		if (WP_DEBUG) {
1893
+			add_action('admin_head', array($this, 'add_xdebug_style'));
1894
+		}
1895
+		// register all styles
1896
+		wp_register_style(
1897
+			'espresso-ui-theme',
1898
+			EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
1899
+			array(),
1900
+			EVENT_ESPRESSO_VERSION
1901
+		);
1902
+		wp_register_style('ee-admin-css', EE_ADMIN_URL . 'assets/ee-admin-page.css', array(), EVENT_ESPRESSO_VERSION);
1903
+		//helpers styles
1904
+		wp_register_style(
1905
+			'ee-text-links',
1906
+			EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.css',
1907
+			array(),
1908
+			EVENT_ESPRESSO_VERSION
1909
+		);
1910
+		/** SCRIPTS **/
1911
+		//register all scripts
1912
+		wp_register_script(
1913
+			'ee-dialog',
1914
+			EE_ADMIN_URL . 'assets/ee-dialog-helper.js',
1915
+			array('jquery', 'jquery-ui-draggable'),
1916
+			EVENT_ESPRESSO_VERSION,
1917
+			true
1918
+		);
1919
+		wp_register_script(
1920
+			'ee_admin_js',
1921
+			EE_ADMIN_URL . 'assets/ee-admin-page.js',
1922
+			array('espresso_core', 'ee-parse-uri', 'ee-dialog'),
1923
+			EVENT_ESPRESSO_VERSION,
1924
+			true
1925
+		);
1926
+		wp_register_script(
1927
+			'jquery-ui-timepicker-addon',
1928
+			EE_GLOBAL_ASSETS_URL . 'scripts/jquery-ui-timepicker-addon.js',
1929
+			array('jquery-ui-datepicker', 'jquery-ui-slider'),
1930
+			EVENT_ESPRESSO_VERSION,
1931
+			true
1932
+		);
1933
+		add_filter('FHEE_load_joyride', '__return_true');
1934
+		//script for sorting tables
1935
+		wp_register_script(
1936
+			'espresso_ajax_table_sorting',
1937
+			EE_ADMIN_URL . 'assets/espresso_ajax_table_sorting.js',
1938
+			array('ee_admin_js', 'jquery-ui-sortable'),
1939
+			EVENT_ESPRESSO_VERSION,
1940
+			true
1941
+		);
1942
+		//script for parsing uri's
1943
+		wp_register_script(
1944
+			'ee-parse-uri',
1945
+			EE_GLOBAL_ASSETS_URL . 'scripts/parseuri.js',
1946
+			array(),
1947
+			EVENT_ESPRESSO_VERSION,
1948
+			true
1949
+		);
1950
+		//and parsing associative serialized form elements
1951
+		wp_register_script(
1952
+			'ee-serialize-full-array',
1953
+			EE_GLOBAL_ASSETS_URL . 'scripts/jquery.serializefullarray.js',
1954
+			array('jquery'),
1955
+			EVENT_ESPRESSO_VERSION,
1956
+			true
1957
+		);
1958
+		//helpers scripts
1959
+		wp_register_script(
1960
+			'ee-text-links',
1961
+			EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.js',
1962
+			array('jquery'),
1963
+			EVENT_ESPRESSO_VERSION,
1964
+			true
1965
+		);
1966
+		wp_register_script(
1967
+			'ee-moment-core',
1968
+			EE_THIRD_PARTY_URL . 'moment/moment-with-locales.min.js',
1969
+			array(),
1970
+			EVENT_ESPRESSO_VERSION,
1971
+			true
1972
+		);
1973
+		wp_register_script(
1974
+			'ee-moment',
1975
+			EE_THIRD_PARTY_URL . 'moment/moment-timezone-with-data.min.js',
1976
+			array('ee-moment-core'),
1977
+			EVENT_ESPRESSO_VERSION,
1978
+			true
1979
+		);
1980
+		wp_register_script(
1981
+			'ee-datepicker',
1982
+			EE_ADMIN_URL . 'assets/ee-datepicker.js',
1983
+			array('jquery-ui-timepicker-addon', 'ee-moment'),
1984
+			EVENT_ESPRESSO_VERSION,
1985
+			true
1986
+		);
1987
+		//google charts
1988
+		wp_register_script(
1989
+			'google-charts',
1990
+			'https://www.gstatic.com/charts/loader.js',
1991
+			array(),
1992
+			EVENT_ESPRESSO_VERSION,
1993
+			false
1994
+		);
1995
+		// ENQUEUE ALL BASICS BY DEFAULT
1996
+		wp_enqueue_style('ee-admin-css');
1997
+		wp_enqueue_script('ee_admin_js');
1998
+		wp_enqueue_script('ee-accounting');
1999
+		wp_enqueue_script('jquery-validate');
2000
+		//taking care of metaboxes
2001
+		if (
2002
+			empty($this->_cpt_route)
2003
+			&& (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
2004
+		) {
2005
+			wp_enqueue_script('dashboard');
2006
+		}
2007
+		// LOCALIZED DATA
2008
+		//localize script for ajax lazy loading
2009
+		$lazy_loader_container_ids = apply_filters(
2010
+			'FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers',
2011
+			array('espresso_news_post_box_content')
2012
+		);
2013
+		wp_localize_script('ee_admin_js', 'eeLazyLoadingContainers', $lazy_loader_container_ids);
2014
+		/**
2015
+		 * help tour stuff
2016
+		 */
2017
+		if (! empty($this->_help_tour)) {
2018
+			//register the js for kicking things off
2019
+			wp_enqueue_script(
2020
+				'ee-help-tour',
2021
+				EE_ADMIN_URL . 'assets/ee-help-tour.js',
2022
+				array('jquery-joyride'),
2023
+				EVENT_ESPRESSO_VERSION,
2024
+				true
2025
+			);
2026
+			$tours = array();
2027
+			//setup tours for the js tour object
2028
+			foreach ($this->_help_tour['tours'] as $tour) {
2029
+				if ($tour instanceof EE_Help_Tour) {
2030
+					$tours[] = array(
2031
+						'id'      => $tour->get_slug(),
2032
+						'options' => $tour->get_options(),
2033
+					);
2034
+				}
2035
+			}
2036
+			wp_localize_script('ee-help-tour', 'EE_HELP_TOUR', array('tours' => $tours));
2037
+			//admin_footer_global will take care of making sure our help_tour skeleton gets printed via the info stored in $this->_help_tour
2038
+		}
2039
+	}
2040
+
2041
+
2042
+
2043
+	/**
2044
+	 *        admin_footer_scripts_eei18n_js_strings
2045
+	 *
2046
+	 * @return        void
2047
+	 */
2048
+	public function admin_footer_scripts_eei18n_js_strings()
2049
+	{
2050
+		EE_Registry::$i18n_js_strings['ajax_url']       = WP_AJAX_URL;
2051
+		EE_Registry::$i18n_js_strings['confirm_delete'] = esc_html__(
2052
+			'Are you absolutely sure you want to delete this item?\nThis action will delete ALL DATA associated with this item!!!\nThis can NOT be undone!!!',
2053
+			'event_espresso'
2054
+		);
2055
+		EE_Registry::$i18n_js_strings['January']        = esc_html__('January', 'event_espresso');
2056
+		EE_Registry::$i18n_js_strings['February']       = esc_html__('February', 'event_espresso');
2057
+		EE_Registry::$i18n_js_strings['March']          = esc_html__('March', 'event_espresso');
2058
+		EE_Registry::$i18n_js_strings['April']          = esc_html__('April', 'event_espresso');
2059
+		EE_Registry::$i18n_js_strings['May']            = esc_html__('May', 'event_espresso');
2060
+		EE_Registry::$i18n_js_strings['June']           = esc_html__('June', 'event_espresso');
2061
+		EE_Registry::$i18n_js_strings['July']           = esc_html__('July', 'event_espresso');
2062
+		EE_Registry::$i18n_js_strings['August']         = esc_html__('August', 'event_espresso');
2063
+		EE_Registry::$i18n_js_strings['September']      = esc_html__('September', 'event_espresso');
2064
+		EE_Registry::$i18n_js_strings['October']        = esc_html__('October', 'event_espresso');
2065
+		EE_Registry::$i18n_js_strings['November']       = esc_html__('November', 'event_espresso');
2066
+		EE_Registry::$i18n_js_strings['December']       = esc_html__('December', 'event_espresso');
2067
+		EE_Registry::$i18n_js_strings['Jan']            = esc_html__('Jan', 'event_espresso');
2068
+		EE_Registry::$i18n_js_strings['Feb']            = esc_html__('Feb', 'event_espresso');
2069
+		EE_Registry::$i18n_js_strings['Mar']            = esc_html__('Mar', 'event_espresso');
2070
+		EE_Registry::$i18n_js_strings['Apr']            = esc_html__('Apr', 'event_espresso');
2071
+		EE_Registry::$i18n_js_strings['May']            = esc_html__('May', 'event_espresso');
2072
+		EE_Registry::$i18n_js_strings['Jun']            = esc_html__('Jun', 'event_espresso');
2073
+		EE_Registry::$i18n_js_strings['Jul']            = esc_html__('Jul', 'event_espresso');
2074
+		EE_Registry::$i18n_js_strings['Aug']            = esc_html__('Aug', 'event_espresso');
2075
+		EE_Registry::$i18n_js_strings['Sep']            = esc_html__('Sep', 'event_espresso');
2076
+		EE_Registry::$i18n_js_strings['Oct']            = esc_html__('Oct', 'event_espresso');
2077
+		EE_Registry::$i18n_js_strings['Nov']            = esc_html__('Nov', 'event_espresso');
2078
+		EE_Registry::$i18n_js_strings['Dec']            = esc_html__('Dec', 'event_espresso');
2079
+		EE_Registry::$i18n_js_strings['Sunday']         = esc_html__('Sunday', 'event_espresso');
2080
+		EE_Registry::$i18n_js_strings['Monday']         = esc_html__('Monday', 'event_espresso');
2081
+		EE_Registry::$i18n_js_strings['Tuesday']        = esc_html__('Tuesday', 'event_espresso');
2082
+		EE_Registry::$i18n_js_strings['Wednesday']      = esc_html__('Wednesday', 'event_espresso');
2083
+		EE_Registry::$i18n_js_strings['Thursday']       = esc_html__('Thursday', 'event_espresso');
2084
+		EE_Registry::$i18n_js_strings['Friday']         = esc_html__('Friday', 'event_espresso');
2085
+		EE_Registry::$i18n_js_strings['Saturday']       = esc_html__('Saturday', 'event_espresso');
2086
+		EE_Registry::$i18n_js_strings['Sun']            = esc_html__('Sun', 'event_espresso');
2087
+		EE_Registry::$i18n_js_strings['Mon']            = esc_html__('Mon', 'event_espresso');
2088
+		EE_Registry::$i18n_js_strings['Tue']            = esc_html__('Tue', 'event_espresso');
2089
+		EE_Registry::$i18n_js_strings['Wed']            = esc_html__('Wed', 'event_espresso');
2090
+		EE_Registry::$i18n_js_strings['Thu']            = esc_html__('Thu', 'event_espresso');
2091
+		EE_Registry::$i18n_js_strings['Fri']            = esc_html__('Fri', 'event_espresso');
2092
+		EE_Registry::$i18n_js_strings['Sat']            = esc_html__('Sat', 'event_espresso');
2093
+	}
2094
+
2095
+
2096
+
2097
+	/**
2098
+	 *        load enhanced xdebug styles for ppl with failing eyesight
2099
+	 *
2100
+	 * @return        void
2101
+	 */
2102
+	public function add_xdebug_style()
2103
+	{
2104
+		echo '<style>.xdebug-error { font-size:1.5em; }</style>';
2105
+	}
2106
+
2107
+
2108
+	/************************/
2109
+	/** LIST TABLE METHODS **/
2110
+	/************************/
2111
+	/**
2112
+	 * this sets up the list table if the current view requires it.
2113
+	 *
2114
+	 * @return void
2115
+	 * @throws EE_Error
2116
+	 */
2117
+	protected function _set_list_table()
2118
+	{
2119
+		//first is this a list_table view?
2120
+		if (! isset($this->_route_config['list_table'])) {
2121
+			return;
2122
+		} //not a list_table view so get out.
2123
+		// list table functions are per view specific (because some admin pages might have more than one list table!)
2124
+		$list_table_view = '_set_list_table_views_' . $this->_req_action;
2125
+		if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2126
+			//user error msg
2127
+			$error_msg = esc_html__(
2128
+				'An error occurred. The requested list table views could not be found.',
2129
+				'event_espresso'
2130
+			);
2131
+			//developer error msg
2132
+			$error_msg .= '||' . sprintf(
2133
+					esc_html__(
2134
+						'List table views for "%s" route could not be setup. Check that you have the corresponding method, "%s" set up for defining list_table_views for this route.',
2135
+						'event_espresso'
2136
+					),
2137
+					$this->_req_action,
2138
+					$list_table_view
2139
+				);
2140
+			throw new EE_Error($error_msg);
2141
+		}
2142
+		//let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2143
+		$this->_views = apply_filters(
2144
+			'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2145
+			$this->_views
2146
+		);
2147
+		$this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2148
+		$this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2149
+		$this->_set_list_table_view();
2150
+		$this->_set_list_table_object();
2151
+	}
2152
+
2153
+
2154
+
2155
+	/**
2156
+	 * set current view for List Table
2157
+	 *
2158
+	 * @return void
2159
+	 */
2160
+	protected function _set_list_table_view()
2161
+	{
2162
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2163
+		// looking at active items or dumpster diving ?
2164
+		if (! isset($this->_req_data['status']) || ! array_key_exists($this->_req_data['status'], $this->_views)) {
2165
+			$this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
2166
+		} else {
2167
+			$this->_view = sanitize_key($this->_req_data['status']);
2168
+		}
2169
+	}
2170
+
2171
+
2172
+	/**
2173
+	 * _set_list_table_object
2174
+	 * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
2175
+	 *
2176
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2177
+	 * @throws \InvalidArgumentException
2178
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2179
+	 * @throws EE_Error
2180
+	 * @throws InvalidInterfaceException
2181
+	 */
2182
+	protected function _set_list_table_object()
2183
+	{
2184
+		if (isset($this->_route_config['list_table'])) {
2185
+			if (! class_exists($this->_route_config['list_table'])) {
2186
+				throw new EE_Error(
2187
+					sprintf(
2188
+						esc_html__(
2189
+							'The %s class defined for the list table does not exist.  Please check the spelling of the class ref in the $_page_config property on %s.',
2190
+							'event_espresso'
2191
+						),
2192
+						$this->_route_config['list_table'],
2193
+						get_class($this)
2194
+					)
2195
+				);
2196
+			}
2197
+			$this->_list_table_object = LoaderFactory::getLoader()->getShared(
2198
+				$this->_route_config['list_table'],
2199
+				array($this)
2200
+			);
2201
+		}
2202
+	}
2203
+
2204
+
2205
+
2206
+	/**
2207
+	 * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
2208
+	 *
2209
+	 * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
2210
+	 *                                                    urls.  The array should be indexed by the view it is being
2211
+	 *                                                    added to.
2212
+	 * @return array
2213
+	 */
2214
+	public function get_list_table_view_RLs($extra_query_args = array())
2215
+	{
2216
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2217
+		if (empty($this->_views)) {
2218
+			$this->_views = array();
2219
+		}
2220
+		// cycle thru views
2221
+		foreach ($this->_views as $key => $view) {
2222
+			$query_args = array();
2223
+			// check for current view
2224
+			$this->_views[$key]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2225
+			$query_args['action']                      = $this->_req_action;
2226
+			$query_args[$this->_req_action . '_nonce'] = wp_create_nonce($query_args['action'] . '_nonce');
2227
+			$query_args['status']                      = $view['slug'];
2228
+			//merge any other arguments sent in.
2229
+			if (isset($extra_query_args[$view['slug']])) {
2230
+				$query_args = array_merge($query_args, $extra_query_args[$view['slug']]);
2231
+			}
2232
+			$this->_views[$key]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2233
+		}
2234
+		return $this->_views;
2235
+	}
2236
+
2237
+
2238
+
2239
+	/**
2240
+	 * _entries_per_page_dropdown
2241
+	 * generates a drop down box for selecting the number of visible rows in an admin page list table
2242
+	 *
2243
+	 * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how
2244
+	 *         WP does it.
2245
+	 * @param int $max_entries total number of rows in the table
2246
+	 * @return string
2247
+	 */
2248
+	protected function _entries_per_page_dropdown($max_entries = 0)
2249
+	{
2250
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2251
+		$values   = array(10, 25, 50, 100);
2252
+		$per_page = (! empty($this->_req_data['per_page'])) ? absint($this->_req_data['per_page']) : 10;
2253
+		if ($max_entries) {
2254
+			$values[] = $max_entries;
2255
+			sort($values);
2256
+		}
2257
+		$entries_per_page_dropdown = '
2258 2258
 			<div id="entries-per-page-dv" class="alignleft actions">
2259 2259
 				<label class="hide-if-no-js">
2260 2260
 					Show
2261 2261
 					<select id="entries-per-page-slct" name="entries-per-page-slct">';
2262
-        foreach ($values as $value) {
2263
-            if ($value < $max_entries) {
2264
-                $selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2265
-                $entries_per_page_dropdown .= '
2262
+		foreach ($values as $value) {
2263
+			if ($value < $max_entries) {
2264
+				$selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2265
+				$entries_per_page_dropdown .= '
2266 2266
 						<option value="' . $value . '"' . $selected . '>' . $value . '&nbsp;&nbsp;</option>';
2267
-            }
2268
-        }
2269
-        $selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2270
-        $entries_per_page_dropdown .= '
2267
+			}
2268
+		}
2269
+		$selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2270
+		$entries_per_page_dropdown .= '
2271 2271
 						<option value="' . $max_entries . '"' . $selected . '>All&nbsp;&nbsp;</option>';
2272
-        $entries_per_page_dropdown .= '
2272
+		$entries_per_page_dropdown .= '
2273 2273
 					</select>
2274 2274
 					entries
2275 2275
 				</label>
2276 2276
 				<input id="entries-per-page-btn" class="button-secondary" type="submit" value="Go" >
2277 2277
 			</div>
2278 2278
 		';
2279
-        return $entries_per_page_dropdown;
2280
-    }
2281
-
2282
-
2283
-
2284
-    /**
2285
-     *        _set_search_attributes
2286
-     *
2287
-     * @return        void
2288
-     */
2289
-    public function _set_search_attributes()
2290
-    {
2291
-        $this->_template_args['search']['btn_label'] = sprintf(
2292
-            esc_html__('Search %s', 'event_espresso'),
2293
-            empty($this->_search_btn_label) ? $this->page_label
2294
-                : $this->_search_btn_label
2295
-        );
2296
-        $this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2297
-    }
2298
-
2299
-
2300
-
2301
-    /*** END LIST TABLE METHODS **/
2302
-
2303
-
2304
-
2305
-    /**
2306
-     * _add_registered_metaboxes
2307
-     *  this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
2308
-     *
2309
-     * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
2310
-     * @return void
2311
-     * @throws EE_Error
2312
-     */
2313
-    private function _add_registered_meta_boxes()
2314
-    {
2315
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2316
-        //we only add meta boxes if the page_route calls for it
2317
-        if (is_array($this->_route_config) && isset($this->_route_config['metaboxes'])
2318
-            && is_array(
2319
-                $this->_route_config['metaboxes']
2320
-            )
2321
-        ) {
2322
-            // this simply loops through the callbacks provided
2323
-            // and checks if there is a corresponding callback registered by the child
2324
-            // if there is then we go ahead and process the metabox loader.
2325
-            foreach ($this->_route_config['metaboxes'] as $metabox_callback) {
2326
-                // first check for Closures
2327
-                if ($metabox_callback instanceof Closure) {
2328
-                    $result = $metabox_callback();
2329
-                } elseif (is_array($metabox_callback) && isset($metabox_callback[0], $metabox_callback[1])) {
2330
-                    $result = call_user_func(array($metabox_callback[0], $metabox_callback[1]));
2331
-                } else {
2332
-                    $result = call_user_func(array($this, &$metabox_callback));
2333
-                }
2334
-                if ($result === false) {
2335
-                    // user error msg
2336
-                    $error_msg = esc_html__(
2337
-                            'An error occurred. The  requested metabox could not be found.',
2338
-                            'event_espresso'
2339
-                    );
2340
-                    // developer error msg
2341
-                    $error_msg .= '||' . sprintf(
2342
-                            esc_html__(
2343
-                                'The metabox with the string "%s" could not be called. Check that the spelling for method names and actions in the "_page_config[\'metaboxes\']" array are all correct.',
2344
-                                'event_espresso'
2345
-                            ),
2346
-                            $metabox_callback
2347
-                        );
2348
-                    throw new EE_Error($error_msg);
2349
-                }
2350
-            }
2351
-        }
2352
-    }
2353
-
2354
-
2355
-
2356
-    /**
2357
-     * _add_screen_columns
2358
-     * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as
2359
-     * the dynamic column template and we'll setup the column options for the page.
2360
-     *
2361
-     * @return void
2362
-     */
2363
-    private function _add_screen_columns()
2364
-    {
2365
-        if (
2366
-            is_array($this->_route_config)
2367
-            && isset($this->_route_config['columns'])
2368
-            && is_array($this->_route_config['columns'])
2369
-            && count($this->_route_config['columns']) === 2
2370
-        ) {
2371
-            add_screen_option(
2372
-                'layout_columns',
2373
-                array(
2374
-                    'max'     => (int)$this->_route_config['columns'][0],
2375
-                    'default' => (int)$this->_route_config['columns'][1],
2376
-                )
2377
-            );
2378
-            $this->_template_args['num_columns']                 = $this->_route_config['columns'][0];
2379
-            $screen_id                                           = $this->_current_screen->id;
2380
-            $screen_columns                                      = (int)get_user_option("screen_layout_{$screen_id}");
2381
-            $total_columns                                       = ! empty($screen_columns)
2382
-                ? $screen_columns
2383
-                : $this->_route_config['columns'][1];
2384
-            $this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2385
-            $this->_template_args['current_page']                = $this->_wp_page_slug;
2386
-            $this->_template_args['screen']                      = $this->_current_screen;
2387
-            $this->_column_template_path                         = EE_ADMIN_TEMPLATE
2388
-                                                                   . 'admin_details_metabox_column_wrapper.template.php';
2389
-            // finally if we don't have has_metaboxes set in the route config
2390
-            // let's make sure it IS set other wise the necessary hidden fields for this won't be loaded.
2391
-            $this->_route_config['has_metaboxes'] = true;
2392
-        }
2393
-    }
2394
-
2395
-
2396
-
2397
-    /** GLOBALLY AVAILABLE METABOXES **/
2398
-
2399
-
2400
-    /**
2401
-     * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply
2402
-     * referencing the callback in the _page_config array property.  This way you can be very specific about what pages
2403
-     * these get loaded on.
2404
-     */
2405
-    private function _espresso_news_post_box()
2406
-    {
2407
-        $news_box_title = apply_filters(
2408
-            'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2409
-            esc_html__('New @ Event Espresso', 'event_espresso')
2410
-        );
2411
-        add_meta_box(
2412
-            'espresso_news_post_box',
2413
-            $news_box_title,
2414
-            array(
2415
-                $this,
2416
-                'espresso_news_post_box',
2417
-            ),
2418
-            $this->_wp_page_slug,
2419
-            'side'
2420
-        );
2421
-    }
2422
-
2423
-
2424
-
2425
-    /**
2426
-     * Code for setting up espresso ratings request metabox.
2427
-     */
2428
-    protected function _espresso_ratings_request()
2429
-    {
2430
-        if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2431
-            return;
2432
-        }
2433
-        $ratings_box_title = apply_filters(
2434
-            'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2435
-            esc_html__('Keep Event Espresso Decaf Free', 'event_espresso')
2436
-        );
2437
-        add_meta_box(
2438
-            'espresso_ratings_request',
2439
-            $ratings_box_title,
2440
-            array(
2441
-                $this,
2442
-                'espresso_ratings_request',
2443
-            ),
2444
-            $this->_wp_page_slug,
2445
-            'side'
2446
-        );
2447
-    }
2448
-
2449
-
2450
-
2451
-    /**
2452
-     * Code for setting up espresso ratings request metabox content.
2453
-     *
2454
-     * @throws DomainException
2455
-     */
2456
-    public function espresso_ratings_request()
2457
-    {
2458
-        EEH_Template::display_template(
2459
-            EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php',
2460
-                array()
2461
-        );
2462
-    }
2463
-
2464
-
2465
-
2466
-    public static function cached_rss_display($rss_id, $url)
2467
-    {
2468
-        $loading    = '<p class="widget-loading hide-if-no-js">'
2469
-                      . __('Loading&#8230;')
2470
-                      . '</p><p class="hide-if-js">'
2471
-                      . esc_html__('This widget requires JavaScript.')
2472
-                      . '</p>';
2473
-        $pre        = '<div class="espresso-rss-display">' . "\n\t";
2474
-        $pre        .= '<span id="' . $rss_id . '_url" class="hidden">' . $url . '</span>';
2475
-        $post       = '</div>' . "\n";
2476
-        $cache_key  = 'ee_rss_' . md5($rss_id);
2477
-        $output = get_transient($cache_key);
2478
-        if ($output !== false) {
2479
-            echo $pre . $output . $post;
2480
-            return true;
2481
-        }
2482
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2483
-            echo $pre . $loading . $post;
2484
-            return false;
2485
-        }
2486
-        ob_start();
2487
-        wp_widget_rss_output($url, array('show_date' => 0, 'items' => 5));
2488
-        set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
2489
-        return true;
2490
-    }
2491
-
2492
-
2493
-
2494
-    public function espresso_news_post_box()
2495
-    {
2496
-        ?>
2279
+		return $entries_per_page_dropdown;
2280
+	}
2281
+
2282
+
2283
+
2284
+	/**
2285
+	 *        _set_search_attributes
2286
+	 *
2287
+	 * @return        void
2288
+	 */
2289
+	public function _set_search_attributes()
2290
+	{
2291
+		$this->_template_args['search']['btn_label'] = sprintf(
2292
+			esc_html__('Search %s', 'event_espresso'),
2293
+			empty($this->_search_btn_label) ? $this->page_label
2294
+				: $this->_search_btn_label
2295
+		);
2296
+		$this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2297
+	}
2298
+
2299
+
2300
+
2301
+	/*** END LIST TABLE METHODS **/
2302
+
2303
+
2304
+
2305
+	/**
2306
+	 * _add_registered_metaboxes
2307
+	 *  this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
2308
+	 *
2309
+	 * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
2310
+	 * @return void
2311
+	 * @throws EE_Error
2312
+	 */
2313
+	private function _add_registered_meta_boxes()
2314
+	{
2315
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2316
+		//we only add meta boxes if the page_route calls for it
2317
+		if (is_array($this->_route_config) && isset($this->_route_config['metaboxes'])
2318
+			&& is_array(
2319
+				$this->_route_config['metaboxes']
2320
+			)
2321
+		) {
2322
+			// this simply loops through the callbacks provided
2323
+			// and checks if there is a corresponding callback registered by the child
2324
+			// if there is then we go ahead and process the metabox loader.
2325
+			foreach ($this->_route_config['metaboxes'] as $metabox_callback) {
2326
+				// first check for Closures
2327
+				if ($metabox_callback instanceof Closure) {
2328
+					$result = $metabox_callback();
2329
+				} elseif (is_array($metabox_callback) && isset($metabox_callback[0], $metabox_callback[1])) {
2330
+					$result = call_user_func(array($metabox_callback[0], $metabox_callback[1]));
2331
+				} else {
2332
+					$result = call_user_func(array($this, &$metabox_callback));
2333
+				}
2334
+				if ($result === false) {
2335
+					// user error msg
2336
+					$error_msg = esc_html__(
2337
+							'An error occurred. The  requested metabox could not be found.',
2338
+							'event_espresso'
2339
+					);
2340
+					// developer error msg
2341
+					$error_msg .= '||' . sprintf(
2342
+							esc_html__(
2343
+								'The metabox with the string "%s" could not be called. Check that the spelling for method names and actions in the "_page_config[\'metaboxes\']" array are all correct.',
2344
+								'event_espresso'
2345
+							),
2346
+							$metabox_callback
2347
+						);
2348
+					throw new EE_Error($error_msg);
2349
+				}
2350
+			}
2351
+		}
2352
+	}
2353
+
2354
+
2355
+
2356
+	/**
2357
+	 * _add_screen_columns
2358
+	 * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as
2359
+	 * the dynamic column template and we'll setup the column options for the page.
2360
+	 *
2361
+	 * @return void
2362
+	 */
2363
+	private function _add_screen_columns()
2364
+	{
2365
+		if (
2366
+			is_array($this->_route_config)
2367
+			&& isset($this->_route_config['columns'])
2368
+			&& is_array($this->_route_config['columns'])
2369
+			&& count($this->_route_config['columns']) === 2
2370
+		) {
2371
+			add_screen_option(
2372
+				'layout_columns',
2373
+				array(
2374
+					'max'     => (int)$this->_route_config['columns'][0],
2375
+					'default' => (int)$this->_route_config['columns'][1],
2376
+				)
2377
+			);
2378
+			$this->_template_args['num_columns']                 = $this->_route_config['columns'][0];
2379
+			$screen_id                                           = $this->_current_screen->id;
2380
+			$screen_columns                                      = (int)get_user_option("screen_layout_{$screen_id}");
2381
+			$total_columns                                       = ! empty($screen_columns)
2382
+				? $screen_columns
2383
+				: $this->_route_config['columns'][1];
2384
+			$this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2385
+			$this->_template_args['current_page']                = $this->_wp_page_slug;
2386
+			$this->_template_args['screen']                      = $this->_current_screen;
2387
+			$this->_column_template_path                         = EE_ADMIN_TEMPLATE
2388
+																   . 'admin_details_metabox_column_wrapper.template.php';
2389
+			// finally if we don't have has_metaboxes set in the route config
2390
+			// let's make sure it IS set other wise the necessary hidden fields for this won't be loaded.
2391
+			$this->_route_config['has_metaboxes'] = true;
2392
+		}
2393
+	}
2394
+
2395
+
2396
+
2397
+	/** GLOBALLY AVAILABLE METABOXES **/
2398
+
2399
+
2400
+	/**
2401
+	 * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply
2402
+	 * referencing the callback in the _page_config array property.  This way you can be very specific about what pages
2403
+	 * these get loaded on.
2404
+	 */
2405
+	private function _espresso_news_post_box()
2406
+	{
2407
+		$news_box_title = apply_filters(
2408
+			'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2409
+			esc_html__('New @ Event Espresso', 'event_espresso')
2410
+		);
2411
+		add_meta_box(
2412
+			'espresso_news_post_box',
2413
+			$news_box_title,
2414
+			array(
2415
+				$this,
2416
+				'espresso_news_post_box',
2417
+			),
2418
+			$this->_wp_page_slug,
2419
+			'side'
2420
+		);
2421
+	}
2422
+
2423
+
2424
+
2425
+	/**
2426
+	 * Code for setting up espresso ratings request metabox.
2427
+	 */
2428
+	protected function _espresso_ratings_request()
2429
+	{
2430
+		if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2431
+			return;
2432
+		}
2433
+		$ratings_box_title = apply_filters(
2434
+			'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2435
+			esc_html__('Keep Event Espresso Decaf Free', 'event_espresso')
2436
+		);
2437
+		add_meta_box(
2438
+			'espresso_ratings_request',
2439
+			$ratings_box_title,
2440
+			array(
2441
+				$this,
2442
+				'espresso_ratings_request',
2443
+			),
2444
+			$this->_wp_page_slug,
2445
+			'side'
2446
+		);
2447
+	}
2448
+
2449
+
2450
+
2451
+	/**
2452
+	 * Code for setting up espresso ratings request metabox content.
2453
+	 *
2454
+	 * @throws DomainException
2455
+	 */
2456
+	public function espresso_ratings_request()
2457
+	{
2458
+		EEH_Template::display_template(
2459
+			EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php',
2460
+				array()
2461
+		);
2462
+	}
2463
+
2464
+
2465
+
2466
+	public static function cached_rss_display($rss_id, $url)
2467
+	{
2468
+		$loading    = '<p class="widget-loading hide-if-no-js">'
2469
+					  . __('Loading&#8230;')
2470
+					  . '</p><p class="hide-if-js">'
2471
+					  . esc_html__('This widget requires JavaScript.')
2472
+					  . '</p>';
2473
+		$pre        = '<div class="espresso-rss-display">' . "\n\t";
2474
+		$pre        .= '<span id="' . $rss_id . '_url" class="hidden">' . $url . '</span>';
2475
+		$post       = '</div>' . "\n";
2476
+		$cache_key  = 'ee_rss_' . md5($rss_id);
2477
+		$output = get_transient($cache_key);
2478
+		if ($output !== false) {
2479
+			echo $pre . $output . $post;
2480
+			return true;
2481
+		}
2482
+		if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2483
+			echo $pre . $loading . $post;
2484
+			return false;
2485
+		}
2486
+		ob_start();
2487
+		wp_widget_rss_output($url, array('show_date' => 0, 'items' => 5));
2488
+		set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
2489
+		return true;
2490
+	}
2491
+
2492
+
2493
+
2494
+	public function espresso_news_post_box()
2495
+	{
2496
+		?>
2497 2497
         <div class="padding">
2498 2498
             <div id="espresso_news_post_box_content" class="infolinks">
2499 2499
                 <?php
2500
-                // Get RSS Feed(s)
2501
-                self::cached_rss_display(
2502
-                    'espresso_news_post_box_content',
2503
-                    urlencode(
2504
-                        apply_filters(
2505
-                            'FHEE__EE_Admin_Page__espresso_news_post_box__feed_url',
2506
-                            'http://eventespresso.com/feed/'
2507
-                        )
2508
-                    )
2509
-                );
2510
-                ?>
2500
+				// Get RSS Feed(s)
2501
+				self::cached_rss_display(
2502
+					'espresso_news_post_box_content',
2503
+					urlencode(
2504
+						apply_filters(
2505
+							'FHEE__EE_Admin_Page__espresso_news_post_box__feed_url',
2506
+							'http://eventespresso.com/feed/'
2507
+						)
2508
+					)
2509
+				);
2510
+				?>
2511 2511
             </div>
2512 2512
             <?php do_action('AHEE__EE_Admin_Page__espresso_news_post_box__after_content'); ?>
2513 2513
         </div>
2514 2514
         <?php
2515
-    }
2516
-
2517
-
2518
-
2519
-    private function _espresso_links_post_box()
2520
-    {
2521
-        //Hiding until we actually have content to put in here...
2522
-        //add_meta_box('espresso_links_post_box', esc_html__('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2523
-    }
2524
-
2525
-
2526
-
2527
-    public function espresso_links_post_box()
2528
-    {
2529
-        //Hiding until we actually have content to put in here...
2530
-        // EEH_Template::display_template(
2531
-        //     EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php'
2532
-        // );
2533
-    }
2534
-
2535
-
2536
-
2537
-    protected function _espresso_sponsors_post_box()
2538
-    {
2539
-        if (apply_filters('FHEE_show_sponsors_meta_box', true)) {
2540
-            add_meta_box(
2541
-                'espresso_sponsors_post_box',
2542
-                esc_html__('Event Espresso Highlights', 'event_espresso'),
2543
-                array($this, 'espresso_sponsors_post_box'),
2544
-                $this->_wp_page_slug,
2545
-                'side'
2546
-            );
2547
-        }
2548
-    }
2549
-
2550
-
2551
-
2552
-    public function espresso_sponsors_post_box()
2553
-    {
2554
-        EEH_Template::display_template(
2555
-            EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2556
-        );
2557
-    }
2558
-
2559
-
2560
-
2561
-    private function _publish_post_box()
2562
-    {
2563
-        $meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2564
-        // if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2565
-        // then we'll use that for the metabox label.
2566
-        // Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2567
-        if (! empty($this->_labels['publishbox'])) {
2568
-            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][$this->_req_action]
2569
-                : $this->_labels['publishbox'];
2570
-        } else {
2571
-            $box_label = esc_html__('Publish', 'event_espresso');
2572
-        }
2573
-        $box_label = apply_filters(
2574
-            'FHEE__EE_Admin_Page___publish_post_box__box_label',
2575
-            $box_label,
2576
-            $this->_req_action,
2577
-            $this
2578
-        );
2579
-        add_meta_box(
2580
-            $meta_box_ref,
2581
-            $box_label,
2582
-            array($this, 'editor_overview'),
2583
-            $this->_current_screen->id,
2584
-            'side',
2585
-            'high'
2586
-        );
2587
-    }
2588
-
2589
-
2590
-
2591
-    public function editor_overview()
2592
-    {
2593
-        //if we have extra content set let's add it in if not make sure its empty
2594
-        $this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2595
-            ? $this->_template_args['publish_box_extra_content']
2596
-            : '';
2597
-        echo EEH_Template::display_template(
2598
-            EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2599
-            $this->_template_args,
2600
-            true
2601
-        );
2602
-    }
2603
-
2604
-
2605
-    /** end of globally available metaboxes section **/
2606
-
2607
-
2608
-
2609
-    /**
2610
-     * Public wrapper for the protected method.  Allows plugins/addons to externally call the
2611
-     * protected method.
2612
-     *
2613
-     * @see   $this->_set_publish_post_box_vars for param details
2614
-     * @since 4.6.0
2615
-     * @param string $name
2616
-     * @param int    $id
2617
-     * @param bool   $delete
2618
-     * @param string $save_close_redirect_URL
2619
-     * @param bool   $both_btns
2620
-     * @throws EE_Error
2621
-     * @throws InvalidArgumentException
2622
-     * @throws InvalidDataTypeException
2623
-     * @throws InvalidInterfaceException
2624
-     */
2625
-    public function set_publish_post_box_vars(
2626
-        $name = '',
2627
-        $id = 0,
2628
-        $delete = false,
2629
-        $save_close_redirect_URL = '',
2630
-        $both_btns = true
2631
-    ) {
2632
-        $this->_set_publish_post_box_vars(
2633
-            $name,
2634
-            $id,
2635
-            $delete,
2636
-            $save_close_redirect_URL,
2637
-            $both_btns
2638
-        );
2639
-    }
2640
-
2641
-
2642
-
2643
-    /**
2644
-     * Sets the _template_args arguments used by the _publish_post_box shortcut
2645
-     * Note: currently there is no validation for this.  However if you want the delete button, the
2646
-     * save, and save and close buttons to work properly, then you will want to include a
2647
-     * values for the name and id arguments.
2648
-     *
2649
-     * @todo  Add in validation for name/id arguments.
2650
-     * @param    string  $name                    key used for the action ID (i.e. event_id)
2651
-     * @param    int     $id                      id attached to the item published
2652
-     * @param    string  $delete                  page route callback for the delete action
2653
-     * @param    string  $save_close_redirect_URL custom URL to redirect to after Save & Close has been completed
2654
-     * @param    boolean $both_btns               whether to display BOTH the "Save & Close" and "Save" buttons or just
2655
-     *                                            the Save button
2656
-     * @throws EE_Error
2657
-     * @throws InvalidArgumentException
2658
-     * @throws InvalidDataTypeException
2659
-     * @throws InvalidInterfaceException
2660
-     */
2661
-    protected function _set_publish_post_box_vars(
2662
-        $name = '',
2663
-        $id = 0,
2664
-        $delete = '',
2665
-        $save_close_redirect_URL = '',
2666
-        $both_btns = true
2667
-    ) {
2668
-        // if Save & Close, use a custom redirect URL or default to the main page?
2669
-        $save_close_redirect_URL = ! empty($save_close_redirect_URL)
2670
-            ? $save_close_redirect_URL
2671
-            : $this->_admin_base_url;
2672
-        // create the Save & Close and Save buttons
2673
-        $this->_set_save_buttons($both_btns, array(), array(), $save_close_redirect_URL);
2674
-        //if we have extra content set let's add it in if not make sure its empty
2675
-        $this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2676
-            ? $this->_template_args['publish_box_extra_content']
2677
-            : '';
2678
-        if ($delete && ! empty($id)) {
2679
-            //make sure we have a default if just true is sent.
2680
-            $delete           = ! empty($delete) ? $delete : 'delete';
2681
-            $delete_link_args = array($name => $id);
2682
-            $delete           = $this->get_action_link_or_button(
2683
-                $delete,
2684
-                $delete,
2685
-                $delete_link_args,
2686
-                'submitdelete deletion',
2687
-                '',
2688
-                false
2689
-            );
2690
-        }
2691
-        $this->_template_args['publish_delete_link'] = ! empty($id) ? $delete : '';
2692
-        if (! empty($name) && ! empty($id)) {
2693
-            $hidden_field_arr[$name] = array(
2694
-                'type'  => 'hidden',
2695
-                'value' => $id,
2696
-            );
2697
-            $hf                      = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2698
-        } else {
2699
-            $hf = '';
2700
-        }
2701
-        // add hidden field
2702
-        $this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2703
-            ? $hf[$name]['field']
2704
-            : $hf;
2705
-    }
2706
-
2707
-
2708
-
2709
-    /**
2710
-     * displays an error message to ppl who have javascript disabled
2711
-     *
2712
-     * @return void
2713
-     */
2714
-    private function _display_no_javascript_warning()
2715
-    {
2716
-        ?>
2515
+	}
2516
+
2517
+
2518
+
2519
+	private function _espresso_links_post_box()
2520
+	{
2521
+		//Hiding until we actually have content to put in here...
2522
+		//add_meta_box('espresso_links_post_box', esc_html__('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2523
+	}
2524
+
2525
+
2526
+
2527
+	public function espresso_links_post_box()
2528
+	{
2529
+		//Hiding until we actually have content to put in here...
2530
+		// EEH_Template::display_template(
2531
+		//     EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php'
2532
+		// );
2533
+	}
2534
+
2535
+
2536
+
2537
+	protected function _espresso_sponsors_post_box()
2538
+	{
2539
+		if (apply_filters('FHEE_show_sponsors_meta_box', true)) {
2540
+			add_meta_box(
2541
+				'espresso_sponsors_post_box',
2542
+				esc_html__('Event Espresso Highlights', 'event_espresso'),
2543
+				array($this, 'espresso_sponsors_post_box'),
2544
+				$this->_wp_page_slug,
2545
+				'side'
2546
+			);
2547
+		}
2548
+	}
2549
+
2550
+
2551
+
2552
+	public function espresso_sponsors_post_box()
2553
+	{
2554
+		EEH_Template::display_template(
2555
+			EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2556
+		);
2557
+	}
2558
+
2559
+
2560
+
2561
+	private function _publish_post_box()
2562
+	{
2563
+		$meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2564
+		// if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2565
+		// then we'll use that for the metabox label.
2566
+		// Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2567
+		if (! empty($this->_labels['publishbox'])) {
2568
+			$box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][$this->_req_action]
2569
+				: $this->_labels['publishbox'];
2570
+		} else {
2571
+			$box_label = esc_html__('Publish', 'event_espresso');
2572
+		}
2573
+		$box_label = apply_filters(
2574
+			'FHEE__EE_Admin_Page___publish_post_box__box_label',
2575
+			$box_label,
2576
+			$this->_req_action,
2577
+			$this
2578
+		);
2579
+		add_meta_box(
2580
+			$meta_box_ref,
2581
+			$box_label,
2582
+			array($this, 'editor_overview'),
2583
+			$this->_current_screen->id,
2584
+			'side',
2585
+			'high'
2586
+		);
2587
+	}
2588
+
2589
+
2590
+
2591
+	public function editor_overview()
2592
+	{
2593
+		//if we have extra content set let's add it in if not make sure its empty
2594
+		$this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2595
+			? $this->_template_args['publish_box_extra_content']
2596
+			: '';
2597
+		echo EEH_Template::display_template(
2598
+			EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2599
+			$this->_template_args,
2600
+			true
2601
+		);
2602
+	}
2603
+
2604
+
2605
+	/** end of globally available metaboxes section **/
2606
+
2607
+
2608
+
2609
+	/**
2610
+	 * Public wrapper for the protected method.  Allows plugins/addons to externally call the
2611
+	 * protected method.
2612
+	 *
2613
+	 * @see   $this->_set_publish_post_box_vars for param details
2614
+	 * @since 4.6.0
2615
+	 * @param string $name
2616
+	 * @param int    $id
2617
+	 * @param bool   $delete
2618
+	 * @param string $save_close_redirect_URL
2619
+	 * @param bool   $both_btns
2620
+	 * @throws EE_Error
2621
+	 * @throws InvalidArgumentException
2622
+	 * @throws InvalidDataTypeException
2623
+	 * @throws InvalidInterfaceException
2624
+	 */
2625
+	public function set_publish_post_box_vars(
2626
+		$name = '',
2627
+		$id = 0,
2628
+		$delete = false,
2629
+		$save_close_redirect_URL = '',
2630
+		$both_btns = true
2631
+	) {
2632
+		$this->_set_publish_post_box_vars(
2633
+			$name,
2634
+			$id,
2635
+			$delete,
2636
+			$save_close_redirect_URL,
2637
+			$both_btns
2638
+		);
2639
+	}
2640
+
2641
+
2642
+
2643
+	/**
2644
+	 * Sets the _template_args arguments used by the _publish_post_box shortcut
2645
+	 * Note: currently there is no validation for this.  However if you want the delete button, the
2646
+	 * save, and save and close buttons to work properly, then you will want to include a
2647
+	 * values for the name and id arguments.
2648
+	 *
2649
+	 * @todo  Add in validation for name/id arguments.
2650
+	 * @param    string  $name                    key used for the action ID (i.e. event_id)
2651
+	 * @param    int     $id                      id attached to the item published
2652
+	 * @param    string  $delete                  page route callback for the delete action
2653
+	 * @param    string  $save_close_redirect_URL custom URL to redirect to after Save & Close has been completed
2654
+	 * @param    boolean $both_btns               whether to display BOTH the "Save & Close" and "Save" buttons or just
2655
+	 *                                            the Save button
2656
+	 * @throws EE_Error
2657
+	 * @throws InvalidArgumentException
2658
+	 * @throws InvalidDataTypeException
2659
+	 * @throws InvalidInterfaceException
2660
+	 */
2661
+	protected function _set_publish_post_box_vars(
2662
+		$name = '',
2663
+		$id = 0,
2664
+		$delete = '',
2665
+		$save_close_redirect_URL = '',
2666
+		$both_btns = true
2667
+	) {
2668
+		// if Save & Close, use a custom redirect URL or default to the main page?
2669
+		$save_close_redirect_URL = ! empty($save_close_redirect_URL)
2670
+			? $save_close_redirect_URL
2671
+			: $this->_admin_base_url;
2672
+		// create the Save & Close and Save buttons
2673
+		$this->_set_save_buttons($both_btns, array(), array(), $save_close_redirect_URL);
2674
+		//if we have extra content set let's add it in if not make sure its empty
2675
+		$this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2676
+			? $this->_template_args['publish_box_extra_content']
2677
+			: '';
2678
+		if ($delete && ! empty($id)) {
2679
+			//make sure we have a default if just true is sent.
2680
+			$delete           = ! empty($delete) ? $delete : 'delete';
2681
+			$delete_link_args = array($name => $id);
2682
+			$delete           = $this->get_action_link_or_button(
2683
+				$delete,
2684
+				$delete,
2685
+				$delete_link_args,
2686
+				'submitdelete deletion',
2687
+				'',
2688
+				false
2689
+			);
2690
+		}
2691
+		$this->_template_args['publish_delete_link'] = ! empty($id) ? $delete : '';
2692
+		if (! empty($name) && ! empty($id)) {
2693
+			$hidden_field_arr[$name] = array(
2694
+				'type'  => 'hidden',
2695
+				'value' => $id,
2696
+			);
2697
+			$hf                      = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2698
+		} else {
2699
+			$hf = '';
2700
+		}
2701
+		// add hidden field
2702
+		$this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2703
+			? $hf[$name]['field']
2704
+			: $hf;
2705
+	}
2706
+
2707
+
2708
+
2709
+	/**
2710
+	 * displays an error message to ppl who have javascript disabled
2711
+	 *
2712
+	 * @return void
2713
+	 */
2714
+	private function _display_no_javascript_warning()
2715
+	{
2716
+		?>
2717 2717
         <noscript>
2718 2718
             <div id="no-js-message" class="error">
2719 2719
                 <p style="font-size:1.3em;">
2720 2720
                     <span style="color:red;"><?php esc_html_e('Warning!', 'event_espresso'); ?></span>
2721 2721
                     <?php esc_html_e(
2722
-                        'Javascript is currently turned off for your browser. Javascript must be enabled in order for all of the features on this page to function properly. Please turn your javascript back on.',
2723
-                        'event_espresso'
2724
-                    ); ?>
2722
+						'Javascript is currently turned off for your browser. Javascript must be enabled in order for all of the features on this page to function properly. Please turn your javascript back on.',
2723
+						'event_espresso'
2724
+					); ?>
2725 2725
                 </p>
2726 2726
             </div>
2727 2727
         </noscript>
2728 2728
         <?php
2729
-    }
2729
+	}
2730 2730
 
2731 2731
 
2732 2732
 
2733
-    /**
2734
-     * displays espresso success and/or error notices
2735
-     *
2736
-     * @return void
2737
-     */
2738
-    private function _display_espresso_notices()
2739
-    {
2740
-        $notices = $this->_get_transient(true);
2741
-        echo stripslashes($notices);
2742
-    }
2733
+	/**
2734
+	 * displays espresso success and/or error notices
2735
+	 *
2736
+	 * @return void
2737
+	 */
2738
+	private function _display_espresso_notices()
2739
+	{
2740
+		$notices = $this->_get_transient(true);
2741
+		echo stripslashes($notices);
2742
+	}
2743 2743
 
2744 2744
 
2745 2745
 
2746
-    /**
2747
-     * spinny things pacify the masses
2748
-     *
2749
-     * @return void
2750
-     */
2751
-    protected function _add_admin_page_ajax_loading_img()
2752
-    {
2753
-        ?>
2746
+	/**
2747
+	 * spinny things pacify the masses
2748
+	 *
2749
+	 * @return void
2750
+	 */
2751
+	protected function _add_admin_page_ajax_loading_img()
2752
+	{
2753
+		?>
2754 2754
         <div id="espresso-ajax-loading" class="ajax-loading-grey">
2755 2755
             <span class="ee-spinner ee-spin"></span><span class="hidden"><?php esc_html_e(
2756
-                    'loading...',
2757
-                    'event_espresso'
2758
-                ); ?></span>
2756
+					'loading...',
2757
+					'event_espresso'
2758
+				); ?></span>
2759 2759
         </div>
2760 2760
         <?php
2761
-    }
2761
+	}
2762 2762
 
2763 2763
 
2764 2764
 
2765
-    /**
2766
-     * add admin page overlay for modal boxes
2767
-     *
2768
-     * @return void
2769
-     */
2770
-    protected function _add_admin_page_overlay()
2771
-    {
2772
-        ?>
2765
+	/**
2766
+	 * add admin page overlay for modal boxes
2767
+	 *
2768
+	 * @return void
2769
+	 */
2770
+	protected function _add_admin_page_overlay()
2771
+	{
2772
+		?>
2773 2773
         <div id="espresso-admin-page-overlay-dv" class=""></div>
2774 2774
         <?php
2775
-    }
2776
-
2777
-
2778
-
2779
-    /**
2780
-     * facade for add_meta_box
2781
-     *
2782
-     * @param string  $action        where the metabox get's displayed
2783
-     * @param string  $title         Title of Metabox (output in metabox header)
2784
-     * @param string  $callback      If not empty and $create_fun is set to false then we'll use a custom callback
2785
-     *                               instead of the one created in here.
2786
-     * @param array   $callback_args an array of args supplied for the metabox
2787
-     * @param string  $column        what metabox column
2788
-     * @param string  $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2789
-     * @param boolean $create_func   default is true.  Basically we can say we don't WANT to have the runtime function
2790
-     *                               created but just set our own callback for wp's add_meta_box.
2791
-     * @throws \DomainException
2792
-     */
2793
-    public function _add_admin_page_meta_box(
2794
-        $action,
2795
-        $title,
2796
-        $callback,
2797
-        $callback_args,
2798
-        $column = 'normal',
2799
-        $priority = 'high',
2800
-        $create_func = true
2801
-    ) {
2802
-        do_action('AHEE_log', __FILE__, __FUNCTION__, $callback);
2803
-        //if we have empty callback args and we want to automatically create the metabox callback then we need to make sure the callback args are generated.
2804
-        if (empty($callback_args) && $create_func) {
2805
-            $callback_args = array(
2806
-                'template_path' => $this->_template_path,
2807
-                'template_args' => $this->_template_args,
2808
-            );
2809
-        }
2810
-        //if $create_func is true (default) then we automatically create the function for displaying the actual meta box.  If false then we take the $callback reference passed through and use it instead (so callers can define their own callback function/method if they wish)
2811
-        $call_back_func = $create_func
2812
-            ? function ($post, $metabox)
2813
-            {
2814
-                do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2815
-                echo EEH_Template::display_template(
2816
-                    $metabox['args']['template_path'],
2817
-                    $metabox['args']['template_args'],
2818
-                    true
2819
-                );
2820
-            }
2821
-            : $callback;
2822
-        add_meta_box(
2823
-            str_replace('_', '-', $action) . '-mbox',
2824
-            $title,
2825
-            $call_back_func,
2826
-            $this->_wp_page_slug,
2827
-            $column,
2828
-            $priority,
2829
-            $callback_args
2830
-        );
2831
-    }
2832
-
2833
-
2834
-
2835
-    /**
2836
-     * generates HTML wrapper for and admin details page that contains metaboxes in columns
2837
-     *
2838
-     * @throws DomainException
2839
-     * @throws EE_Error
2840
-     */
2841
-    public function display_admin_page_with_metabox_columns()
2842
-    {
2843
-        $this->_template_args['post_body_content']  = $this->_template_args['admin_page_content'];
2844
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2845
-            $this->_column_template_path,
2846
-            $this->_template_args,
2847
-            true
2848
-        );
2849
-        //the final wrapper
2850
-        $this->admin_page_wrapper();
2851
-    }
2852
-
2853
-
2854
-
2855
-    /**
2856
-     * generates  HTML wrapper for an admin details page
2857
-     *
2858
-     * @return void
2859
-     * @throws EE_Error
2860
-     * @throws DomainException
2861
-     */
2862
-    public function display_admin_page_with_sidebar()
2863
-    {
2864
-        $this->_display_admin_page(true);
2865
-    }
2866
-
2867
-
2868
-
2869
-    /**
2870
-     * generates  HTML wrapper for an admin details page (except no sidebar)
2871
-     *
2872
-     * @return void
2873
-     * @throws EE_Error
2874
-     * @throws DomainException
2875
-     */
2876
-    public function display_admin_page_with_no_sidebar()
2877
-    {
2878
-        $this->_display_admin_page();
2879
-    }
2880
-
2881
-
2882
-
2883
-    /**
2884
-     * generates HTML wrapper for an EE about admin page (no sidebar)
2885
-     *
2886
-     * @return void
2887
-     * @throws EE_Error
2888
-     * @throws DomainException
2889
-     */
2890
-    public function display_about_admin_page()
2891
-    {
2892
-        $this->_display_admin_page(false, true);
2893
-    }
2894
-
2895
-
2896
-
2897
-    /**
2898
-     * display_admin_page
2899
-     * contains the code for actually displaying an admin page
2900
-     *
2901
-     * @param  boolean $sidebar true with sidebar, false without
2902
-     * @param  boolean $about   use the about admin wrapper instead of the default.
2903
-     * @return void
2904
-     * @throws DomainException
2905
-     * @throws EE_Error
2906
-     */
2907
-    private function _display_admin_page($sidebar = false, $about = false)
2908
-    {
2909
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2910
-        //custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2911
-        do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2912
-        // set current wp page slug - looks like: event-espresso_page_event_categories
2913
-        // keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2914
-        $this->_template_args['current_page']              = $this->_wp_page_slug;
2915
-        $this->_template_args['admin_page_wrapper_div_id'] = $this->_cpt_route
2916
-            ? 'poststuff'
2917
-            : 'espresso-default-admin';
2918
-        $template_path                                     = $sidebar
2919
-            ? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2920
-            : EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2921
-        if (defined('DOING_AJAX') && DOING_AJAX) {
2922
-            $template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2923
-        }
2924
-        $template_path                                     = ! empty($this->_column_template_path)
2925
-            ? $this->_column_template_path : $template_path;
2926
-        $this->_template_args['post_body_content']         = isset($this->_template_args['admin_page_content'])
2927
-            ? $this->_template_args['admin_page_content']
2928
-            : '';
2929
-        $this->_template_args['before_admin_page_content'] = isset($this->_template_args['before_admin_page_content'])
2930
-            ? $this->_template_args['before_admin_page_content']
2931
-            : '';
2932
-        $this->_template_args['after_admin_page_content']  = isset($this->_template_args['after_admin_page_content'])
2933
-            ? $this->_template_args['after_admin_page_content']
2934
-            : '';
2935
-        $this->_template_args['admin_page_content']        = EEH_Template::display_template(
2936
-            $template_path,
2937
-            $this->_template_args,
2938
-            true
2939
-        );
2940
-        // the final template wrapper
2941
-        $this->admin_page_wrapper($about);
2942
-    }
2943
-
2944
-
2945
-
2946
-    /**
2947
-     * This is used to display caf preview pages.
2948
-     *
2949
-     * @since 4.3.2
2950
-     * @param string $utm_campaign_source what is the key used for google analytics link
2951
-     * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE
2952
-     *                                    = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2953
-     * @return void
2954
-     * @throws DomainException
2955
-     * @throws EE_Error
2956
-     * @throws InvalidArgumentException
2957
-     * @throws InvalidDataTypeException
2958
-     * @throws InvalidInterfaceException
2959
-     */
2960
-    public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2961
-    {
2962
-        //let's generate a default preview action button if there isn't one already present.
2963
-        $this->_labels['buttons']['buy_now']           = esc_html__(
2964
-            'Upgrade to Event Espresso 4 Right Now',
2965
-            'event_espresso'
2966
-        );
2967
-        $buy_now_url                                   = add_query_arg(
2968
-            array(
2969
-                'ee_ver'       => 'ee4',
2970
-                'utm_source'   => 'ee4_plugin_admin',
2971
-                'utm_medium'   => 'link',
2972
-                'utm_campaign' => $utm_campaign_source,
2973
-                'utm_content'  => 'buy_now_button',
2974
-            ),
2975
-            'http://eventespresso.com/pricing/'
2976
-        );
2977
-        $this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2978
-            ? $this->get_action_link_or_button(
2979
-                '',
2980
-                'buy_now',
2981
-                array(),
2982
-                'button-primary button-large',
2983
-                $buy_now_url,
2984
-                true
2985
-            )
2986
-            : $this->_template_args['preview_action_button'];
2987
-        $this->_template_args['admin_page_content']    = EEH_Template::display_template(
2988
-            EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2989
-            $this->_template_args,
2990
-            true
2991
-        );
2992
-        $this->_display_admin_page($display_sidebar);
2993
-    }
2994
-
2995
-
2996
-
2997
-    /**
2998
-     * display_admin_list_table_page_with_sidebar
2999
-     * generates HTML wrapper for an admin_page with list_table
3000
-     *
3001
-     * @return void
3002
-     * @throws EE_Error
3003
-     * @throws DomainException
3004
-     */
3005
-    public function display_admin_list_table_page_with_sidebar()
3006
-    {
3007
-        $this->_display_admin_list_table_page(true);
3008
-    }
3009
-
3010
-
3011
-
3012
-    /**
3013
-     * display_admin_list_table_page_with_no_sidebar
3014
-     * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
3015
-     *
3016
-     * @return void
3017
-     * @throws EE_Error
3018
-     * @throws DomainException
3019
-     */
3020
-    public function display_admin_list_table_page_with_no_sidebar()
3021
-    {
3022
-        $this->_display_admin_list_table_page();
3023
-    }
3024
-
3025
-
3026
-
3027
-    /**
3028
-     * generates html wrapper for an admin_list_table page
3029
-     *
3030
-     * @param boolean $sidebar whether to display with sidebar or not.
3031
-     * @return void
3032
-     * @throws DomainException
3033
-     * @throws EE_Error
3034
-     */
3035
-    private function _display_admin_list_table_page($sidebar = false)
3036
-    {
3037
-        //setup search attributes
3038
-        $this->_set_search_attributes();
3039
-        $this->_template_args['current_page']     = $this->_wp_page_slug;
3040
-        $template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
3041
-        $this->_template_args['table_url']        = defined('DOING_AJAX')
3042
-            ? add_query_arg(array('noheader' => 'true', 'route' => $this->_req_action), $this->_admin_base_url)
3043
-            : add_query_arg(array('route' => $this->_req_action), $this->_admin_base_url);
3044
-        $this->_template_args['list_table']       = $this->_list_table_object;
3045
-        $this->_template_args['current_route']    = $this->_req_action;
3046
-        $this->_template_args['list_table_class'] = get_class($this->_list_table_object);
3047
-        $ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
3048
-        if (! empty($ajax_sorting_callback)) {
3049
-            $sortable_list_table_form_fields = wp_nonce_field(
3050
-                $ajax_sorting_callback . '_nonce',
3051
-                $ajax_sorting_callback . '_nonce',
3052
-                false,
3053
-                false
3054
-            );
3055
-            //			$reorder_action = 'espresso_' . $ajax_sorting_callback . '_nonce';
3056
-            //			$sortable_list_table_form_fields = wp_nonce_field( $reorder_action, 'ajax_table_sort_nonce', FALSE, FALSE );
3057
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="'
3058
-                                                . $this->page_slug
3059
-                                                . '" />';
3060
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="'
3061
-                                                . $ajax_sorting_callback
3062
-                                                . '" />';
3063
-        } else {
3064
-            $sortable_list_table_form_fields = '';
3065
-        }
3066
-        $this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
3067
-        $hidden_form_fields                                      = isset($this->_template_args['list_table_hidden_fields'])
3068
-            ? $this->_template_args['list_table_hidden_fields']
3069
-            : '';
3070
-        $nonce_ref                                               = $this->_req_action . '_nonce';
3071
-        $hidden_form_fields                                      .= '<input type="hidden" name="'
3072
-                                                                    . $nonce_ref
3073
-                                                                    . '" value="'
3074
-                                                                    . wp_create_nonce($nonce_ref)
3075
-                                                                    . '">';
3076
-        $this->_template_args['list_table_hidden_fields']        = $hidden_form_fields;
3077
-        //display message about search results?
3078
-        $this->_template_args['before_list_table'] .= ! empty($this->_req_data['s'])
3079
-            ? '<p class="ee-search-results">' . sprintf(
3080
-                esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
3081
-                trim($this->_req_data['s'], '%')
3082
-            ) . '</p>'
3083
-            : '';
3084
-        // filter before_list_table template arg
3085
-        $this->_template_args['before_list_table'] = apply_filters(
3086
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
3087
-            $this->_template_args['before_list_table'],
3088
-            $this->page_slug,
3089
-            $this->_req_data,
3090
-            $this->_req_action
3091
-        );
3092
-        // convert to array and filter again
3093
-        // arrays are easier to inject new items in a specific location,
3094
-        // but would not be backwards compatible, so we have to add a new filter
3095
-        $this->_template_args['before_list_table'] = implode(
3096
-            " \n",
3097
-            (array)apply_filters(
3098
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
3099
-                (array)$this->_template_args['before_list_table'],
3100
-                $this->page_slug,
3101
-                $this->_req_data,
3102
-                $this->_req_action
3103
-            )
3104
-        );
3105
-        // filter after_list_table template arg
3106
-        $this->_template_args['after_list_table'] = apply_filters(
3107
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
3108
-            $this->_template_args['after_list_table'],
3109
-            $this->page_slug,
3110
-            $this->_req_data,
3111
-            $this->_req_action
3112
-        );
3113
-        // convert to array and filter again
3114
-        // arrays are easier to inject new items in a specific location,
3115
-        // but would not be backwards compatible, so we have to add a new filter
3116
-        $this->_template_args['after_list_table']   = implode(
3117
-            " \n",
3118
-            (array)apply_filters(
3119
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
3120
-                (array)$this->_template_args['after_list_table'],
3121
-                $this->page_slug,
3122
-                $this->_req_data,
3123
-                $this->_req_action
3124
-            )
3125
-        );
3126
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3127
-            $template_path,
3128
-            $this->_template_args,
3129
-            true
3130
-        );
3131
-        // the final template wrapper
3132
-        if ($sidebar) {
3133
-            $this->display_admin_page_with_sidebar();
3134
-        } else {
3135
-            $this->display_admin_page_with_no_sidebar();
3136
-        }
3137
-    }
3138
-
3139
-
3140
-
3141
-    /**
3142
-     * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the
3143
-     * html string for the legend.
3144
-     * $items are expected in an array in the following format:
3145
-     * $legend_items = array(
3146
-     *        'item_id' => array(
3147
-     *            'icon' => 'http://url_to_icon_being_described.png',
3148
-     *            'desc' => esc_html__('localized description of item');
3149
-     *        )
3150
-     * );
3151
-     *
3152
-     * @param  array $items see above for format of array
3153
-     * @return string html string of legend
3154
-     * @throws DomainException
3155
-     */
3156
-    protected function _display_legend($items)
3157
-    {
3158
-        $this->_template_args['items'] = apply_filters(
3159
-            'FHEE__EE_Admin_Page___display_legend__items',
3160
-            (array)$items,
3161
-            $this
3162
-        );
3163
-        return EEH_Template::display_template(
3164
-            EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3165
-            $this->_template_args,
3166
-            true
3167
-        );
3168
-    }
3169
-
3170
-
3171
-    /**
3172
-     * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
3173
-     * The returned json object is created from an array in the following format:
3174
-     * array(
3175
-     *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
3176
-     *  'success' => FALSE, //(default FALSE) - contains any special success message.
3177
-     *  'notices' => '', // - contains any EE_Error formatted notices
3178
-     *  'content' => 'string can be html', //this is a string of formatted content (can be html)
3179
-     *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
3180
-     *  We're also going to include the template args with every package (so js can pick out any specific template args
3181
-     *  that might be included in here)
3182
-     * )
3183
-     * The json object is populated by whatever is set in the $_template_args property.
3184
-     *
3185
-     * @param bool  $sticky_notices    Used to indicate whether you want to ensure notices are added to a transient
3186
-     *                                 instead of displayed.
3187
-     * @param array $notices_arguments Use this to pass any additional args on to the _process_notices.
3188
-     * @return void
3189
-     * @throws EE_Error
3190
-     */
3191
-    protected function _return_json($sticky_notices = false, $notices_arguments = array())
3192
-    {
3193
-        //make sure any EE_Error notices have been handled.
3194
-        $this->_process_notices($notices_arguments, true, $sticky_notices);
3195
-        $data = isset($this->_template_args['data']) ? $this->_template_args['data'] : array();
3196
-        unset($this->_template_args['data']);
3197
-        $json = array(
3198
-            'error'     => isset($this->_template_args['error']) ? $this->_template_args['error'] : false,
3199
-            'success'   => isset($this->_template_args['success']) ? $this->_template_args['success'] : false,
3200
-            'errors'    => isset($this->_template_args['errors']) ? $this->_template_args['errors'] : false,
3201
-            'attention' => isset($this->_template_args['attention']) ? $this->_template_args['attention'] : false,
3202
-            'notices'   => EE_Error::get_notices(),
3203
-            'content'   => isset($this->_template_args['admin_page_content'])
3204
-                ? $this->_template_args['admin_page_content'] : '',
3205
-            'data'      => array_merge($data, array('template_args' => $this->_template_args)),
3206
-            'isEEajax'  => true
3207
-            //special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
3208
-        );
3209
-        // make sure there are no php errors or headers_sent.  Then we can set correct json header.
3210
-        if (null === error_get_last() || ! headers_sent()) {
3211
-            header('Content-Type: application/json; charset=UTF-8');
3212
-        }
3213
-        echo wp_json_encode($json);
3214
-        exit();
3215
-    }
3216
-
3217
-
3218
-
3219
-    /**
3220
-     * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
3221
-     *
3222
-     * @return void
3223
-     * @throws EE_Error
3224
-     */
3225
-    public function return_json()
3226
-    {
3227
-        if (defined('DOING_AJAX') && DOING_AJAX) {
3228
-            $this->_return_json();
3229
-        } else {
3230
-            throw new EE_Error(
3231
-                sprintf(
3232
-                    esc_html__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'),
3233
-                    __FUNCTION__
3234
-                )
3235
-            );
3236
-        }
3237
-    }
3238
-
3239
-
3240
-
3241
-    /**
3242
-     * This provides a way for child hook classes to send along themselves by reference so methods/properties within
3243
-     * them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
3244
-     *
3245
-     * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
3246
-     */
3247
-    public function set_hook_object(EE_Admin_Hooks $hook_obj)
3248
-    {
3249
-        $this->_hook_obj = $hook_obj;
3250
-    }
3251
-
3252
-
3253
-
3254
-    /**
3255
-     *        generates  HTML wrapper with Tabbed nav for an admin page
3256
-     *
3257
-     * @param  boolean $about whether to use the special about page wrapper or default.
3258
-     * @return void
3259
-     * @throws DomainException
3260
-     * @throws EE_Error
3261
-     */
3262
-    public function admin_page_wrapper($about = false)
3263
-    {
3264
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3265
-        $this->_nav_tabs                                   = $this->_get_main_nav_tabs();
3266
-        $this->_template_args['nav_tabs']                  = $this->_nav_tabs;
3267
-        $this->_template_args['admin_page_title']          = $this->_admin_page_title;
3268
-        $this->_template_args['before_admin_page_content'] = apply_filters(
3269
-            "FHEE_before_admin_page_content{$this->_current_page}{$this->_current_view}",
3270
-            isset($this->_template_args['before_admin_page_content'])
3271
-                ? $this->_template_args['before_admin_page_content']
3272
-                : ''
3273
-        );
3274
-        $this->_template_args['after_admin_page_content']  = apply_filters(
3275
-            "FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3276
-            isset($this->_template_args['after_admin_page_content'])
3277
-                ? $this->_template_args['after_admin_page_content']
3278
-                : ''
3279
-        );
3280
-        $this->_template_args['after_admin_page_content']  .= $this->_set_help_popup_content();
3281
-        // load settings page wrapper template
3282
-        $template_path = ! defined('DOING_AJAX')
3283
-            ? EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php'
3284
-            : EE_ADMIN_TEMPLATE
3285
-              . 'admin_wrapper_ajax.template.php';
3286
-        //about page?
3287
-        $template_path = $about
3288
-            ? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3289
-            : $template_path;
3290
-        if (defined('DOING_AJAX')) {
3291
-            $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3292
-                $template_path,
3293
-                $this->_template_args,
3294
-                true
3295
-            );
3296
-            $this->_return_json();
3297
-        } else {
3298
-            EEH_Template::display_template($template_path, $this->_template_args);
3299
-        }
3300
-    }
3301
-
3302
-
3303
-
3304
-    /**
3305
-     * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
3306
-     *
3307
-     * @return string html
3308
-     * @throws EE_Error
3309
-     */
3310
-    protected function _get_main_nav_tabs()
3311
-    {
3312
-        // let's generate the html using the EEH_Tabbed_Content helper.
3313
-        // We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute
3314
-        // (rather than setting in the page_routes array)
3315
-        return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs);
3316
-    }
3317
-
3318
-
3319
-
3320
-    /**
3321
-     *        sort nav tabs
3322
-     *
3323
-     * @param $a
3324
-     * @param $b
3325
-     * @return int
3326
-     */
3327
-    private function _sort_nav_tabs($a, $b)
3328
-    {
3329
-        if ($a['order'] === $b['order']) {
3330
-            return 0;
3331
-        }
3332
-        return ($a['order'] < $b['order']) ? -1 : 1;
3333
-    }
3334
-
3335
-
3336
-
3337
-    /**
3338
-     *    generates HTML for the forms used on admin pages
3339
-     *
3340
-     * @param    array $input_vars - array of input field details
3341
-     * @param string   $generator  (options are 'string' or 'array', basically use this to indicate which generator to
3342
-     *                             use)
3343
-     * @param bool     $id
3344
-     * @return string
3345
-     * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
3346
-     * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
3347
-     */
3348
-    protected function _generate_admin_form_fields($input_vars = array(), $generator = 'string', $id = false)
3349
-    {
3350
-        $content = $generator === 'string'
3351
-            ? EEH_Form_Fields::get_form_fields($input_vars, $id)
3352
-            : EEH_Form_Fields::get_form_fields_array($input_vars);
3353
-        return $content;
3354
-    }
3355
-
3356
-
3357
-
3358
-    /**
3359
-     * generates the "Save" and "Save & Close" buttons for edit forms
3360
-     *
3361
-     * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save &
3362
-     *                                   Close" button.
3363
-     * @param array            $text     if included, generator will use the given text for the buttons ( array([0] =>
3364
-     *                                   'Save', [1] => 'save & close')
3365
-     * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e.
3366
-     *                                   via the "name" value in the button).  We can also use this to just dump
3367
-     *                                   default actions by submitting some other value.
3368
-     * @param bool|string|null $referrer if false then we just do the default action on save and close.  Other wise it
3369
-     *                                   will use the $referrer string. IF null, then we don't do ANYTHING on save and
3370
-     *                                   close (normal form handling).
3371
-     */
3372
-    protected function _set_save_buttons($both = true, $text = array(), $actions = array(), $referrer = null)
3373
-    {
3374
-        //make sure $text and $actions are in an array
3375
-        $text          = (array)$text;
3376
-        $actions       = (array)$actions;
3377
-        $referrer_url  = empty($referrer)
3378
-            ? '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3379
-              . $_SERVER['REQUEST_URI']
3380
-              . '" />'
3381
-            : '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3382
-              . $referrer
3383
-              . '" />';
3384
-        $button_text   = ! empty($text)
3385
-            ? $text
3386
-            : array(
3387
-                esc_html__('Save', 'event_espresso'),
3388
-                esc_html__('Save and Close', 'event_espresso'),
3389
-            );
3390
-        $default_names = array('save', 'save_and_close');
3391
-        //add in a hidden index for the current page (so save and close redirects properly)
3392
-        $this->_template_args['save_buttons'] = $referrer_url;
3393
-        foreach ($button_text as $key => $button) {
3394
-            $ref                                  = $default_names[$key];
3395
-            $this->_template_args['save_buttons'] .= '<input type="submit" class="button-primary '
3396
-                                                     . $ref
3397
-                                                     . '" value="'
3398
-                                                     . $button
3399
-                                                     . '" name="'
3400
-                                                     . (! empty($actions) ? $actions[$key] : $ref)
3401
-                                                     . '" id="'
3402
-                                                     . $this->_current_view . '_' . $ref
3403
-                                                     . '" />';
3404
-            if (! $both) {
3405
-                break;
3406
-            }
3407
-        }
3408
-    }
3409
-
3410
-
3411
-
3412
-    /**
3413
-     * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
3414
-     *
3415
-     * @see   $this->_set_add_edit_form_tags() for details on params
3416
-     * @since 4.6.0
3417
-     * @param string $route
3418
-     * @param array  $additional_hidden_fields
3419
-     */
3420
-    public function set_add_edit_form_tags($route = '', $additional_hidden_fields = array())
3421
-    {
3422
-        $this->_set_add_edit_form_tags($route, $additional_hidden_fields);
3423
-    }
3424
-
3425
-
3426
-
3427
-    /**
3428
-     * set form open and close tags on add/edit pages.
3429
-     *
3430
-     * @param string $route                    the route you want the form to direct to
3431
-     * @param array  $additional_hidden_fields any additional hidden fields required in the form header
3432
-     * @return void
3433
-     */
3434
-    protected function _set_add_edit_form_tags($route = '', $additional_hidden_fields = array())
3435
-    {
3436
-        if (empty($route)) {
3437
-            $user_msg = esc_html__(
3438
-                'An error occurred. No action was set for this page\'s form.',
3439
-                'event_espresso'
3440
-            );
3441
-            $dev_msg  = $user_msg . "\n" . sprintf(
3442
-                    esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3443
-                    __FUNCTION__,
3444
-                    __CLASS__
3445
-                );
3446
-            EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3447
-        }
3448
-        // open form
3449
-        $this->_template_args['before_admin_page_content'] = '<form name="form" method="post" action="'
3450
-                                                             . $this->_admin_base_url
3451
-                                                             . '" id="'
3452
-                                                             . $route
3453
-                                                             . '_event_form" >';
3454
-        // add nonce
3455
-        $nonce = wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3456
-        //		$nonce = wp_nonce_field( $route . '_nonce', '_wpnonce', FALSE, FALSE );
3457
-        $this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3458
-        // add REQUIRED form action
3459
-        $hidden_fields = array(
3460
-            'action' => array('type' => 'hidden', 'value' => $route),
3461
-        );
3462
-        // merge arrays
3463
-        $hidden_fields = is_array($additional_hidden_fields)
3464
-            ? array_merge($hidden_fields, $additional_hidden_fields)
3465
-            : $hidden_fields;
3466
-        // generate form fields
3467
-        $form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3468
-        // add fields to form
3469
-        foreach ((array)$form_fields as $field_name => $form_field) {
3470
-            $this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3471
-        }
3472
-        // close form
3473
-        $this->_template_args['after_admin_page_content'] = '</form>';
3474
-    }
3475
-
3476
-
3477
-
3478
-    /**
3479
-     * Public Wrapper for _redirect_after_action() method since its
3480
-     * discovered it would be useful for external code to have access.
3481
-     *
3482
-     * @see   EE_Admin_Page::_redirect_after_action() for params.
3483
-     * @since 4.5.0
3484
-     * @param bool   $success
3485
-     * @param string $what
3486
-     * @param string $action_desc
3487
-     * @param array  $query_args
3488
-     * @param bool   $override_overwrite
3489
-     * @throws EE_Error
3490
-     */
3491
-    public function redirect_after_action(
3492
-        $success = false,
3493
-        $what = 'item',
3494
-        $action_desc = 'processed',
3495
-        $query_args = array(),
3496
-        $override_overwrite = false
3497
-    ) {
3498
-        $this->_redirect_after_action(
3499
-            $success,
3500
-            $what,
3501
-            $action_desc,
3502
-            $query_args,
3503
-            $override_overwrite
3504
-        );
3505
-    }
3506
-
3507
-
3508
-
3509
-    /**
3510
-     *    _redirect_after_action
3511
-     *
3512
-     * @param int    $success            - whether success was for two or more records, or just one, or none
3513
-     * @param string $what               - what the action was performed on
3514
-     * @param string $action_desc        - what was done ie: updated, deleted, etc
3515
-     * @param array  $query_args         - an array of query_args to be added to the URL to redirect to after the admin
3516
-     *                                   action is completed
3517
-     * @param BOOL   $override_overwrite by default all EE_Error::success messages are overwritten, this allows you to
3518
-     *                                   override this so that they show.
3519
-     * @return void
3520
-     * @throws EE_Error
3521
-     */
3522
-    protected function _redirect_after_action(
3523
-        $success = 0,
3524
-        $what = 'item',
3525
-        $action_desc = 'processed',
3526
-        $query_args = array(),
3527
-        $override_overwrite = false
3528
-    ) {
3529
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3530
-        //class name for actions/filters.
3531
-        $classname = get_class($this);
3532
-        // set redirect url.
3533
-        // Note if there is a "page" index in the $query_args then we go with vanilla admin.php route,
3534
-        // otherwise we go with whatever is set as the _admin_base_url
3535
-        $redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3536
-        $notices      = EE_Error::get_notices(false);
3537
-        // overwrite default success messages //BUT ONLY if overwrite not overridden
3538
-        if (! $override_overwrite || ! empty($notices['errors'])) {
3539
-            EE_Error::overwrite_success();
3540
-        }
3541
-        if (! empty($what) && ! empty($action_desc)  && empty($notices['errors'])) {
3542
-            // how many records affected ? more than one record ? or just one ?
3543
-            if ($success > 1) {
3544
-                // set plural msg
3545
-                EE_Error::add_success(
3546
-                    sprintf(
3547
-                        esc_html__('The "%s" have been successfully %s.', 'event_espresso'),
3548
-                        $what,
3549
-                        $action_desc
3550
-                    ),
3551
-                    __FILE__,
3552
-                    __FUNCTION__,
3553
-                    __LINE__
3554
-                );
3555
-            } elseif ($success === 1) {
3556
-                // set singular msg
3557
-                EE_Error::add_success(
3558
-                    sprintf(
3559
-                        esc_html__('The "%s" has been successfully %s.', 'event_espresso'),
3560
-                        $what,
3561
-                        $action_desc
3562
-                    ),
3563
-                    __FILE__,
3564
-                    __FUNCTION__,
3565
-                    __LINE__
3566
-                );
3567
-            }
3568
-        }
3569
-        // check that $query_args isn't something crazy
3570
-        if (! is_array($query_args)) {
3571
-            $query_args = array();
3572
-        }
3573
-        /**
3574
-         * Allow injecting actions before the query_args are modified for possible different
3575
-         * redirections on save and close actions
3576
-         *
3577
-         * @since 4.2.0
3578
-         * @param array $query_args       The original query_args array coming into the
3579
-         *                                method.
3580
-         */
3581
-        do_action(
3582
-            "AHEE__{$classname}___redirect_after_action__before_redirect_modification_{$this->_req_action}",
3583
-            $query_args
3584
-        );
3585
-        //calculate where we're going (if we have a "save and close" button pushed)
3586
-        if (isset($this->_req_data['save_and_close'], $this->_req_data['save_and_close_referrer'])) {
3587
-            // even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
3588
-            $parsed_url = parse_url($this->_req_data['save_and_close_referrer']);
3589
-            // regenerate query args array from referrer URL
3590
-            parse_str($parsed_url['query'], $query_args);
3591
-            // correct page and action will be in the query args now
3592
-            $redirect_url = admin_url('admin.php');
3593
-        }
3594
-        //merge any default query_args set in _default_route_query_args property
3595
-        if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3596
-            $args_to_merge = array();
3597
-            foreach ($this->_default_route_query_args as $query_param => $query_value) {
3598
-                //is there a wp_referer array in our _default_route_query_args property?
3599
-                if ($query_param === 'wp_referer') {
3600
-                    $query_value = (array)$query_value;
3601
-                    foreach ($query_value as $reference => $value) {
3602
-                        if (strpos($reference, 'nonce') !== false) {
3603
-                            continue;
3604
-                        }
3605
-                        //finally we will override any arguments in the referer with
3606
-                        //what might be set on the _default_route_query_args array.
3607
-                        if (isset($this->_default_route_query_args[$reference])) {
3608
-                            $args_to_merge[$reference] = urlencode($this->_default_route_query_args[$reference]);
3609
-                        } else {
3610
-                            $args_to_merge[$reference] = urlencode($value);
3611
-                        }
3612
-                    }
3613
-                    continue;
3614
-                }
3615
-                $args_to_merge[$query_param] = $query_value;
3616
-            }
3617
-            //now let's merge these arguments but override with what was specifically sent in to the
3618
-            //redirect.
3619
-            $query_args = array_merge($args_to_merge, $query_args);
3620
-        }
3621
-        $this->_process_notices($query_args);
3622
-        // generate redirect url
3623
-        // if redirecting to anything other than the main page, add a nonce
3624
-        if (isset($query_args['action'])) {
3625
-            // manually generate wp_nonce and merge that with the query vars
3626
-            // becuz the wp_nonce_url function wrecks havoc on some vars
3627
-            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3628
-        }
3629
-        // we're adding some hooks and filters in here for processing any things just before redirects
3630
-        // (example: an admin page has done an insert or update and we want to run something after that).
3631
-        do_action('AHEE_redirect_' . $classname . $this->_req_action, $query_args);
3632
-        $redirect_url = apply_filters(
3633
-            'FHEE_redirect_' . $classname . $this->_req_action,
3634
-            self::add_query_args_and_nonce($query_args, $redirect_url),
3635
-            $query_args
3636
-        );
3637
-        // check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3638
-        if (defined('DOING_AJAX')) {
3639
-            $default_data                    = array(
3640
-                'close'        => true,
3641
-                'redirect_url' => $redirect_url,
3642
-                'where'        => 'main',
3643
-                'what'         => 'append',
3644
-            );
3645
-            $this->_template_args['success'] = $success;
3646
-            $this->_template_args['data']    = ! empty($this->_template_args['data']) ? array_merge(
3647
-                $default_data,
3648
-                $this->_template_args['data']
3649
-            ) : $default_data;
3650
-            $this->_return_json();
3651
-        }
3652
-        wp_safe_redirect($redirect_url);
3653
-        exit();
3654
-    }
3655
-
3656
-
3657
-
3658
-    /**
3659
-     * process any notices before redirecting (or returning ajax request)
3660
-     * This method sets the $this->_template_args['notices'] attribute;
3661
-     *
3662
-     * @param  array $query_args        any query args that need to be used for notice transient ('action')
3663
-     * @param bool   $skip_route_verify This is typically used when we are processing notices REALLY early and
3664
-     *                                  page_routes haven't been defined yet.
3665
-     * @param bool   $sticky_notices    This is used to flag that regardless of whether this is doing_ajax or not, we
3666
-     *                                  still save a transient for the notice.
3667
-     * @return void
3668
-     * @throws EE_Error
3669
-     */
3670
-    protected function _process_notices($query_args = array(), $skip_route_verify = false, $sticky_notices = true)
3671
-    {
3672
-        //first let's set individual error properties if doing_ajax and the properties aren't already set.
3673
-        if (defined('DOING_AJAX') && DOING_AJAX) {
3674
-            $notices = EE_Error::get_notices(false);
3675
-            if (empty($this->_template_args['success'])) {
3676
-                $this->_template_args['success'] = isset($notices['success']) ? $notices['success'] : false;
3677
-            }
3678
-            if (empty($this->_template_args['errors'])) {
3679
-                $this->_template_args['errors'] = isset($notices['errors']) ? $notices['errors'] : false;
3680
-            }
3681
-            if (empty($this->_template_args['attention'])) {
3682
-                $this->_template_args['attention'] = isset($notices['attention']) ? $notices['attention'] : false;
3683
-            }
3684
-        }
3685
-        $this->_template_args['notices'] = EE_Error::get_notices();
3686
-        //IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3687
-        if (! defined('DOING_AJAX') || $sticky_notices) {
3688
-            $route = isset($query_args['action']) ? $query_args['action'] : 'default';
3689
-            $this->_add_transient(
3690
-                $route,
3691
-                $this->_template_args['notices'],
3692
-                true,
3693
-                $skip_route_verify
3694
-            );
3695
-        }
3696
-    }
3697
-
3698
-
3699
-
3700
-    /**
3701
-     * get_action_link_or_button
3702
-     * returns the button html for adding, editing, or deleting an item (depending on given type)
3703
-     *
3704
-     * @param string $action        use this to indicate which action the url is generated with.
3705
-     * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key)
3706
-     *                              property.
3707
-     * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
3708
-     * @param string $class         Use this to give the class for the button. Defaults to 'button-primary'
3709
-     * @param string $base_url      If this is not provided
3710
-     *                              the _admin_base_url will be used as the default for the button base_url.
3711
-     *                              Otherwise this value will be used.
3712
-     * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
3713
-     * @return string
3714
-     * @throws InvalidArgumentException
3715
-     * @throws InvalidInterfaceException
3716
-     * @throws InvalidDataTypeException
3717
-     * @throws EE_Error
3718
-     */
3719
-    public function get_action_link_or_button(
3720
-        $action,
3721
-        $type = 'add',
3722
-        $extra_request = array(),
3723
-        $class = 'button-primary',
3724
-        $base_url = '',
3725
-        $exclude_nonce = false
3726
-    ) {
3727
-        //first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3728
-        if (empty($base_url) && ! isset($this->_page_routes[$action])) {
3729
-            throw new EE_Error(
3730
-                sprintf(
3731
-                    esc_html__(
3732
-                        'There is no page route for given action for the button.  This action was given: %s',
3733
-                        'event_espresso'
3734
-                    ),
3735
-                    $action
3736
-                )
3737
-            );
3738
-        }
3739
-        if (! isset($this->_labels['buttons'][$type])) {
3740
-            throw new EE_Error(
3741
-                sprintf(
3742
-                    __(
3743
-                        'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
3744
-                        'event_espresso'
3745
-                    ),
3746
-                    $type
3747
-                )
3748
-            );
3749
-        }
3750
-        //finally check user access for this button.
3751
-        $has_access = $this->check_user_access($action, true);
3752
-        if (! $has_access) {
3753
-            return '';
3754
-        }
3755
-        $_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
3756
-        $query_args = array(
3757
-            'action' => $action,
3758
-        );
3759
-        //merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3760
-        if (! empty($extra_request)) {
3761
-            $query_args = array_merge($extra_request, $query_args);
3762
-        }
3763
-        $url = self::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3764
-        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][$type], $class);
3765
-    }
3766
-
3767
-
3768
-
3769
-    /**
3770
-     * _per_page_screen_option
3771
-     * Utility function for adding in a per_page_option in the screen_options_dropdown.
3772
-     *
3773
-     * @return void
3774
-     * @throws InvalidArgumentException
3775
-     * @throws InvalidInterfaceException
3776
-     * @throws InvalidDataTypeException
3777
-     */
3778
-    protected function _per_page_screen_option()
3779
-    {
3780
-        $option = 'per_page';
3781
-        $args   = array(
3782
-            'label'   => esc_html__(
3783
-                    apply_filters(
3784
-                        'FHEE__EE_Admin_Page___per_page_screen_options___label',
3785
-                        $this->_admin_page_title,
3786
-                        $this
3787
-                    )
3788
-            ),
3789
-            'default' => (int) apply_filters(
3790
-                    'FHEE__EE_Admin_Page___per_page_screen_options__default',
3791
-                    10
3792
-            ),
3793
-            'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3794
-        );
3795
-        //ONLY add the screen option if the user has access to it.
3796
-        if ($this->check_user_access($this->_current_view, true)) {
3797
-            add_screen_option($option, $args);
3798
-        }
3799
-    }
3800
-
3801
-
3802
-
3803
-    /**
3804
-     * set_per_page_screen_option
3805
-     * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3806
-     * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than
3807
-     * admin_menu.
3808
-     *
3809
-     * @return void
3810
-     */
3811
-    private function _set_per_page_screen_options()
3812
-    {
3813
-        if (isset($_POST['wp_screen_options']) && is_array($_POST['wp_screen_options'])) {
3814
-            check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3815
-            if (! $user = wp_get_current_user()) {
3816
-                return;
3817
-            }
3818
-            $option = $_POST['wp_screen_options']['option'];
3819
-            $value  = $_POST['wp_screen_options']['value'];
3820
-            if ($option != sanitize_key($option)) {
3821
-                return;
3822
-            }
3823
-            $map_option = $option;
3824
-            $option     = str_replace('-', '_', $option);
3825
-            switch ($map_option) {
3826
-                case $this->_current_page . '_' . $this->_current_view . '_per_page':
3827
-                    $value = (int)$value;
3828
-                    $max_value = apply_filters(
3829
-                        'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3830
-                        999,
3831
-                        $this->_current_page,
3832
-                        $this->_current_view
3833
-                    );
3834
-                    if ($value < 1) {
3835
-                        return;
3836
-                    }
3837
-                    $value = min($value, $max_value);
3838
-                    break;
3839
-                default:
3840
-                    $value = apply_filters(
3841
-                        'FHEE__EE_Admin_Page___set_per_page_screen_options__value',
3842
-                        false,
3843
-                        $option,
3844
-                        $value
3845
-                    );
3846
-                    if (false === $value) {
3847
-                        return;
3848
-                    }
3849
-                    break;
3850
-            }
3851
-            update_user_meta($user->ID, $option, $value);
3852
-            wp_safe_redirect(remove_query_arg(array('pagenum', 'apage', 'paged'), wp_get_referer()));
3853
-            exit;
3854
-        }
3855
-    }
3856
-
3857
-
3858
-
3859
-    /**
3860
-     * This just allows for setting the $_template_args property if it needs to be set outside the object
3861
-     *
3862
-     * @param array $data array that will be assigned to template args.
3863
-     */
3864
-    public function set_template_args($data)
3865
-    {
3866
-        $this->_template_args = array_merge($this->_template_args, (array)$data);
3867
-    }
3868
-
3869
-
3870
-
3871
-    /**
3872
-     * This makes available the WP transient system for temporarily moving data between routes
3873
-     *
3874
-     * @param string $route             the route that should receive the transient
3875
-     * @param array  $data              the data that gets sent
3876
-     * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise its just a
3877
-     *                                  normal route transient.
3878
-     * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used
3879
-     *                                  when we are adding a transient before page_routes have been defined.
3880
-     * @return void
3881
-     * @throws EE_Error
3882
-     */
3883
-    protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3884
-    {
3885
-        $user_id = get_current_user_id();
3886
-        if (! $skip_route_verify) {
3887
-            $this->_verify_route($route);
3888
-        }
3889
-        //now let's set the string for what kind of transient we're setting
3890
-        $transient = $notices
3891
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3892
-            : 'rte_tx_' . $route . '_' . $user_id;
3893
-        $data      = $notices ? array('notices' => $data) : $data;
3894
-        //is there already a transient for this route?  If there is then let's ADD to that transient
3895
-        $existing = is_multisite() && is_network_admin()
3896
-            ? get_site_transient($transient)
3897
-            : get_transient($transient);
3898
-        if ($existing) {
3899
-            $data = array_merge((array)$data, (array)$existing);
3900
-        }
3901
-        if (is_multisite() && is_network_admin()) {
3902
-            set_site_transient($transient, $data, 8);
3903
-        } else {
3904
-            set_transient($transient, $data, 8);
3905
-        }
3906
-    }
3907
-
3908
-
3909
-
3910
-    /**
3911
-     * this retrieves the temporary transient that has been set for moving data between routes.
3912
-     *
3913
-     * @param bool   $notices true we get notices transient. False we just return normal route transient
3914
-     * @param string $route
3915
-     * @return mixed data
3916
-     */
3917
-    protected function _get_transient($notices = false, $route = '')
3918
-    {
3919
-        $user_id   = get_current_user_id();
3920
-        $route     = ! $route ? $this->_req_action : $route;
3921
-        $transient = $notices
3922
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3923
-            : 'rte_tx_' . $route . '_' . $user_id;
3924
-        $data      = is_multisite() && is_network_admin()
3925
-            ? get_site_transient($transient)
3926
-            : get_transient($transient);
3927
-        //delete transient after retrieval (just in case it hasn't expired);
3928
-        if (is_multisite() && is_network_admin()) {
3929
-            delete_site_transient($transient);
3930
-        } else {
3931
-            delete_transient($transient);
3932
-        }
3933
-        return $notices && isset($data['notices']) ? $data['notices'] : $data;
3934
-    }
3935
-
3936
-
3937
-
3938
-    /**
3939
-     * The purpose of this method is just to run garbage collection on any EE transients that might have expired but
3940
-     * would not be called later. This will be assigned to run on a specific EE Admin page. (place the method in the
3941
-     * default route callback on the EE_Admin page you want it run.)
3942
-     *
3943
-     * @return void
3944
-     */
3945
-    protected function _transient_garbage_collection()
3946
-    {
3947
-        global $wpdb;
3948
-        //retrieve all existing transients
3949
-        $query = "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3950
-        if ($results = $wpdb->get_results($query)) {
3951
-            foreach ($results as $result) {
3952
-                $transient = str_replace('_transient_', '', $result->option_name);
3953
-                get_transient($transient);
3954
-                if (is_multisite() && is_network_admin()) {
3955
-                    get_site_transient($transient);
3956
-                }
3957
-            }
3958
-        }
3959
-    }
3960
-
3961
-
3962
-
3963
-    /**
3964
-     * get_view
3965
-     *
3966
-     * @return string content of _view property
3967
-     */
3968
-    public function get_view()
3969
-    {
3970
-        return $this->_view;
3971
-    }
3972
-
3973
-
3974
-
3975
-    /**
3976
-     * getter for the protected $_views property
3977
-     *
3978
-     * @return array
3979
-     */
3980
-    public function get_views()
3981
-    {
3982
-        return $this->_views;
3983
-    }
3984
-
3985
-
3986
-
3987
-    /**
3988
-     * get_current_page
3989
-     *
3990
-     * @return string _current_page property value
3991
-     */
3992
-    public function get_current_page()
3993
-    {
3994
-        return $this->_current_page;
3995
-    }
3996
-
3997
-
3998
-
3999
-    /**
4000
-     * get_current_view
4001
-     *
4002
-     * @return string _current_view property value
4003
-     */
4004
-    public function get_current_view()
4005
-    {
4006
-        return $this->_current_view;
4007
-    }
4008
-
4009
-
4010
-
4011
-    /**
4012
-     * get_current_screen
4013
-     *
4014
-     * @return object The current WP_Screen object
4015
-     */
4016
-    public function get_current_screen()
4017
-    {
4018
-        return $this->_current_screen;
4019
-    }
4020
-
4021
-
4022
-
4023
-    /**
4024
-     * get_current_page_view_url
4025
-     *
4026
-     * @return string This returns the url for the current_page_view.
4027
-     */
4028
-    public function get_current_page_view_url()
4029
-    {
4030
-        return $this->_current_page_view_url;
4031
-    }
4032
-
4033
-
4034
-
4035
-    /**
4036
-     * just returns the _req_data property
4037
-     *
4038
-     * @return array
4039
-     */
4040
-    public function get_request_data()
4041
-    {
4042
-        return $this->_req_data;
4043
-    }
4044
-
4045
-
4046
-
4047
-    /**
4048
-     * returns the _req_data protected property
4049
-     *
4050
-     * @return string
4051
-     */
4052
-    public function get_req_action()
4053
-    {
4054
-        return $this->_req_action;
4055
-    }
4056
-
4057
-
4058
-
4059
-    /**
4060
-     * @return bool  value of $_is_caf property
4061
-     */
4062
-    public function is_caf()
4063
-    {
4064
-        return $this->_is_caf;
4065
-    }
4066
-
4067
-
4068
-
4069
-    /**
4070
-     * @return mixed
4071
-     */
4072
-    public function default_espresso_metaboxes()
4073
-    {
4074
-        return $this->_default_espresso_metaboxes;
4075
-    }
4076
-
4077
-
4078
-
4079
-    /**
4080
-     * @return mixed
4081
-     */
4082
-    public function admin_base_url()
4083
-    {
4084
-        return $this->_admin_base_url;
4085
-    }
2775
+	}
2776
+
2777
+
2778
+
2779
+	/**
2780
+	 * facade for add_meta_box
2781
+	 *
2782
+	 * @param string  $action        where the metabox get's displayed
2783
+	 * @param string  $title         Title of Metabox (output in metabox header)
2784
+	 * @param string  $callback      If not empty and $create_fun is set to false then we'll use a custom callback
2785
+	 *                               instead of the one created in here.
2786
+	 * @param array   $callback_args an array of args supplied for the metabox
2787
+	 * @param string  $column        what metabox column
2788
+	 * @param string  $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2789
+	 * @param boolean $create_func   default is true.  Basically we can say we don't WANT to have the runtime function
2790
+	 *                               created but just set our own callback for wp's add_meta_box.
2791
+	 * @throws \DomainException
2792
+	 */
2793
+	public function _add_admin_page_meta_box(
2794
+		$action,
2795
+		$title,
2796
+		$callback,
2797
+		$callback_args,
2798
+		$column = 'normal',
2799
+		$priority = 'high',
2800
+		$create_func = true
2801
+	) {
2802
+		do_action('AHEE_log', __FILE__, __FUNCTION__, $callback);
2803
+		//if we have empty callback args and we want to automatically create the metabox callback then we need to make sure the callback args are generated.
2804
+		if (empty($callback_args) && $create_func) {
2805
+			$callback_args = array(
2806
+				'template_path' => $this->_template_path,
2807
+				'template_args' => $this->_template_args,
2808
+			);
2809
+		}
2810
+		//if $create_func is true (default) then we automatically create the function for displaying the actual meta box.  If false then we take the $callback reference passed through and use it instead (so callers can define their own callback function/method if they wish)
2811
+		$call_back_func = $create_func
2812
+			? function ($post, $metabox)
2813
+			{
2814
+				do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2815
+				echo EEH_Template::display_template(
2816
+					$metabox['args']['template_path'],
2817
+					$metabox['args']['template_args'],
2818
+					true
2819
+				);
2820
+			}
2821
+			: $callback;
2822
+		add_meta_box(
2823
+			str_replace('_', '-', $action) . '-mbox',
2824
+			$title,
2825
+			$call_back_func,
2826
+			$this->_wp_page_slug,
2827
+			$column,
2828
+			$priority,
2829
+			$callback_args
2830
+		);
2831
+	}
2832
+
2833
+
2834
+
2835
+	/**
2836
+	 * generates HTML wrapper for and admin details page that contains metaboxes in columns
2837
+	 *
2838
+	 * @throws DomainException
2839
+	 * @throws EE_Error
2840
+	 */
2841
+	public function display_admin_page_with_metabox_columns()
2842
+	{
2843
+		$this->_template_args['post_body_content']  = $this->_template_args['admin_page_content'];
2844
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2845
+			$this->_column_template_path,
2846
+			$this->_template_args,
2847
+			true
2848
+		);
2849
+		//the final wrapper
2850
+		$this->admin_page_wrapper();
2851
+	}
2852
+
2853
+
2854
+
2855
+	/**
2856
+	 * generates  HTML wrapper for an admin details page
2857
+	 *
2858
+	 * @return void
2859
+	 * @throws EE_Error
2860
+	 * @throws DomainException
2861
+	 */
2862
+	public function display_admin_page_with_sidebar()
2863
+	{
2864
+		$this->_display_admin_page(true);
2865
+	}
2866
+
2867
+
2868
+
2869
+	/**
2870
+	 * generates  HTML wrapper for an admin details page (except no sidebar)
2871
+	 *
2872
+	 * @return void
2873
+	 * @throws EE_Error
2874
+	 * @throws DomainException
2875
+	 */
2876
+	public function display_admin_page_with_no_sidebar()
2877
+	{
2878
+		$this->_display_admin_page();
2879
+	}
2880
+
2881
+
2882
+
2883
+	/**
2884
+	 * generates HTML wrapper for an EE about admin page (no sidebar)
2885
+	 *
2886
+	 * @return void
2887
+	 * @throws EE_Error
2888
+	 * @throws DomainException
2889
+	 */
2890
+	public function display_about_admin_page()
2891
+	{
2892
+		$this->_display_admin_page(false, true);
2893
+	}
2894
+
2895
+
2896
+
2897
+	/**
2898
+	 * display_admin_page
2899
+	 * contains the code for actually displaying an admin page
2900
+	 *
2901
+	 * @param  boolean $sidebar true with sidebar, false without
2902
+	 * @param  boolean $about   use the about admin wrapper instead of the default.
2903
+	 * @return void
2904
+	 * @throws DomainException
2905
+	 * @throws EE_Error
2906
+	 */
2907
+	private function _display_admin_page($sidebar = false, $about = false)
2908
+	{
2909
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2910
+		//custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2911
+		do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2912
+		// set current wp page slug - looks like: event-espresso_page_event_categories
2913
+		// keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2914
+		$this->_template_args['current_page']              = $this->_wp_page_slug;
2915
+		$this->_template_args['admin_page_wrapper_div_id'] = $this->_cpt_route
2916
+			? 'poststuff'
2917
+			: 'espresso-default-admin';
2918
+		$template_path                                     = $sidebar
2919
+			? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2920
+			: EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2921
+		if (defined('DOING_AJAX') && DOING_AJAX) {
2922
+			$template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2923
+		}
2924
+		$template_path                                     = ! empty($this->_column_template_path)
2925
+			? $this->_column_template_path : $template_path;
2926
+		$this->_template_args['post_body_content']         = isset($this->_template_args['admin_page_content'])
2927
+			? $this->_template_args['admin_page_content']
2928
+			: '';
2929
+		$this->_template_args['before_admin_page_content'] = isset($this->_template_args['before_admin_page_content'])
2930
+			? $this->_template_args['before_admin_page_content']
2931
+			: '';
2932
+		$this->_template_args['after_admin_page_content']  = isset($this->_template_args['after_admin_page_content'])
2933
+			? $this->_template_args['after_admin_page_content']
2934
+			: '';
2935
+		$this->_template_args['admin_page_content']        = EEH_Template::display_template(
2936
+			$template_path,
2937
+			$this->_template_args,
2938
+			true
2939
+		);
2940
+		// the final template wrapper
2941
+		$this->admin_page_wrapper($about);
2942
+	}
2943
+
2944
+
2945
+
2946
+	/**
2947
+	 * This is used to display caf preview pages.
2948
+	 *
2949
+	 * @since 4.3.2
2950
+	 * @param string $utm_campaign_source what is the key used for google analytics link
2951
+	 * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE
2952
+	 *                                    = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2953
+	 * @return void
2954
+	 * @throws DomainException
2955
+	 * @throws EE_Error
2956
+	 * @throws InvalidArgumentException
2957
+	 * @throws InvalidDataTypeException
2958
+	 * @throws InvalidInterfaceException
2959
+	 */
2960
+	public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2961
+	{
2962
+		//let's generate a default preview action button if there isn't one already present.
2963
+		$this->_labels['buttons']['buy_now']           = esc_html__(
2964
+			'Upgrade to Event Espresso 4 Right Now',
2965
+			'event_espresso'
2966
+		);
2967
+		$buy_now_url                                   = add_query_arg(
2968
+			array(
2969
+				'ee_ver'       => 'ee4',
2970
+				'utm_source'   => 'ee4_plugin_admin',
2971
+				'utm_medium'   => 'link',
2972
+				'utm_campaign' => $utm_campaign_source,
2973
+				'utm_content'  => 'buy_now_button',
2974
+			),
2975
+			'http://eventespresso.com/pricing/'
2976
+		);
2977
+		$this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2978
+			? $this->get_action_link_or_button(
2979
+				'',
2980
+				'buy_now',
2981
+				array(),
2982
+				'button-primary button-large',
2983
+				$buy_now_url,
2984
+				true
2985
+			)
2986
+			: $this->_template_args['preview_action_button'];
2987
+		$this->_template_args['admin_page_content']    = EEH_Template::display_template(
2988
+			EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2989
+			$this->_template_args,
2990
+			true
2991
+		);
2992
+		$this->_display_admin_page($display_sidebar);
2993
+	}
2994
+
2995
+
2996
+
2997
+	/**
2998
+	 * display_admin_list_table_page_with_sidebar
2999
+	 * generates HTML wrapper for an admin_page with list_table
3000
+	 *
3001
+	 * @return void
3002
+	 * @throws EE_Error
3003
+	 * @throws DomainException
3004
+	 */
3005
+	public function display_admin_list_table_page_with_sidebar()
3006
+	{
3007
+		$this->_display_admin_list_table_page(true);
3008
+	}
3009
+
3010
+
3011
+
3012
+	/**
3013
+	 * display_admin_list_table_page_with_no_sidebar
3014
+	 * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
3015
+	 *
3016
+	 * @return void
3017
+	 * @throws EE_Error
3018
+	 * @throws DomainException
3019
+	 */
3020
+	public function display_admin_list_table_page_with_no_sidebar()
3021
+	{
3022
+		$this->_display_admin_list_table_page();
3023
+	}
3024
+
3025
+
3026
+
3027
+	/**
3028
+	 * generates html wrapper for an admin_list_table page
3029
+	 *
3030
+	 * @param boolean $sidebar whether to display with sidebar or not.
3031
+	 * @return void
3032
+	 * @throws DomainException
3033
+	 * @throws EE_Error
3034
+	 */
3035
+	private function _display_admin_list_table_page($sidebar = false)
3036
+	{
3037
+		//setup search attributes
3038
+		$this->_set_search_attributes();
3039
+		$this->_template_args['current_page']     = $this->_wp_page_slug;
3040
+		$template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
3041
+		$this->_template_args['table_url']        = defined('DOING_AJAX')
3042
+			? add_query_arg(array('noheader' => 'true', 'route' => $this->_req_action), $this->_admin_base_url)
3043
+			: add_query_arg(array('route' => $this->_req_action), $this->_admin_base_url);
3044
+		$this->_template_args['list_table']       = $this->_list_table_object;
3045
+		$this->_template_args['current_route']    = $this->_req_action;
3046
+		$this->_template_args['list_table_class'] = get_class($this->_list_table_object);
3047
+		$ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
3048
+		if (! empty($ajax_sorting_callback)) {
3049
+			$sortable_list_table_form_fields = wp_nonce_field(
3050
+				$ajax_sorting_callback . '_nonce',
3051
+				$ajax_sorting_callback . '_nonce',
3052
+				false,
3053
+				false
3054
+			);
3055
+			//			$reorder_action = 'espresso_' . $ajax_sorting_callback . '_nonce';
3056
+			//			$sortable_list_table_form_fields = wp_nonce_field( $reorder_action, 'ajax_table_sort_nonce', FALSE, FALSE );
3057
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="'
3058
+												. $this->page_slug
3059
+												. '" />';
3060
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="'
3061
+												. $ajax_sorting_callback
3062
+												. '" />';
3063
+		} else {
3064
+			$sortable_list_table_form_fields = '';
3065
+		}
3066
+		$this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
3067
+		$hidden_form_fields                                      = isset($this->_template_args['list_table_hidden_fields'])
3068
+			? $this->_template_args['list_table_hidden_fields']
3069
+			: '';
3070
+		$nonce_ref                                               = $this->_req_action . '_nonce';
3071
+		$hidden_form_fields                                      .= '<input type="hidden" name="'
3072
+																	. $nonce_ref
3073
+																	. '" value="'
3074
+																	. wp_create_nonce($nonce_ref)
3075
+																	. '">';
3076
+		$this->_template_args['list_table_hidden_fields']        = $hidden_form_fields;
3077
+		//display message about search results?
3078
+		$this->_template_args['before_list_table'] .= ! empty($this->_req_data['s'])
3079
+			? '<p class="ee-search-results">' . sprintf(
3080
+				esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
3081
+				trim($this->_req_data['s'], '%')
3082
+			) . '</p>'
3083
+			: '';
3084
+		// filter before_list_table template arg
3085
+		$this->_template_args['before_list_table'] = apply_filters(
3086
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
3087
+			$this->_template_args['before_list_table'],
3088
+			$this->page_slug,
3089
+			$this->_req_data,
3090
+			$this->_req_action
3091
+		);
3092
+		// convert to array and filter again
3093
+		// arrays are easier to inject new items in a specific location,
3094
+		// but would not be backwards compatible, so we have to add a new filter
3095
+		$this->_template_args['before_list_table'] = implode(
3096
+			" \n",
3097
+			(array)apply_filters(
3098
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
3099
+				(array)$this->_template_args['before_list_table'],
3100
+				$this->page_slug,
3101
+				$this->_req_data,
3102
+				$this->_req_action
3103
+			)
3104
+		);
3105
+		// filter after_list_table template arg
3106
+		$this->_template_args['after_list_table'] = apply_filters(
3107
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
3108
+			$this->_template_args['after_list_table'],
3109
+			$this->page_slug,
3110
+			$this->_req_data,
3111
+			$this->_req_action
3112
+		);
3113
+		// convert to array and filter again
3114
+		// arrays are easier to inject new items in a specific location,
3115
+		// but would not be backwards compatible, so we have to add a new filter
3116
+		$this->_template_args['after_list_table']   = implode(
3117
+			" \n",
3118
+			(array)apply_filters(
3119
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
3120
+				(array)$this->_template_args['after_list_table'],
3121
+				$this->page_slug,
3122
+				$this->_req_data,
3123
+				$this->_req_action
3124
+			)
3125
+		);
3126
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
3127
+			$template_path,
3128
+			$this->_template_args,
3129
+			true
3130
+		);
3131
+		// the final template wrapper
3132
+		if ($sidebar) {
3133
+			$this->display_admin_page_with_sidebar();
3134
+		} else {
3135
+			$this->display_admin_page_with_no_sidebar();
3136
+		}
3137
+	}
3138
+
3139
+
3140
+
3141
+	/**
3142
+	 * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the
3143
+	 * html string for the legend.
3144
+	 * $items are expected in an array in the following format:
3145
+	 * $legend_items = array(
3146
+	 *        'item_id' => array(
3147
+	 *            'icon' => 'http://url_to_icon_being_described.png',
3148
+	 *            'desc' => esc_html__('localized description of item');
3149
+	 *        )
3150
+	 * );
3151
+	 *
3152
+	 * @param  array $items see above for format of array
3153
+	 * @return string html string of legend
3154
+	 * @throws DomainException
3155
+	 */
3156
+	protected function _display_legend($items)
3157
+	{
3158
+		$this->_template_args['items'] = apply_filters(
3159
+			'FHEE__EE_Admin_Page___display_legend__items',
3160
+			(array)$items,
3161
+			$this
3162
+		);
3163
+		return EEH_Template::display_template(
3164
+			EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3165
+			$this->_template_args,
3166
+			true
3167
+		);
3168
+	}
3169
+
3170
+
3171
+	/**
3172
+	 * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
3173
+	 * The returned json object is created from an array in the following format:
3174
+	 * array(
3175
+	 *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
3176
+	 *  'success' => FALSE, //(default FALSE) - contains any special success message.
3177
+	 *  'notices' => '', // - contains any EE_Error formatted notices
3178
+	 *  'content' => 'string can be html', //this is a string of formatted content (can be html)
3179
+	 *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
3180
+	 *  We're also going to include the template args with every package (so js can pick out any specific template args
3181
+	 *  that might be included in here)
3182
+	 * )
3183
+	 * The json object is populated by whatever is set in the $_template_args property.
3184
+	 *
3185
+	 * @param bool  $sticky_notices    Used to indicate whether you want to ensure notices are added to a transient
3186
+	 *                                 instead of displayed.
3187
+	 * @param array $notices_arguments Use this to pass any additional args on to the _process_notices.
3188
+	 * @return void
3189
+	 * @throws EE_Error
3190
+	 */
3191
+	protected function _return_json($sticky_notices = false, $notices_arguments = array())
3192
+	{
3193
+		//make sure any EE_Error notices have been handled.
3194
+		$this->_process_notices($notices_arguments, true, $sticky_notices);
3195
+		$data = isset($this->_template_args['data']) ? $this->_template_args['data'] : array();
3196
+		unset($this->_template_args['data']);
3197
+		$json = array(
3198
+			'error'     => isset($this->_template_args['error']) ? $this->_template_args['error'] : false,
3199
+			'success'   => isset($this->_template_args['success']) ? $this->_template_args['success'] : false,
3200
+			'errors'    => isset($this->_template_args['errors']) ? $this->_template_args['errors'] : false,
3201
+			'attention' => isset($this->_template_args['attention']) ? $this->_template_args['attention'] : false,
3202
+			'notices'   => EE_Error::get_notices(),
3203
+			'content'   => isset($this->_template_args['admin_page_content'])
3204
+				? $this->_template_args['admin_page_content'] : '',
3205
+			'data'      => array_merge($data, array('template_args' => $this->_template_args)),
3206
+			'isEEajax'  => true
3207
+			//special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
3208
+		);
3209
+		// make sure there are no php errors or headers_sent.  Then we can set correct json header.
3210
+		if (null === error_get_last() || ! headers_sent()) {
3211
+			header('Content-Type: application/json; charset=UTF-8');
3212
+		}
3213
+		echo wp_json_encode($json);
3214
+		exit();
3215
+	}
3216
+
3217
+
3218
+
3219
+	/**
3220
+	 * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
3221
+	 *
3222
+	 * @return void
3223
+	 * @throws EE_Error
3224
+	 */
3225
+	public function return_json()
3226
+	{
3227
+		if (defined('DOING_AJAX') && DOING_AJAX) {
3228
+			$this->_return_json();
3229
+		} else {
3230
+			throw new EE_Error(
3231
+				sprintf(
3232
+					esc_html__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'),
3233
+					__FUNCTION__
3234
+				)
3235
+			);
3236
+		}
3237
+	}
3238
+
3239
+
3240
+
3241
+	/**
3242
+	 * This provides a way for child hook classes to send along themselves by reference so methods/properties within
3243
+	 * them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
3244
+	 *
3245
+	 * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
3246
+	 */
3247
+	public function set_hook_object(EE_Admin_Hooks $hook_obj)
3248
+	{
3249
+		$this->_hook_obj = $hook_obj;
3250
+	}
3251
+
3252
+
3253
+
3254
+	/**
3255
+	 *        generates  HTML wrapper with Tabbed nav for an admin page
3256
+	 *
3257
+	 * @param  boolean $about whether to use the special about page wrapper or default.
3258
+	 * @return void
3259
+	 * @throws DomainException
3260
+	 * @throws EE_Error
3261
+	 */
3262
+	public function admin_page_wrapper($about = false)
3263
+	{
3264
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3265
+		$this->_nav_tabs                                   = $this->_get_main_nav_tabs();
3266
+		$this->_template_args['nav_tabs']                  = $this->_nav_tabs;
3267
+		$this->_template_args['admin_page_title']          = $this->_admin_page_title;
3268
+		$this->_template_args['before_admin_page_content'] = apply_filters(
3269
+			"FHEE_before_admin_page_content{$this->_current_page}{$this->_current_view}",
3270
+			isset($this->_template_args['before_admin_page_content'])
3271
+				? $this->_template_args['before_admin_page_content']
3272
+				: ''
3273
+		);
3274
+		$this->_template_args['after_admin_page_content']  = apply_filters(
3275
+			"FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3276
+			isset($this->_template_args['after_admin_page_content'])
3277
+				? $this->_template_args['after_admin_page_content']
3278
+				: ''
3279
+		);
3280
+		$this->_template_args['after_admin_page_content']  .= $this->_set_help_popup_content();
3281
+		// load settings page wrapper template
3282
+		$template_path = ! defined('DOING_AJAX')
3283
+			? EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php'
3284
+			: EE_ADMIN_TEMPLATE
3285
+			  . 'admin_wrapper_ajax.template.php';
3286
+		//about page?
3287
+		$template_path = $about
3288
+			? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3289
+			: $template_path;
3290
+		if (defined('DOING_AJAX')) {
3291
+			$this->_template_args['admin_page_content'] = EEH_Template::display_template(
3292
+				$template_path,
3293
+				$this->_template_args,
3294
+				true
3295
+			);
3296
+			$this->_return_json();
3297
+		} else {
3298
+			EEH_Template::display_template($template_path, $this->_template_args);
3299
+		}
3300
+	}
3301
+
3302
+
3303
+
3304
+	/**
3305
+	 * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
3306
+	 *
3307
+	 * @return string html
3308
+	 * @throws EE_Error
3309
+	 */
3310
+	protected function _get_main_nav_tabs()
3311
+	{
3312
+		// let's generate the html using the EEH_Tabbed_Content helper.
3313
+		// We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute
3314
+		// (rather than setting in the page_routes array)
3315
+		return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs);
3316
+	}
3317
+
3318
+
3319
+
3320
+	/**
3321
+	 *        sort nav tabs
3322
+	 *
3323
+	 * @param $a
3324
+	 * @param $b
3325
+	 * @return int
3326
+	 */
3327
+	private function _sort_nav_tabs($a, $b)
3328
+	{
3329
+		if ($a['order'] === $b['order']) {
3330
+			return 0;
3331
+		}
3332
+		return ($a['order'] < $b['order']) ? -1 : 1;
3333
+	}
3334
+
3335
+
3336
+
3337
+	/**
3338
+	 *    generates HTML for the forms used on admin pages
3339
+	 *
3340
+	 * @param    array $input_vars - array of input field details
3341
+	 * @param string   $generator  (options are 'string' or 'array', basically use this to indicate which generator to
3342
+	 *                             use)
3343
+	 * @param bool     $id
3344
+	 * @return string
3345
+	 * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
3346
+	 * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
3347
+	 */
3348
+	protected function _generate_admin_form_fields($input_vars = array(), $generator = 'string', $id = false)
3349
+	{
3350
+		$content = $generator === 'string'
3351
+			? EEH_Form_Fields::get_form_fields($input_vars, $id)
3352
+			: EEH_Form_Fields::get_form_fields_array($input_vars);
3353
+		return $content;
3354
+	}
3355
+
3356
+
3357
+
3358
+	/**
3359
+	 * generates the "Save" and "Save & Close" buttons for edit forms
3360
+	 *
3361
+	 * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save &
3362
+	 *                                   Close" button.
3363
+	 * @param array            $text     if included, generator will use the given text for the buttons ( array([0] =>
3364
+	 *                                   'Save', [1] => 'save & close')
3365
+	 * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e.
3366
+	 *                                   via the "name" value in the button).  We can also use this to just dump
3367
+	 *                                   default actions by submitting some other value.
3368
+	 * @param bool|string|null $referrer if false then we just do the default action on save and close.  Other wise it
3369
+	 *                                   will use the $referrer string. IF null, then we don't do ANYTHING on save and
3370
+	 *                                   close (normal form handling).
3371
+	 */
3372
+	protected function _set_save_buttons($both = true, $text = array(), $actions = array(), $referrer = null)
3373
+	{
3374
+		//make sure $text and $actions are in an array
3375
+		$text          = (array)$text;
3376
+		$actions       = (array)$actions;
3377
+		$referrer_url  = empty($referrer)
3378
+			? '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3379
+			  . $_SERVER['REQUEST_URI']
3380
+			  . '" />'
3381
+			: '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3382
+			  . $referrer
3383
+			  . '" />';
3384
+		$button_text   = ! empty($text)
3385
+			? $text
3386
+			: array(
3387
+				esc_html__('Save', 'event_espresso'),
3388
+				esc_html__('Save and Close', 'event_espresso'),
3389
+			);
3390
+		$default_names = array('save', 'save_and_close');
3391
+		//add in a hidden index for the current page (so save and close redirects properly)
3392
+		$this->_template_args['save_buttons'] = $referrer_url;
3393
+		foreach ($button_text as $key => $button) {
3394
+			$ref                                  = $default_names[$key];
3395
+			$this->_template_args['save_buttons'] .= '<input type="submit" class="button-primary '
3396
+													 . $ref
3397
+													 . '" value="'
3398
+													 . $button
3399
+													 . '" name="'
3400
+													 . (! empty($actions) ? $actions[$key] : $ref)
3401
+													 . '" id="'
3402
+													 . $this->_current_view . '_' . $ref
3403
+													 . '" />';
3404
+			if (! $both) {
3405
+				break;
3406
+			}
3407
+		}
3408
+	}
3409
+
3410
+
3411
+
3412
+	/**
3413
+	 * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
3414
+	 *
3415
+	 * @see   $this->_set_add_edit_form_tags() for details on params
3416
+	 * @since 4.6.0
3417
+	 * @param string $route
3418
+	 * @param array  $additional_hidden_fields
3419
+	 */
3420
+	public function set_add_edit_form_tags($route = '', $additional_hidden_fields = array())
3421
+	{
3422
+		$this->_set_add_edit_form_tags($route, $additional_hidden_fields);
3423
+	}
3424
+
3425
+
3426
+
3427
+	/**
3428
+	 * set form open and close tags on add/edit pages.
3429
+	 *
3430
+	 * @param string $route                    the route you want the form to direct to
3431
+	 * @param array  $additional_hidden_fields any additional hidden fields required in the form header
3432
+	 * @return void
3433
+	 */
3434
+	protected function _set_add_edit_form_tags($route = '', $additional_hidden_fields = array())
3435
+	{
3436
+		if (empty($route)) {
3437
+			$user_msg = esc_html__(
3438
+				'An error occurred. No action was set for this page\'s form.',
3439
+				'event_espresso'
3440
+			);
3441
+			$dev_msg  = $user_msg . "\n" . sprintf(
3442
+					esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3443
+					__FUNCTION__,
3444
+					__CLASS__
3445
+				);
3446
+			EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3447
+		}
3448
+		// open form
3449
+		$this->_template_args['before_admin_page_content'] = '<form name="form" method="post" action="'
3450
+															 . $this->_admin_base_url
3451
+															 . '" id="'
3452
+															 . $route
3453
+															 . '_event_form" >';
3454
+		// add nonce
3455
+		$nonce = wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3456
+		//		$nonce = wp_nonce_field( $route . '_nonce', '_wpnonce', FALSE, FALSE );
3457
+		$this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3458
+		// add REQUIRED form action
3459
+		$hidden_fields = array(
3460
+			'action' => array('type' => 'hidden', 'value' => $route),
3461
+		);
3462
+		// merge arrays
3463
+		$hidden_fields = is_array($additional_hidden_fields)
3464
+			? array_merge($hidden_fields, $additional_hidden_fields)
3465
+			: $hidden_fields;
3466
+		// generate form fields
3467
+		$form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3468
+		// add fields to form
3469
+		foreach ((array)$form_fields as $field_name => $form_field) {
3470
+			$this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3471
+		}
3472
+		// close form
3473
+		$this->_template_args['after_admin_page_content'] = '</form>';
3474
+	}
3475
+
3476
+
3477
+
3478
+	/**
3479
+	 * Public Wrapper for _redirect_after_action() method since its
3480
+	 * discovered it would be useful for external code to have access.
3481
+	 *
3482
+	 * @see   EE_Admin_Page::_redirect_after_action() for params.
3483
+	 * @since 4.5.0
3484
+	 * @param bool   $success
3485
+	 * @param string $what
3486
+	 * @param string $action_desc
3487
+	 * @param array  $query_args
3488
+	 * @param bool   $override_overwrite
3489
+	 * @throws EE_Error
3490
+	 */
3491
+	public function redirect_after_action(
3492
+		$success = false,
3493
+		$what = 'item',
3494
+		$action_desc = 'processed',
3495
+		$query_args = array(),
3496
+		$override_overwrite = false
3497
+	) {
3498
+		$this->_redirect_after_action(
3499
+			$success,
3500
+			$what,
3501
+			$action_desc,
3502
+			$query_args,
3503
+			$override_overwrite
3504
+		);
3505
+	}
3506
+
3507
+
3508
+
3509
+	/**
3510
+	 *    _redirect_after_action
3511
+	 *
3512
+	 * @param int    $success            - whether success was for two or more records, or just one, or none
3513
+	 * @param string $what               - what the action was performed on
3514
+	 * @param string $action_desc        - what was done ie: updated, deleted, etc
3515
+	 * @param array  $query_args         - an array of query_args to be added to the URL to redirect to after the admin
3516
+	 *                                   action is completed
3517
+	 * @param BOOL   $override_overwrite by default all EE_Error::success messages are overwritten, this allows you to
3518
+	 *                                   override this so that they show.
3519
+	 * @return void
3520
+	 * @throws EE_Error
3521
+	 */
3522
+	protected function _redirect_after_action(
3523
+		$success = 0,
3524
+		$what = 'item',
3525
+		$action_desc = 'processed',
3526
+		$query_args = array(),
3527
+		$override_overwrite = false
3528
+	) {
3529
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3530
+		//class name for actions/filters.
3531
+		$classname = get_class($this);
3532
+		// set redirect url.
3533
+		// Note if there is a "page" index in the $query_args then we go with vanilla admin.php route,
3534
+		// otherwise we go with whatever is set as the _admin_base_url
3535
+		$redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3536
+		$notices      = EE_Error::get_notices(false);
3537
+		// overwrite default success messages //BUT ONLY if overwrite not overridden
3538
+		if (! $override_overwrite || ! empty($notices['errors'])) {
3539
+			EE_Error::overwrite_success();
3540
+		}
3541
+		if (! empty($what) && ! empty($action_desc)  && empty($notices['errors'])) {
3542
+			// how many records affected ? more than one record ? or just one ?
3543
+			if ($success > 1) {
3544
+				// set plural msg
3545
+				EE_Error::add_success(
3546
+					sprintf(
3547
+						esc_html__('The "%s" have been successfully %s.', 'event_espresso'),
3548
+						$what,
3549
+						$action_desc
3550
+					),
3551
+					__FILE__,
3552
+					__FUNCTION__,
3553
+					__LINE__
3554
+				);
3555
+			} elseif ($success === 1) {
3556
+				// set singular msg
3557
+				EE_Error::add_success(
3558
+					sprintf(
3559
+						esc_html__('The "%s" has been successfully %s.', 'event_espresso'),
3560
+						$what,
3561
+						$action_desc
3562
+					),
3563
+					__FILE__,
3564
+					__FUNCTION__,
3565
+					__LINE__
3566
+				);
3567
+			}
3568
+		}
3569
+		// check that $query_args isn't something crazy
3570
+		if (! is_array($query_args)) {
3571
+			$query_args = array();
3572
+		}
3573
+		/**
3574
+		 * Allow injecting actions before the query_args are modified for possible different
3575
+		 * redirections on save and close actions
3576
+		 *
3577
+		 * @since 4.2.0
3578
+		 * @param array $query_args       The original query_args array coming into the
3579
+		 *                                method.
3580
+		 */
3581
+		do_action(
3582
+			"AHEE__{$classname}___redirect_after_action__before_redirect_modification_{$this->_req_action}",
3583
+			$query_args
3584
+		);
3585
+		//calculate where we're going (if we have a "save and close" button pushed)
3586
+		if (isset($this->_req_data['save_and_close'], $this->_req_data['save_and_close_referrer'])) {
3587
+			// even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
3588
+			$parsed_url = parse_url($this->_req_data['save_and_close_referrer']);
3589
+			// regenerate query args array from referrer URL
3590
+			parse_str($parsed_url['query'], $query_args);
3591
+			// correct page and action will be in the query args now
3592
+			$redirect_url = admin_url('admin.php');
3593
+		}
3594
+		//merge any default query_args set in _default_route_query_args property
3595
+		if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3596
+			$args_to_merge = array();
3597
+			foreach ($this->_default_route_query_args as $query_param => $query_value) {
3598
+				//is there a wp_referer array in our _default_route_query_args property?
3599
+				if ($query_param === 'wp_referer') {
3600
+					$query_value = (array)$query_value;
3601
+					foreach ($query_value as $reference => $value) {
3602
+						if (strpos($reference, 'nonce') !== false) {
3603
+							continue;
3604
+						}
3605
+						//finally we will override any arguments in the referer with
3606
+						//what might be set on the _default_route_query_args array.
3607
+						if (isset($this->_default_route_query_args[$reference])) {
3608
+							$args_to_merge[$reference] = urlencode($this->_default_route_query_args[$reference]);
3609
+						} else {
3610
+							$args_to_merge[$reference] = urlencode($value);
3611
+						}
3612
+					}
3613
+					continue;
3614
+				}
3615
+				$args_to_merge[$query_param] = $query_value;
3616
+			}
3617
+			//now let's merge these arguments but override with what was specifically sent in to the
3618
+			//redirect.
3619
+			$query_args = array_merge($args_to_merge, $query_args);
3620
+		}
3621
+		$this->_process_notices($query_args);
3622
+		// generate redirect url
3623
+		// if redirecting to anything other than the main page, add a nonce
3624
+		if (isset($query_args['action'])) {
3625
+			// manually generate wp_nonce and merge that with the query vars
3626
+			// becuz the wp_nonce_url function wrecks havoc on some vars
3627
+			$query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3628
+		}
3629
+		// we're adding some hooks and filters in here for processing any things just before redirects
3630
+		// (example: an admin page has done an insert or update and we want to run something after that).
3631
+		do_action('AHEE_redirect_' . $classname . $this->_req_action, $query_args);
3632
+		$redirect_url = apply_filters(
3633
+			'FHEE_redirect_' . $classname . $this->_req_action,
3634
+			self::add_query_args_and_nonce($query_args, $redirect_url),
3635
+			$query_args
3636
+		);
3637
+		// check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3638
+		if (defined('DOING_AJAX')) {
3639
+			$default_data                    = array(
3640
+				'close'        => true,
3641
+				'redirect_url' => $redirect_url,
3642
+				'where'        => 'main',
3643
+				'what'         => 'append',
3644
+			);
3645
+			$this->_template_args['success'] = $success;
3646
+			$this->_template_args['data']    = ! empty($this->_template_args['data']) ? array_merge(
3647
+				$default_data,
3648
+				$this->_template_args['data']
3649
+			) : $default_data;
3650
+			$this->_return_json();
3651
+		}
3652
+		wp_safe_redirect($redirect_url);
3653
+		exit();
3654
+	}
3655
+
3656
+
3657
+
3658
+	/**
3659
+	 * process any notices before redirecting (or returning ajax request)
3660
+	 * This method sets the $this->_template_args['notices'] attribute;
3661
+	 *
3662
+	 * @param  array $query_args        any query args that need to be used for notice transient ('action')
3663
+	 * @param bool   $skip_route_verify This is typically used when we are processing notices REALLY early and
3664
+	 *                                  page_routes haven't been defined yet.
3665
+	 * @param bool   $sticky_notices    This is used to flag that regardless of whether this is doing_ajax or not, we
3666
+	 *                                  still save a transient for the notice.
3667
+	 * @return void
3668
+	 * @throws EE_Error
3669
+	 */
3670
+	protected function _process_notices($query_args = array(), $skip_route_verify = false, $sticky_notices = true)
3671
+	{
3672
+		//first let's set individual error properties if doing_ajax and the properties aren't already set.
3673
+		if (defined('DOING_AJAX') && DOING_AJAX) {
3674
+			$notices = EE_Error::get_notices(false);
3675
+			if (empty($this->_template_args['success'])) {
3676
+				$this->_template_args['success'] = isset($notices['success']) ? $notices['success'] : false;
3677
+			}
3678
+			if (empty($this->_template_args['errors'])) {
3679
+				$this->_template_args['errors'] = isset($notices['errors']) ? $notices['errors'] : false;
3680
+			}
3681
+			if (empty($this->_template_args['attention'])) {
3682
+				$this->_template_args['attention'] = isset($notices['attention']) ? $notices['attention'] : false;
3683
+			}
3684
+		}
3685
+		$this->_template_args['notices'] = EE_Error::get_notices();
3686
+		//IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3687
+		if (! defined('DOING_AJAX') || $sticky_notices) {
3688
+			$route = isset($query_args['action']) ? $query_args['action'] : 'default';
3689
+			$this->_add_transient(
3690
+				$route,
3691
+				$this->_template_args['notices'],
3692
+				true,
3693
+				$skip_route_verify
3694
+			);
3695
+		}
3696
+	}
3697
+
3698
+
3699
+
3700
+	/**
3701
+	 * get_action_link_or_button
3702
+	 * returns the button html for adding, editing, or deleting an item (depending on given type)
3703
+	 *
3704
+	 * @param string $action        use this to indicate which action the url is generated with.
3705
+	 * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key)
3706
+	 *                              property.
3707
+	 * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
3708
+	 * @param string $class         Use this to give the class for the button. Defaults to 'button-primary'
3709
+	 * @param string $base_url      If this is not provided
3710
+	 *                              the _admin_base_url will be used as the default for the button base_url.
3711
+	 *                              Otherwise this value will be used.
3712
+	 * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
3713
+	 * @return string
3714
+	 * @throws InvalidArgumentException
3715
+	 * @throws InvalidInterfaceException
3716
+	 * @throws InvalidDataTypeException
3717
+	 * @throws EE_Error
3718
+	 */
3719
+	public function get_action_link_or_button(
3720
+		$action,
3721
+		$type = 'add',
3722
+		$extra_request = array(),
3723
+		$class = 'button-primary',
3724
+		$base_url = '',
3725
+		$exclude_nonce = false
3726
+	) {
3727
+		//first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3728
+		if (empty($base_url) && ! isset($this->_page_routes[$action])) {
3729
+			throw new EE_Error(
3730
+				sprintf(
3731
+					esc_html__(
3732
+						'There is no page route for given action for the button.  This action was given: %s',
3733
+						'event_espresso'
3734
+					),
3735
+					$action
3736
+				)
3737
+			);
3738
+		}
3739
+		if (! isset($this->_labels['buttons'][$type])) {
3740
+			throw new EE_Error(
3741
+				sprintf(
3742
+					__(
3743
+						'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
3744
+						'event_espresso'
3745
+					),
3746
+					$type
3747
+				)
3748
+			);
3749
+		}
3750
+		//finally check user access for this button.
3751
+		$has_access = $this->check_user_access($action, true);
3752
+		if (! $has_access) {
3753
+			return '';
3754
+		}
3755
+		$_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
3756
+		$query_args = array(
3757
+			'action' => $action,
3758
+		);
3759
+		//merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3760
+		if (! empty($extra_request)) {
3761
+			$query_args = array_merge($extra_request, $query_args);
3762
+		}
3763
+		$url = self::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3764
+		return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][$type], $class);
3765
+	}
3766
+
3767
+
3768
+
3769
+	/**
3770
+	 * _per_page_screen_option
3771
+	 * Utility function for adding in a per_page_option in the screen_options_dropdown.
3772
+	 *
3773
+	 * @return void
3774
+	 * @throws InvalidArgumentException
3775
+	 * @throws InvalidInterfaceException
3776
+	 * @throws InvalidDataTypeException
3777
+	 */
3778
+	protected function _per_page_screen_option()
3779
+	{
3780
+		$option = 'per_page';
3781
+		$args   = array(
3782
+			'label'   => esc_html__(
3783
+					apply_filters(
3784
+						'FHEE__EE_Admin_Page___per_page_screen_options___label',
3785
+						$this->_admin_page_title,
3786
+						$this
3787
+					)
3788
+			),
3789
+			'default' => (int) apply_filters(
3790
+					'FHEE__EE_Admin_Page___per_page_screen_options__default',
3791
+					10
3792
+			),
3793
+			'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3794
+		);
3795
+		//ONLY add the screen option if the user has access to it.
3796
+		if ($this->check_user_access($this->_current_view, true)) {
3797
+			add_screen_option($option, $args);
3798
+		}
3799
+	}
3800
+
3801
+
3802
+
3803
+	/**
3804
+	 * set_per_page_screen_option
3805
+	 * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3806
+	 * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than
3807
+	 * admin_menu.
3808
+	 *
3809
+	 * @return void
3810
+	 */
3811
+	private function _set_per_page_screen_options()
3812
+	{
3813
+		if (isset($_POST['wp_screen_options']) && is_array($_POST['wp_screen_options'])) {
3814
+			check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3815
+			if (! $user = wp_get_current_user()) {
3816
+				return;
3817
+			}
3818
+			$option = $_POST['wp_screen_options']['option'];
3819
+			$value  = $_POST['wp_screen_options']['value'];
3820
+			if ($option != sanitize_key($option)) {
3821
+				return;
3822
+			}
3823
+			$map_option = $option;
3824
+			$option     = str_replace('-', '_', $option);
3825
+			switch ($map_option) {
3826
+				case $this->_current_page . '_' . $this->_current_view . '_per_page':
3827
+					$value = (int)$value;
3828
+					$max_value = apply_filters(
3829
+						'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3830
+						999,
3831
+						$this->_current_page,
3832
+						$this->_current_view
3833
+					);
3834
+					if ($value < 1) {
3835
+						return;
3836
+					}
3837
+					$value = min($value, $max_value);
3838
+					break;
3839
+				default:
3840
+					$value = apply_filters(
3841
+						'FHEE__EE_Admin_Page___set_per_page_screen_options__value',
3842
+						false,
3843
+						$option,
3844
+						$value
3845
+					);
3846
+					if (false === $value) {
3847
+						return;
3848
+					}
3849
+					break;
3850
+			}
3851
+			update_user_meta($user->ID, $option, $value);
3852
+			wp_safe_redirect(remove_query_arg(array('pagenum', 'apage', 'paged'), wp_get_referer()));
3853
+			exit;
3854
+		}
3855
+	}
3856
+
3857
+
3858
+
3859
+	/**
3860
+	 * This just allows for setting the $_template_args property if it needs to be set outside the object
3861
+	 *
3862
+	 * @param array $data array that will be assigned to template args.
3863
+	 */
3864
+	public function set_template_args($data)
3865
+	{
3866
+		$this->_template_args = array_merge($this->_template_args, (array)$data);
3867
+	}
3868
+
3869
+
3870
+
3871
+	/**
3872
+	 * This makes available the WP transient system for temporarily moving data between routes
3873
+	 *
3874
+	 * @param string $route             the route that should receive the transient
3875
+	 * @param array  $data              the data that gets sent
3876
+	 * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise its just a
3877
+	 *                                  normal route transient.
3878
+	 * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used
3879
+	 *                                  when we are adding a transient before page_routes have been defined.
3880
+	 * @return void
3881
+	 * @throws EE_Error
3882
+	 */
3883
+	protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3884
+	{
3885
+		$user_id = get_current_user_id();
3886
+		if (! $skip_route_verify) {
3887
+			$this->_verify_route($route);
3888
+		}
3889
+		//now let's set the string for what kind of transient we're setting
3890
+		$transient = $notices
3891
+			? 'ee_rte_n_tx_' . $route . '_' . $user_id
3892
+			: 'rte_tx_' . $route . '_' . $user_id;
3893
+		$data      = $notices ? array('notices' => $data) : $data;
3894
+		//is there already a transient for this route?  If there is then let's ADD to that transient
3895
+		$existing = is_multisite() && is_network_admin()
3896
+			? get_site_transient($transient)
3897
+			: get_transient($transient);
3898
+		if ($existing) {
3899
+			$data = array_merge((array)$data, (array)$existing);
3900
+		}
3901
+		if (is_multisite() && is_network_admin()) {
3902
+			set_site_transient($transient, $data, 8);
3903
+		} else {
3904
+			set_transient($transient, $data, 8);
3905
+		}
3906
+	}
3907
+
3908
+
3909
+
3910
+	/**
3911
+	 * this retrieves the temporary transient that has been set for moving data between routes.
3912
+	 *
3913
+	 * @param bool   $notices true we get notices transient. False we just return normal route transient
3914
+	 * @param string $route
3915
+	 * @return mixed data
3916
+	 */
3917
+	protected function _get_transient($notices = false, $route = '')
3918
+	{
3919
+		$user_id   = get_current_user_id();
3920
+		$route     = ! $route ? $this->_req_action : $route;
3921
+		$transient = $notices
3922
+			? 'ee_rte_n_tx_' . $route . '_' . $user_id
3923
+			: 'rte_tx_' . $route . '_' . $user_id;
3924
+		$data      = is_multisite() && is_network_admin()
3925
+			? get_site_transient($transient)
3926
+			: get_transient($transient);
3927
+		//delete transient after retrieval (just in case it hasn't expired);
3928
+		if (is_multisite() && is_network_admin()) {
3929
+			delete_site_transient($transient);
3930
+		} else {
3931
+			delete_transient($transient);
3932
+		}
3933
+		return $notices && isset($data['notices']) ? $data['notices'] : $data;
3934
+	}
3935
+
3936
+
3937
+
3938
+	/**
3939
+	 * The purpose of this method is just to run garbage collection on any EE transients that might have expired but
3940
+	 * would not be called later. This will be assigned to run on a specific EE Admin page. (place the method in the
3941
+	 * default route callback on the EE_Admin page you want it run.)
3942
+	 *
3943
+	 * @return void
3944
+	 */
3945
+	protected function _transient_garbage_collection()
3946
+	{
3947
+		global $wpdb;
3948
+		//retrieve all existing transients
3949
+		$query = "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3950
+		if ($results = $wpdb->get_results($query)) {
3951
+			foreach ($results as $result) {
3952
+				$transient = str_replace('_transient_', '', $result->option_name);
3953
+				get_transient($transient);
3954
+				if (is_multisite() && is_network_admin()) {
3955
+					get_site_transient($transient);
3956
+				}
3957
+			}
3958
+		}
3959
+	}
3960
+
3961
+
3962
+
3963
+	/**
3964
+	 * get_view
3965
+	 *
3966
+	 * @return string content of _view property
3967
+	 */
3968
+	public function get_view()
3969
+	{
3970
+		return $this->_view;
3971
+	}
3972
+
3973
+
3974
+
3975
+	/**
3976
+	 * getter for the protected $_views property
3977
+	 *
3978
+	 * @return array
3979
+	 */
3980
+	public function get_views()
3981
+	{
3982
+		return $this->_views;
3983
+	}
3984
+
3985
+
3986
+
3987
+	/**
3988
+	 * get_current_page
3989
+	 *
3990
+	 * @return string _current_page property value
3991
+	 */
3992
+	public function get_current_page()
3993
+	{
3994
+		return $this->_current_page;
3995
+	}
3996
+
3997
+
3998
+
3999
+	/**
4000
+	 * get_current_view
4001
+	 *
4002
+	 * @return string _current_view property value
4003
+	 */
4004
+	public function get_current_view()
4005
+	{
4006
+		return $this->_current_view;
4007
+	}
4008
+
4009
+
4010
+
4011
+	/**
4012
+	 * get_current_screen
4013
+	 *
4014
+	 * @return object The current WP_Screen object
4015
+	 */
4016
+	public function get_current_screen()
4017
+	{
4018
+		return $this->_current_screen;
4019
+	}
4020
+
4021
+
4022
+
4023
+	/**
4024
+	 * get_current_page_view_url
4025
+	 *
4026
+	 * @return string This returns the url for the current_page_view.
4027
+	 */
4028
+	public function get_current_page_view_url()
4029
+	{
4030
+		return $this->_current_page_view_url;
4031
+	}
4032
+
4033
+
4034
+
4035
+	/**
4036
+	 * just returns the _req_data property
4037
+	 *
4038
+	 * @return array
4039
+	 */
4040
+	public function get_request_data()
4041
+	{
4042
+		return $this->_req_data;
4043
+	}
4044
+
4045
+
4046
+
4047
+	/**
4048
+	 * returns the _req_data protected property
4049
+	 *
4050
+	 * @return string
4051
+	 */
4052
+	public function get_req_action()
4053
+	{
4054
+		return $this->_req_action;
4055
+	}
4056
+
4057
+
4058
+
4059
+	/**
4060
+	 * @return bool  value of $_is_caf property
4061
+	 */
4062
+	public function is_caf()
4063
+	{
4064
+		return $this->_is_caf;
4065
+	}
4066
+
4067
+
4068
+
4069
+	/**
4070
+	 * @return mixed
4071
+	 */
4072
+	public function default_espresso_metaboxes()
4073
+	{
4074
+		return $this->_default_espresso_metaboxes;
4075
+	}
4076
+
4077
+
4078
+
4079
+	/**
4080
+	 * @return mixed
4081
+	 */
4082
+	public function admin_base_url()
4083
+	{
4084
+		return $this->_admin_base_url;
4085
+	}
4086 4086
 
4087 4087
 
4088 4088
 
4089
-    /**
4090
-     * @return mixed
4091
-     */
4092
-    public function wp_page_slug()
4093
-    {
4094
-        return $this->_wp_page_slug;
4095
-    }
4089
+	/**
4090
+	 * @return mixed
4091
+	 */
4092
+	public function wp_page_slug()
4093
+	{
4094
+		return $this->_wp_page_slug;
4095
+	}
4096 4096
 
4097 4097
 
4098
-
4099
-    /**
4100
-     * updates  espresso configuration settings
4101
-     *
4102
-     * @param string                   $tab
4103
-     * @param EE_Config_Base|EE_Config $config
4104
-     * @param string                   $file file where error occurred
4105
-     * @param string                   $func function  where error occurred
4106
-     * @param string                   $line line no where error occurred
4107
-     * @return boolean
4108
-     */
4109
-    protected function _update_espresso_configuration($tab, $config, $file = '', $func = '', $line = '')
4110
-    {
4111
-        //remove any options that are NOT going to be saved with the config settings.
4112
-        if (isset($config->core->ee_ueip_optin)) {
4113
-            $config->core->ee_ueip_has_notified = true;
4114
-            // TODO: remove the following two lines and make sure values are migrated from 3.1
4115
-            update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
4116
-            update_option('ee_ueip_has_notified', true);
4117
-        }
4118
-        // and save it (note we're also doing the network save here)
4119
-        $net_saved    = is_main_site() ? EE_Network_Config::instance()->update_config(false, false) : true;
4120
-        $config_saved = EE_Config::instance()->update_espresso_config(false, false);
4121
-        if ($config_saved && $net_saved) {
4122
-            EE_Error::add_success(sprintf(__('"%s" have been successfully updated.', 'event_espresso'), $tab));
4123
-            return true;
4124
-        }
4125
-        EE_Error::add_error(sprintf(__('The "%s" were not updated.', 'event_espresso'), $tab), $file, $func, $line);
4126
-        return false;
4127
-    }
4128
-
4129
-
4130
-
4131
-    /**
4132
-     * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
4133
-     *
4134
-     * @return array
4135
-     */
4136
-    public function get_yes_no_values()
4137
-    {
4138
-        return $this->_yes_no_values;
4139
-    }
4140
-
4141
-
4142
-
4143
-    protected function _get_dir()
4144
-    {
4145
-        $reflector = new ReflectionClass(get_class($this));
4146
-        return dirname($reflector->getFileName());
4147
-    }
4148
-
4149
-
4150
-
4151
-    /**
4152
-     * A helper for getting a "next link".
4153
-     *
4154
-     * @param string $url   The url to link to
4155
-     * @param string $class The class to use.
4156
-     * @return string
4157
-     */
4158
-    protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
4159
-    {
4160
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4161
-    }
4162
-
4163
-
4164
-
4165
-    /**
4166
-     * A helper for getting a "previous link".
4167
-     *
4168
-     * @param string $url   The url to link to
4169
-     * @param string $class The class to use.
4170
-     * @return string
4171
-     */
4172
-    protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
4173
-    {
4174
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4175
-    }
4176
-
4177
-
4178
-
4179
-
4180
-
4181
-
4182
-
4183
-    //below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
4184
-
4185
-
4186
-    /**
4187
-     * This processes an request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller
4188
-     * knows that the _REG_ID isn't in the req_data array but CAN obtain it, the caller should ADD the _REG_ID to the
4189
-     * _req_data array.
4190
-     *
4191
-     * @return bool success/fail
4192
-     * @throws EE_Error
4193
-     * @throws InvalidArgumentException
4194
-     * @throws ReflectionException
4195
-     * @throws InvalidDataTypeException
4196
-     * @throws InvalidInterfaceException
4197
-     */
4198
-    protected function _process_resend_registration()
4199
-    {
4200
-        $this->_template_args['success'] = EED_Messages::process_resend($this->_req_data);
4201
-        do_action(
4202
-            'AHEE__EE_Admin_Page___process_resend_registration',
4203
-            $this->_template_args['success'],
4204
-            $this->_req_data
4205
-        );
4206
-        return $this->_template_args['success'];
4207
-    }
4208
-
4209
-
4210
-
4211
-    /**
4212
-     * This automatically processes any payment message notifications when manual payment has been applied.
4213
-     *
4214
-     * @param \EE_Payment $payment
4215
-     * @return bool success/fail
4216
-     */
4217
-    protected function _process_payment_notification(EE_Payment $payment)
4218
-    {
4219
-        add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
4220
-        do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
4221
-        $this->_template_args['success'] = apply_filters(
4222
-            'FHEE__EE_Admin_Page___process_admin_payment_notification__success',
4223
-            false,
4224
-            $payment
4225
-        );
4226
-        return $this->_template_args['success'];
4227
-    }
4098
+
4099
+	/**
4100
+	 * updates  espresso configuration settings
4101
+	 *
4102
+	 * @param string                   $tab
4103
+	 * @param EE_Config_Base|EE_Config $config
4104
+	 * @param string                   $file file where error occurred
4105
+	 * @param string                   $func function  where error occurred
4106
+	 * @param string                   $line line no where error occurred
4107
+	 * @return boolean
4108
+	 */
4109
+	protected function _update_espresso_configuration($tab, $config, $file = '', $func = '', $line = '')
4110
+	{
4111
+		//remove any options that are NOT going to be saved with the config settings.
4112
+		if (isset($config->core->ee_ueip_optin)) {
4113
+			$config->core->ee_ueip_has_notified = true;
4114
+			// TODO: remove the following two lines and make sure values are migrated from 3.1
4115
+			update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
4116
+			update_option('ee_ueip_has_notified', true);
4117
+		}
4118
+		// and save it (note we're also doing the network save here)
4119
+		$net_saved    = is_main_site() ? EE_Network_Config::instance()->update_config(false, false) : true;
4120
+		$config_saved = EE_Config::instance()->update_espresso_config(false, false);
4121
+		if ($config_saved && $net_saved) {
4122
+			EE_Error::add_success(sprintf(__('"%s" have been successfully updated.', 'event_espresso'), $tab));
4123
+			return true;
4124
+		}
4125
+		EE_Error::add_error(sprintf(__('The "%s" were not updated.', 'event_espresso'), $tab), $file, $func, $line);
4126
+		return false;
4127
+	}
4128
+
4129
+
4130
+
4131
+	/**
4132
+	 * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
4133
+	 *
4134
+	 * @return array
4135
+	 */
4136
+	public function get_yes_no_values()
4137
+	{
4138
+		return $this->_yes_no_values;
4139
+	}
4140
+
4141
+
4142
+
4143
+	protected function _get_dir()
4144
+	{
4145
+		$reflector = new ReflectionClass(get_class($this));
4146
+		return dirname($reflector->getFileName());
4147
+	}
4148
+
4149
+
4150
+
4151
+	/**
4152
+	 * A helper for getting a "next link".
4153
+	 *
4154
+	 * @param string $url   The url to link to
4155
+	 * @param string $class The class to use.
4156
+	 * @return string
4157
+	 */
4158
+	protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
4159
+	{
4160
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
4161
+	}
4162
+
4163
+
4164
+
4165
+	/**
4166
+	 * A helper for getting a "previous link".
4167
+	 *
4168
+	 * @param string $url   The url to link to
4169
+	 * @param string $class The class to use.
4170
+	 * @return string
4171
+	 */
4172
+	protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
4173
+	{
4174
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
4175
+	}
4176
+
4177
+
4178
+
4179
+
4180
+
4181
+
4182
+
4183
+	//below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
4184
+
4185
+
4186
+	/**
4187
+	 * This processes an request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller
4188
+	 * knows that the _REG_ID isn't in the req_data array but CAN obtain it, the caller should ADD the _REG_ID to the
4189
+	 * _req_data array.
4190
+	 *
4191
+	 * @return bool success/fail
4192
+	 * @throws EE_Error
4193
+	 * @throws InvalidArgumentException
4194
+	 * @throws ReflectionException
4195
+	 * @throws InvalidDataTypeException
4196
+	 * @throws InvalidInterfaceException
4197
+	 */
4198
+	protected function _process_resend_registration()
4199
+	{
4200
+		$this->_template_args['success'] = EED_Messages::process_resend($this->_req_data);
4201
+		do_action(
4202
+			'AHEE__EE_Admin_Page___process_resend_registration',
4203
+			$this->_template_args['success'],
4204
+			$this->_req_data
4205
+		);
4206
+		return $this->_template_args['success'];
4207
+	}
4208
+
4209
+
4210
+
4211
+	/**
4212
+	 * This automatically processes any payment message notifications when manual payment has been applied.
4213
+	 *
4214
+	 * @param \EE_Payment $payment
4215
+	 * @return bool success/fail
4216
+	 */
4217
+	protected function _process_payment_notification(EE_Payment $payment)
4218
+	{
4219
+		add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
4220
+		do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
4221
+		$this->_template_args['success'] = apply_filters(
4222
+			'FHEE__EE_Admin_Page___process_admin_payment_notification__success',
4223
+			false,
4224
+			$payment
4225
+		);
4226
+		return $this->_template_args['success'];
4227
+	}
4228 4228
 
4229 4229
 
4230 4230
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Transaction.model.php 1 patch
Indentation   +405 added lines, -405 removed lines patch added patch discarded remove patch
@@ -5,7 +5,7 @@  discard block
 block discarded – undo
5 5
 use EventEspresso\core\services\loaders\LoaderFactory;
6 6
 
7 7
 if ( ! defined('EVENT_ESPRESSO_VERSION')) {
8
-    exit('No direct script access allowed');
8
+	exit('No direct script access allowed');
9 9
 }
10 10
 require_once(EE_MODELS . 'EEM_Base.model.php');
11 11
 
@@ -21,193 +21,193 @@  discard block
 block discarded – undo
21 21
 class EEM_Transaction extends EEM_Base
22 22
 {
23 23
 
24
-    // private instance of the Transaction object
25
-    protected static $_instance;
26
-
27
-    /**
28
-     * Status ID(STS_ID on esp_status table) to indicate the transaction is complete,
29
-     * but payment is pending. This is the state for transactions where payment is promised
30
-     * from an offline gateway.
31
-     */
32
-    //	const open_status_code = 'TPN';
33
-
34
-    /**
35
-     * Status ID(STS_ID on esp_status table) to indicate the transaction failed,
36
-     * either due to a technical reason (server or computer crash during registration),
37
-     *  or some other reason that prevent the collection of any useful contact information from any of the registrants
38
-     */
39
-    const failed_status_code = 'TFL';
40
-
41
-    /**
42
-     * Status ID(STS_ID on esp_status table) to indicate the transaction was abandoned,
43
-     * either due to a technical reason (server or computer crash during registration),
44
-     * or due to an abandoned cart after registrant chose not to complete the registration process
45
-     * HOWEVER...
46
-     * an abandoned TXN differs from a failed TXN in that it was able to capture contact information for at least one
47
-     * registrant
48
-     */
49
-    const abandoned_status_code = 'TAB';
50
-
51
-    /**
52
-     * Status ID(STS_ID on esp_status table) to indicate an incomplete transaction,
53
-     * meaning that monies are still owing: TXN_paid < TXN_total
54
-     */
55
-    const incomplete_status_code = 'TIN';
56
-
57
-    /**
58
-     * Status ID (STS_ID on esp_status table) to indicate a complete transaction.
59
-     * meaning that NO monies are owing: TXN_paid == TXN_total
60
-     */
61
-    const complete_status_code = 'TCM';
62
-
63
-    /**
64
-     *  Status ID(STS_ID on esp_status table) to indicate the transaction is overpaid.
65
-     *  This is the same as complete, but site admins actually owe clients the moneys!  TXN_paid > TXN_total
66
-     */
67
-    const overpaid_status_code = 'TOP';
68
-
69
-
70
-    /**
71
-     *    private constructor to prevent direct creation
72
-     *
73
-     * @Constructor
74
-     * @access protected
75
-     *
76
-     * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and any
77
-     *                         incoming timezone data that gets saved). Note this just sends the timezone info to the
78
-     *                         date time model field objects.  Default is NULL (and will be assumed using the set
79
-     *                         timezone in the 'timezone_string' wp option)
80
-     *
81
-     * @return EEM_Transaction
82
-     * @throws \EE_Error
83
-     */
84
-    protected function __construct($timezone)
85
-    {
86
-        $this->singular_item = __('Transaction', 'event_espresso');
87
-        $this->plural_item   = __('Transactions', 'event_espresso');
88
-
89
-        $this->_tables                 = array(
90
-            'TransactionTable' => new EE_Primary_Table('esp_transaction', 'TXN_ID')
91
-        );
92
-        $this->_fields                 = array(
93
-            'TransactionTable' => array(
94
-                'TXN_ID'           => new EE_Primary_Key_Int_Field('TXN_ID', __('Transaction ID', 'event_espresso')),
95
-                'TXN_timestamp'    => new EE_Datetime_Field('TXN_timestamp',
96
-                    __('date when transaction was created', 'event_espresso'), false, EE_Datetime_Field::now,
97
-                    $timezone),
98
-                'TXN_total'        => new EE_Money_Field('TXN_total',
99
-                    __('Total value of Transaction', 'event_espresso'), false, 0),
100
-                'TXN_paid'         => new EE_Money_Field('TXN_paid',
101
-                    __('Amount paid towards transaction to date', 'event_espresso'), false, 0),
102
-                'STS_ID'           => new EE_Foreign_Key_String_Field('STS_ID', __('Status ID', 'event_espresso'),
103
-                    false, EEM_Transaction::failed_status_code, 'Status'),
104
-                'TXN_session_data' => new EE_Serialized_Text_Field('TXN_session_data',
105
-                    __('Serialized session data', 'event_espresso'), true, ''),
106
-                'TXN_hash_salt'    => new EE_Plain_Text_Field('TXN_hash_salt',
107
-                    __('Transaction Hash Salt', 'event_espresso'), true, ''),
108
-                'PMD_ID'           => new EE_Foreign_Key_Int_Field('PMD_ID',
109
-                    __("Last Used Payment Method", 'event_espresso'), true, null, 'Payment_Method'),
110
-                'TXN_reg_steps'    => new EE_Serialized_Text_Field('TXN_reg_steps',
111
-                    __('Registration Steps', 'event_espresso'), false, array()),
112
-            )
113
-        );
114
-        $this->_model_relations        = array(
115
-            'Registration'   => new EE_Has_Many_Relation(),
116
-            'Payment'        => new EE_Has_Many_Relation(),
117
-            'Status'         => new EE_Belongs_To_Relation(),
118
-            'Line_Item'      => new EE_Has_Many_Relation(false),
119
-            //you can delete a transaction without needing to delete its line items
120
-            'Payment_Method' => new EE_Belongs_To_Relation(),
121
-            'Message'        => new EE_Has_Many_Relation()
122
-        );
123
-        $this->_model_chain_to_wp_user = 'Registration.Event';
124
-        parent::__construct($timezone);
125
-
126
-    }
127
-
128
-
129
-    /**
130
-     *    txn_status_array
131
-     * get list of transaction statuses
132
-     *
133
-     * @access public
134
-     * @return array
135
-     */
136
-    public static function txn_status_array()
137
-    {
138
-        return apply_filters(
139
-            'FHEE__EEM_Transaction__txn_status_array',
140
-            array(
141
-                EEM_Transaction::overpaid_status_code,
142
-                EEM_Transaction::complete_status_code,
143
-                EEM_Transaction::incomplete_status_code,
144
-                EEM_Transaction::abandoned_status_code,
145
-                EEM_Transaction::failed_status_code,
146
-            )
147
-        );
148
-    }
149
-
150
-    /**
151
-     *        get the revenue per day  for the Transaction Admin page Reports Tab
152
-     *
153
-     * @access        public
154
-     *
155
-     * @param string $period
156
-     *
157
-     * @return \stdClass[]
158
-     */
159
-    public function get_revenue_per_day_report($period = '-1 month')
160
-    {
161
-        $sql_date = $this->convert_datetime_for_query('TXN_timestamp', date('Y-m-d H:i:s', strtotime($period)),
162
-            'Y-m-d H:i:s', 'UTC');
163
-
164
-        $query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset($this->get_timezone(), 'TXN_timestamp');
165
-
166
-        return $this->_get_all_wpdb_results(
167
-            array(
168
-                array(
169
-                    'TXN_timestamp' => array('>=', $sql_date)
170
-                ),
171
-                'group_by' => 'txnDate',
172
-                'order_by' => array('TXN_timestamp' => 'ASC')
173
-            ),
174
-            OBJECT,
175
-            array(
176
-                'txnDate' => array('DATE(' . $query_interval . ')', '%s'),
177
-                'revenue' => array('SUM(TransactionTable.TXN_paid)', '%d')
178
-            )
179
-        );
180
-    }
181
-
182
-
183
-    /**
184
-     *        get the revenue per event  for the Transaction Admin page Reports Tab
185
-     *
186
-     * @access        public
187
-     *
188
-     * @param string $period
189
-     *
190
-     * @throws \EE_Error
191
-     * @return mixed
192
-     */
193
-    public function get_revenue_per_event_report($period = '-1 month')
194
-    {
195
-        global $wpdb;
196
-        $transaction_table          = $wpdb->prefix . 'esp_transaction';
197
-        $registration_table         = $wpdb->prefix . 'esp_registration';
198
-        $registration_payment_table = $wpdb->prefix . 'esp_registration_payment';
199
-        $event_table                = $wpdb->posts;
200
-        $payment_table              = $wpdb->prefix . 'esp_payment';
201
-        $sql_date                   = date('Y-m-d H:i:s', strtotime($period));
202
-        $approved_payment_status    = EEM_Payment::status_id_approved;
203
-        $extra_event_on_join        = '';
204
-        //exclude events not authored by user if permissions in effect
205
-        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_event_report')) {
206
-            $extra_event_on_join = ' AND Event.post_author = ' . get_current_user_id();
207
-        }
208
-
209
-        return $wpdb->get_results(
210
-            "SELECT
24
+	// private instance of the Transaction object
25
+	protected static $_instance;
26
+
27
+	/**
28
+	 * Status ID(STS_ID on esp_status table) to indicate the transaction is complete,
29
+	 * but payment is pending. This is the state for transactions where payment is promised
30
+	 * from an offline gateway.
31
+	 */
32
+	//	const open_status_code = 'TPN';
33
+
34
+	/**
35
+	 * Status ID(STS_ID on esp_status table) to indicate the transaction failed,
36
+	 * either due to a technical reason (server or computer crash during registration),
37
+	 *  or some other reason that prevent the collection of any useful contact information from any of the registrants
38
+	 */
39
+	const failed_status_code = 'TFL';
40
+
41
+	/**
42
+	 * Status ID(STS_ID on esp_status table) to indicate the transaction was abandoned,
43
+	 * either due to a technical reason (server or computer crash during registration),
44
+	 * or due to an abandoned cart after registrant chose not to complete the registration process
45
+	 * HOWEVER...
46
+	 * an abandoned TXN differs from a failed TXN in that it was able to capture contact information for at least one
47
+	 * registrant
48
+	 */
49
+	const abandoned_status_code = 'TAB';
50
+
51
+	/**
52
+	 * Status ID(STS_ID on esp_status table) to indicate an incomplete transaction,
53
+	 * meaning that monies are still owing: TXN_paid < TXN_total
54
+	 */
55
+	const incomplete_status_code = 'TIN';
56
+
57
+	/**
58
+	 * Status ID (STS_ID on esp_status table) to indicate a complete transaction.
59
+	 * meaning that NO monies are owing: TXN_paid == TXN_total
60
+	 */
61
+	const complete_status_code = 'TCM';
62
+
63
+	/**
64
+	 *  Status ID(STS_ID on esp_status table) to indicate the transaction is overpaid.
65
+	 *  This is the same as complete, but site admins actually owe clients the moneys!  TXN_paid > TXN_total
66
+	 */
67
+	const overpaid_status_code = 'TOP';
68
+
69
+
70
+	/**
71
+	 *    private constructor to prevent direct creation
72
+	 *
73
+	 * @Constructor
74
+	 * @access protected
75
+	 *
76
+	 * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and any
77
+	 *                         incoming timezone data that gets saved). Note this just sends the timezone info to the
78
+	 *                         date time model field objects.  Default is NULL (and will be assumed using the set
79
+	 *                         timezone in the 'timezone_string' wp option)
80
+	 *
81
+	 * @return EEM_Transaction
82
+	 * @throws \EE_Error
83
+	 */
84
+	protected function __construct($timezone)
85
+	{
86
+		$this->singular_item = __('Transaction', 'event_espresso');
87
+		$this->plural_item   = __('Transactions', 'event_espresso');
88
+
89
+		$this->_tables                 = array(
90
+			'TransactionTable' => new EE_Primary_Table('esp_transaction', 'TXN_ID')
91
+		);
92
+		$this->_fields                 = array(
93
+			'TransactionTable' => array(
94
+				'TXN_ID'           => new EE_Primary_Key_Int_Field('TXN_ID', __('Transaction ID', 'event_espresso')),
95
+				'TXN_timestamp'    => new EE_Datetime_Field('TXN_timestamp',
96
+					__('date when transaction was created', 'event_espresso'), false, EE_Datetime_Field::now,
97
+					$timezone),
98
+				'TXN_total'        => new EE_Money_Field('TXN_total',
99
+					__('Total value of Transaction', 'event_espresso'), false, 0),
100
+				'TXN_paid'         => new EE_Money_Field('TXN_paid',
101
+					__('Amount paid towards transaction to date', 'event_espresso'), false, 0),
102
+				'STS_ID'           => new EE_Foreign_Key_String_Field('STS_ID', __('Status ID', 'event_espresso'),
103
+					false, EEM_Transaction::failed_status_code, 'Status'),
104
+				'TXN_session_data' => new EE_Serialized_Text_Field('TXN_session_data',
105
+					__('Serialized session data', 'event_espresso'), true, ''),
106
+				'TXN_hash_salt'    => new EE_Plain_Text_Field('TXN_hash_salt',
107
+					__('Transaction Hash Salt', 'event_espresso'), true, ''),
108
+				'PMD_ID'           => new EE_Foreign_Key_Int_Field('PMD_ID',
109
+					__("Last Used Payment Method", 'event_espresso'), true, null, 'Payment_Method'),
110
+				'TXN_reg_steps'    => new EE_Serialized_Text_Field('TXN_reg_steps',
111
+					__('Registration Steps', 'event_espresso'), false, array()),
112
+			)
113
+		);
114
+		$this->_model_relations        = array(
115
+			'Registration'   => new EE_Has_Many_Relation(),
116
+			'Payment'        => new EE_Has_Many_Relation(),
117
+			'Status'         => new EE_Belongs_To_Relation(),
118
+			'Line_Item'      => new EE_Has_Many_Relation(false),
119
+			//you can delete a transaction without needing to delete its line items
120
+			'Payment_Method' => new EE_Belongs_To_Relation(),
121
+			'Message'        => new EE_Has_Many_Relation()
122
+		);
123
+		$this->_model_chain_to_wp_user = 'Registration.Event';
124
+		parent::__construct($timezone);
125
+
126
+	}
127
+
128
+
129
+	/**
130
+	 *    txn_status_array
131
+	 * get list of transaction statuses
132
+	 *
133
+	 * @access public
134
+	 * @return array
135
+	 */
136
+	public static function txn_status_array()
137
+	{
138
+		return apply_filters(
139
+			'FHEE__EEM_Transaction__txn_status_array',
140
+			array(
141
+				EEM_Transaction::overpaid_status_code,
142
+				EEM_Transaction::complete_status_code,
143
+				EEM_Transaction::incomplete_status_code,
144
+				EEM_Transaction::abandoned_status_code,
145
+				EEM_Transaction::failed_status_code,
146
+			)
147
+		);
148
+	}
149
+
150
+	/**
151
+	 *        get the revenue per day  for the Transaction Admin page Reports Tab
152
+	 *
153
+	 * @access        public
154
+	 *
155
+	 * @param string $period
156
+	 *
157
+	 * @return \stdClass[]
158
+	 */
159
+	public function get_revenue_per_day_report($period = '-1 month')
160
+	{
161
+		$sql_date = $this->convert_datetime_for_query('TXN_timestamp', date('Y-m-d H:i:s', strtotime($period)),
162
+			'Y-m-d H:i:s', 'UTC');
163
+
164
+		$query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset($this->get_timezone(), 'TXN_timestamp');
165
+
166
+		return $this->_get_all_wpdb_results(
167
+			array(
168
+				array(
169
+					'TXN_timestamp' => array('>=', $sql_date)
170
+				),
171
+				'group_by' => 'txnDate',
172
+				'order_by' => array('TXN_timestamp' => 'ASC')
173
+			),
174
+			OBJECT,
175
+			array(
176
+				'txnDate' => array('DATE(' . $query_interval . ')', '%s'),
177
+				'revenue' => array('SUM(TransactionTable.TXN_paid)', '%d')
178
+			)
179
+		);
180
+	}
181
+
182
+
183
+	/**
184
+	 *        get the revenue per event  for the Transaction Admin page Reports Tab
185
+	 *
186
+	 * @access        public
187
+	 *
188
+	 * @param string $period
189
+	 *
190
+	 * @throws \EE_Error
191
+	 * @return mixed
192
+	 */
193
+	public function get_revenue_per_event_report($period = '-1 month')
194
+	{
195
+		global $wpdb;
196
+		$transaction_table          = $wpdb->prefix . 'esp_transaction';
197
+		$registration_table         = $wpdb->prefix . 'esp_registration';
198
+		$registration_payment_table = $wpdb->prefix . 'esp_registration_payment';
199
+		$event_table                = $wpdb->posts;
200
+		$payment_table              = $wpdb->prefix . 'esp_payment';
201
+		$sql_date                   = date('Y-m-d H:i:s', strtotime($period));
202
+		$approved_payment_status    = EEM_Payment::status_id_approved;
203
+		$extra_event_on_join        = '';
204
+		//exclude events not authored by user if permissions in effect
205
+		if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_event_report')) {
206
+			$extra_event_on_join = ' AND Event.post_author = ' . get_current_user_id();
207
+		}
208
+
209
+		return $wpdb->get_results(
210
+			"SELECT
211 211
 			Transaction_Event.event_name AS event_name,
212 212
 			SUM(Transaction_Event.paid) AS revenue
213 213
 			FROM
@@ -235,227 +235,227 @@  discard block
 block discarded – undo
235 235
 					$extra_event_on_join
236 236
 				) AS Transaction_Event
237 237
 			GROUP BY event_name",
238
-            OBJECT
239
-        );
240
-    }
241
-
242
-
243
-    /**
244
-     * Gets the current transaction given the reg_url_link, or assumes the reg_url_link is in the
245
-     * $_REQUEST global variable. Either way, tries to find the current transaction (through
246
-     * the registration pointed to by reg_url_link), if not returns null
247
-     *
248
-     * @param string $reg_url_link
249
-     *
250
-     * @return EE_Transaction
251
-     */
252
-    public function get_transaction_from_reg_url_link($reg_url_link = '')
253
-    {
254
-        return $this->get_one(array(
255
-            array(
256
-                'Registration.REG_url_link' => ! empty($reg_url_link) ? $reg_url_link : EE_Registry::instance()->REQ->get('e_reg_url_link',
257
-                    '')
258
-            )
259
-        ));
260
-    }
261
-
262
-
263
-    /**
264
-     * Updates the provided EE_Transaction with all the applicable payments
265
-     * (or fetch the EE_Transaction from its ID)
266
-     *
267
-     * @deprecated
268
-     *
269
-     * @param EE_Transaction|int $transaction_obj_or_id
270
-     * @param boolean            $save_txn whether or not to save the transaction during this function call
271
-     *
272
-     * @return boolean
273
-     * @throws \EE_Error
274
-     */
275
-    public function update_based_on_payments($transaction_obj_or_id, $save_txn = true)
276
-    {
277
-        EE_Error::doing_it_wrong(
278
-            __CLASS__ . '::' . __FUNCTION__,
279
-            sprintf(__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
280
-                'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()'),
281
-            '4.6.0'
282
-        );
283
-        /** @type EE_Transaction_Processor $transaction_processor */
284
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
285
-
286
-        return $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment(
287
-            $this->ensure_is_obj($transaction_obj_or_id)
288
-        );
289
-    }
290
-
291
-    /**
292
-     * Deletes "junk" transactions that were probably added by bots. There might be TONS
293
-     * of these, so we are very careful to NOT select (which the models do even when deleting),
294
-     * and so we only use wpdb directly and only do minimal joins.
295
-     * Transactions are considered "junk" if they're failed for longer than a week.
296
-     * Also, there is an extra check for payments related to the transaction, because if a transaction has a payment on
297
-     * it, it's probably not junk (regardless of what status it has).
298
-     * The downside to this approach is that is addons are listening for object deletions
299
-     * on EEM_Base::delete() they won't be notified of this.  However, there is an action that plugins can hook into
300
-     * to catch these types of deletions.
301
-     *
302
-     * @global WPDB $wpdb
303
-     * @return mixed
304
-     */
305
-    public function delete_junk_transactions()
306
-    {
307
-        /** @type WPDB $wpdb */
308
-        global $wpdb;
309
-        $deleted             = false;
310
-        $time_to_leave_alone = apply_filters(
311
-            'FHEE__EEM_Transaction__delete_junk_transactions__time_to_leave_alone'
312
-            , WEEK_IN_SECONDS
313
-        );
314
-
315
-
316
-        /**
317
-         * This allows code to filter the query arguments used for retrieving the transaction IDs to delete.
318
-         * Useful for plugins that want to exclude transactions matching certain query parameters.
319
-         * The query parameters should be in the format accepted by the EEM_Base model queries.
320
-         */
321
-        $ids_query = apply_filters(
322
-            'FHEE__EEM_Transaction__delete_junk_transactions__initial_query_args',
323
-            array(
324
-                0 => array(
325
-                    'STS_ID'        => EEM_Transaction::failed_status_code,
326
-                    'Payment.PAY_ID' => array( 'IS NULL' ),
327
-                    'TXN_timestamp' => array('<', time() - $time_to_leave_alone)
328
-                )
329
-            ),
330
-            $time_to_leave_alone
331
-        );
332
-
333
-
334
-        /**
335
-         * This filter is for when code needs to filter the list of transaction ids that represent transactions
336
-         * about to be deleted based on some other criteria that isn't easily done via the query args filter.
337
-         */
338
-        $txn_ids = apply_filters(
339
-            'FHEE__EEM_Transaction__delete_junk_transactions__transaction_ids_to_delete',
340
-            EEM_Transaction::instance()->get_col($ids_query, 'TXN_ID'),
341
-            $time_to_leave_alone
342
-        );
343
-        //now that we have the ids to delete
344
-        if (! empty($txn_ids) && is_array($txn_ids)) {
345
-            // first, make sure these TXN's are removed the "ee_locked_transactions" array
346
-            EEM_Transaction::unset_locked_transactions($txn_ids);
347
-            // let's get deletin'...
348
-            // Why no wpdb->prepare?  Because the data is trusted.
349
-            // We got the ids from the original query to get them FROM
350
-            // the db (which is sanitized) so no need to prepare them again.
351
-            $query   = '
238
+			OBJECT
239
+		);
240
+	}
241
+
242
+
243
+	/**
244
+	 * Gets the current transaction given the reg_url_link, or assumes the reg_url_link is in the
245
+	 * $_REQUEST global variable. Either way, tries to find the current transaction (through
246
+	 * the registration pointed to by reg_url_link), if not returns null
247
+	 *
248
+	 * @param string $reg_url_link
249
+	 *
250
+	 * @return EE_Transaction
251
+	 */
252
+	public function get_transaction_from_reg_url_link($reg_url_link = '')
253
+	{
254
+		return $this->get_one(array(
255
+			array(
256
+				'Registration.REG_url_link' => ! empty($reg_url_link) ? $reg_url_link : EE_Registry::instance()->REQ->get('e_reg_url_link',
257
+					'')
258
+			)
259
+		));
260
+	}
261
+
262
+
263
+	/**
264
+	 * Updates the provided EE_Transaction with all the applicable payments
265
+	 * (or fetch the EE_Transaction from its ID)
266
+	 *
267
+	 * @deprecated
268
+	 *
269
+	 * @param EE_Transaction|int $transaction_obj_or_id
270
+	 * @param boolean            $save_txn whether or not to save the transaction during this function call
271
+	 *
272
+	 * @return boolean
273
+	 * @throws \EE_Error
274
+	 */
275
+	public function update_based_on_payments($transaction_obj_or_id, $save_txn = true)
276
+	{
277
+		EE_Error::doing_it_wrong(
278
+			__CLASS__ . '::' . __FUNCTION__,
279
+			sprintf(__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
280
+				'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()'),
281
+			'4.6.0'
282
+		);
283
+		/** @type EE_Transaction_Processor $transaction_processor */
284
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
285
+
286
+		return $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment(
287
+			$this->ensure_is_obj($transaction_obj_or_id)
288
+		);
289
+	}
290
+
291
+	/**
292
+	 * Deletes "junk" transactions that were probably added by bots. There might be TONS
293
+	 * of these, so we are very careful to NOT select (which the models do even when deleting),
294
+	 * and so we only use wpdb directly and only do minimal joins.
295
+	 * Transactions are considered "junk" if they're failed for longer than a week.
296
+	 * Also, there is an extra check for payments related to the transaction, because if a transaction has a payment on
297
+	 * it, it's probably not junk (regardless of what status it has).
298
+	 * The downside to this approach is that is addons are listening for object deletions
299
+	 * on EEM_Base::delete() they won't be notified of this.  However, there is an action that plugins can hook into
300
+	 * to catch these types of deletions.
301
+	 *
302
+	 * @global WPDB $wpdb
303
+	 * @return mixed
304
+	 */
305
+	public function delete_junk_transactions()
306
+	{
307
+		/** @type WPDB $wpdb */
308
+		global $wpdb;
309
+		$deleted             = false;
310
+		$time_to_leave_alone = apply_filters(
311
+			'FHEE__EEM_Transaction__delete_junk_transactions__time_to_leave_alone'
312
+			, WEEK_IN_SECONDS
313
+		);
314
+
315
+
316
+		/**
317
+		 * This allows code to filter the query arguments used for retrieving the transaction IDs to delete.
318
+		 * Useful for plugins that want to exclude transactions matching certain query parameters.
319
+		 * The query parameters should be in the format accepted by the EEM_Base model queries.
320
+		 */
321
+		$ids_query = apply_filters(
322
+			'FHEE__EEM_Transaction__delete_junk_transactions__initial_query_args',
323
+			array(
324
+				0 => array(
325
+					'STS_ID'        => EEM_Transaction::failed_status_code,
326
+					'Payment.PAY_ID' => array( 'IS NULL' ),
327
+					'TXN_timestamp' => array('<', time() - $time_to_leave_alone)
328
+				)
329
+			),
330
+			$time_to_leave_alone
331
+		);
332
+
333
+
334
+		/**
335
+		 * This filter is for when code needs to filter the list of transaction ids that represent transactions
336
+		 * about to be deleted based on some other criteria that isn't easily done via the query args filter.
337
+		 */
338
+		$txn_ids = apply_filters(
339
+			'FHEE__EEM_Transaction__delete_junk_transactions__transaction_ids_to_delete',
340
+			EEM_Transaction::instance()->get_col($ids_query, 'TXN_ID'),
341
+			$time_to_leave_alone
342
+		);
343
+		//now that we have the ids to delete
344
+		if (! empty($txn_ids) && is_array($txn_ids)) {
345
+			// first, make sure these TXN's are removed the "ee_locked_transactions" array
346
+			EEM_Transaction::unset_locked_transactions($txn_ids);
347
+			// let's get deletin'...
348
+			// Why no wpdb->prepare?  Because the data is trusted.
349
+			// We got the ids from the original query to get them FROM
350
+			// the db (which is sanitized) so no need to prepare them again.
351
+			$query   = '
352 352
 				DELETE
353 353
 				FROM ' . $this->table() . '
354 354
 				WHERE
355 355
 					TXN_ID IN ( ' . implode(",", $txn_ids) . ')';
356
-            $deleted = $wpdb->query($query);
357
-        }
358
-        if ($deleted) {
359
-            /**
360
-             * Allows code to do something after the transactions have been deleted.
361
-             */
362
-            do_action('AHEE__EEM_Transaction__delete_junk_transactions__successful_deletion', $txn_ids);
363
-        }
364
-
365
-        return $deleted;
366
-    }
367
-
368
-
369
-    /**
370
-     * @param array $transaction_IDs
371
-     *
372
-     * @return bool
373
-     */
374
-    public static function unset_locked_transactions(array $transaction_IDs)
375
-    {
376
-        $locked_transactions = get_option('ee_locked_transactions', array());
377
-        $update              = false;
378
-        foreach ($transaction_IDs as $TXN_ID) {
379
-            if (isset($locked_transactions[$TXN_ID])) {
380
-                unset($locked_transactions[$TXN_ID]);
381
-                $update = true;
382
-            }
383
-        }
384
-        if ($update) {
385
-            update_option('ee_locked_transactions', $locked_transactions);
386
-        }
387
-
388
-        return $update;
389
-    }
390
-
391
-
392
-
393
-    /**
394
-     * returns an array of EE_Transaction objects whose timestamp is greater than
395
-     * the current time minus the session lifespan, which defaults to 60 minutes
396
-     *
397
-     * @return EE_Base_Class[]|EE_Transaction[]
398
-     * @throws EE_Error
399
-     * @throws InvalidArgumentException
400
-     * @throws InvalidDataTypeException
401
-     * @throws InvalidInterfaceException
402
-     */
403
-    public function get_transactions_in_progress()
404
-    {
405
-        return $this->_get_transactions_in_progress();
406
-    }
407
-
408
-
409
-
410
-    /**
411
-     * returns an array of EE_Transaction objects whose timestamp is less than
412
-     * the current time minus the session lifespan, which defaults to 60 minutes
413
-     *
414
-     * @return EE_Base_Class[]|EE_Transaction[]
415
-     * @throws EE_Error
416
-     * @throws InvalidArgumentException
417
-     * @throws InvalidDataTypeException
418
-     * @throws InvalidInterfaceException
419
-     */
420
-    public function get_transactions_not_in_progress()
421
-    {
422
-        return $this->_get_transactions_in_progress('<=');
423
-    }
424
-
425
-
426
-
427
-    /**
428
-     * @param string $comparison
429
-     * @return EE_Base_Class[]|EE_Transaction[]
430
-     * @throws EE_Error
431
-     * @throws InvalidArgumentException
432
-     * @throws InvalidDataTypeException
433
-     * @throws InvalidInterfaceException
434
-     */
435
-    private function _get_transactions_in_progress($comparison = '>=')
436
-    {
437
-        $comparison = $comparison === '>=' || $comparison === '<='
438
-            ? $comparison
439
-            : '>=';
440
-        /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
441
-        $session_lifespan = LoaderFactory::getLoader()->getShared(
442
-            'EventEspresso\core\domain\values\session\SessionLifespan'
443
-        );
444
-        return $this->get_all(
445
-            array(
446
-                array(
447
-                    'TXN_timestamp' => array(
448
-                        $comparison,
449
-                        $session_lifespan->expiration()
450
-                    ),
451
-                    'STS_ID' => array(
452
-                        '!=',
453
-                        EEM_Transaction::complete_status_code
454
-                    ),
455
-                )
456
-            )
457
-        );
458
-    }
356
+			$deleted = $wpdb->query($query);
357
+		}
358
+		if ($deleted) {
359
+			/**
360
+			 * Allows code to do something after the transactions have been deleted.
361
+			 */
362
+			do_action('AHEE__EEM_Transaction__delete_junk_transactions__successful_deletion', $txn_ids);
363
+		}
364
+
365
+		return $deleted;
366
+	}
367
+
368
+
369
+	/**
370
+	 * @param array $transaction_IDs
371
+	 *
372
+	 * @return bool
373
+	 */
374
+	public static function unset_locked_transactions(array $transaction_IDs)
375
+	{
376
+		$locked_transactions = get_option('ee_locked_transactions', array());
377
+		$update              = false;
378
+		foreach ($transaction_IDs as $TXN_ID) {
379
+			if (isset($locked_transactions[$TXN_ID])) {
380
+				unset($locked_transactions[$TXN_ID]);
381
+				$update = true;
382
+			}
383
+		}
384
+		if ($update) {
385
+			update_option('ee_locked_transactions', $locked_transactions);
386
+		}
387
+
388
+		return $update;
389
+	}
390
+
391
+
392
+
393
+	/**
394
+	 * returns an array of EE_Transaction objects whose timestamp is greater than
395
+	 * the current time minus the session lifespan, which defaults to 60 minutes
396
+	 *
397
+	 * @return EE_Base_Class[]|EE_Transaction[]
398
+	 * @throws EE_Error
399
+	 * @throws InvalidArgumentException
400
+	 * @throws InvalidDataTypeException
401
+	 * @throws InvalidInterfaceException
402
+	 */
403
+	public function get_transactions_in_progress()
404
+	{
405
+		return $this->_get_transactions_in_progress();
406
+	}
407
+
408
+
409
+
410
+	/**
411
+	 * returns an array of EE_Transaction objects whose timestamp is less than
412
+	 * the current time minus the session lifespan, which defaults to 60 minutes
413
+	 *
414
+	 * @return EE_Base_Class[]|EE_Transaction[]
415
+	 * @throws EE_Error
416
+	 * @throws InvalidArgumentException
417
+	 * @throws InvalidDataTypeException
418
+	 * @throws InvalidInterfaceException
419
+	 */
420
+	public function get_transactions_not_in_progress()
421
+	{
422
+		return $this->_get_transactions_in_progress('<=');
423
+	}
424
+
425
+
426
+
427
+	/**
428
+	 * @param string $comparison
429
+	 * @return EE_Base_Class[]|EE_Transaction[]
430
+	 * @throws EE_Error
431
+	 * @throws InvalidArgumentException
432
+	 * @throws InvalidDataTypeException
433
+	 * @throws InvalidInterfaceException
434
+	 */
435
+	private function _get_transactions_in_progress($comparison = '>=')
436
+	{
437
+		$comparison = $comparison === '>=' || $comparison === '<='
438
+			? $comparison
439
+			: '>=';
440
+		/** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
441
+		$session_lifespan = LoaderFactory::getLoader()->getShared(
442
+			'EventEspresso\core\domain\values\session\SessionLifespan'
443
+		);
444
+		return $this->get_all(
445
+			array(
446
+				array(
447
+					'TXN_timestamp' => array(
448
+						$comparison,
449
+						$session_lifespan->expiration()
450
+					),
451
+					'STS_ID' => array(
452
+						'!=',
453
+						EEM_Transaction::complete_status_code
454
+					),
455
+				)
456
+			)
457
+		);
458
+	}
459 459
 
460 460
 
461 461
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Line_Item.model.php 3 patches
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -4,7 +4,7 @@  discard block
 block discarded – undo
4 4
 use EventEspresso\core\exceptions\InvalidInterfaceException;
5 5
 use EventEspresso\core\services\loaders\LoaderFactory;
6 6
 
7
-if (!defined('EVENT_ESPRESSO_VERSION')) exit('No direct script access allowed');
7
+if ( ! defined('EVENT_ESPRESSO_VERSION')) exit('No direct script access allowed');
8 8
 
9 9
 /**
10 10
  * Event Espresso
@@ -211,8 +211,8 @@  discard block
 block discarded – undo
211 211
         );
212 212
         $query = $wpdb->prepare(
213 213
             'DELETE li
214
-				FROM ' . $this->table() . ' li
215
-				LEFT JOIN ' . EEM_Transaction::instance()->table() . ' t ON li.TXN_ID = t.TXN_ID
214
+				FROM ' . $this->table().' li
215
+				LEFT JOIN ' . EEM_Transaction::instance()->table().' t ON li.TXN_ID = t.TXN_ID
216 216
 				WHERE t.TXN_ID IS NULL AND li.LIN_timestamp < %s',
217 217
             // use GMT time because that's what TXN_timestamps are in
218 218
             date('Y-m-d H:i:s', time() - $time_to_leave_alone)
@@ -253,7 +253,7 @@  discard block
 block discarded – undo
253 253
         $query_params = array(
254 254
             'OBJ_type' => $OBJ_type,
255 255
             // if incoming $OBJ_IDs is an array, then make sure it is formatted correctly for the query
256
-            'OBJ_ID' => is_array($OBJ_IDs) && !isset($OBJ_IDs['IN']) ? array('IN', $OBJ_IDs) : $OBJ_IDs
256
+            'OBJ_ID' => is_array($OBJ_IDs) && ! isset($OBJ_IDs['IN']) ? array('IN', $OBJ_IDs) : $OBJ_IDs
257 257
         );
258 258
         if ($TXN_ID) {
259 259
             $query_params['TXN_ID'] = $TXN_ID;
Please login to merge, or discard this patch.
Braces   +3 added lines, -1 removed lines patch added patch discarded remove patch
@@ -4,7 +4,9 @@
 block discarded – undo
4 4
 use EventEspresso\core\exceptions\InvalidInterfaceException;
5 5
 use EventEspresso\core\services\loaders\LoaderFactory;
6 6
 
7
-if (!defined('EVENT_ESPRESSO_VERSION')) exit('No direct script access allowed');
7
+if (!defined('EVENT_ESPRESSO_VERSION')) {
8
+	exit('No direct script access allowed');
9
+}
8 10
 
9 11
 /**
10 12
  * Event Espresso
Please login to merge, or discard this patch.
Indentation   +395 added lines, -395 removed lines patch added patch discarded remove patch
@@ -47,404 +47,404 @@
 block discarded – undo
47 47
 class EEM_Line_Item extends EEM_Base
48 48
 {
49 49
 
50
-    /**
51
-     * Tax sub-total is just the total of all the taxes, which should be children
52
-     * of this line item. There should only ever be one tax sub-total, and it should
53
-     * be a direct child of. Its quantity and LIN_unit_price = 1.
54
-     */
55
-    const type_tax_sub_total = 'tax-sub-total';
56
-
57
-    /**
58
-     * Tax line items indicate a tax applied to all the taxable line items.
59
-     * Should not have any children line items. Its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal
60
-     * (eg 10% tax = 10, not 0.1). Its LIN_total = LIN_unit_price * pre-tax-total. Quantity = 1.
61
-     */
62
-    const type_tax = 'tax';
63
-
64
-    /**
65
-     * Indicating individual items purchased, or discounts or surcharges.
66
-     * The sum of all the regular line items  plus the tax items should equal
67
-     * the grand total.
68
-     * Possible children are sub-line-items and cancellations.
69
-     * For flat items, LIN_unit_price * LIN_quantity = LIN_total. Its LIN_total is the sum of all the children
70
-     * LIN_totals. Its LIN_percent = 0.
71
-     * For percent items, its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal (eg 10% = 10, not 0.1).
72
-     * Its LIN_total is LIN_percent / 100 * sum of lower-priority sibling line items. Quantity = 1.
73
-     */
74
-    const type_line_item = 'line-item';
75
-
76
-    /**
77
-     * Line item indicating all the factors that make a single line item.
78
-     * Sub-line items should have NO children line items.
79
-     * For flat sub-items, their quantity should match their parent item, their LIN_unit_price should be this sub-item's
80
-     * contribution towards the price of ONE of their parent items, and its LIN_total should be
81
-     *  = LIN_quantity * LIN_unit_price. Its LIN_percent = 0.
82
-     * For percent sub-items, the quantity should be 1, LIN_unit_price should be 0, and its LIN_total should
83
-     * = LIN_percent / 100 * sum of lower-priority sibling line items..
84
-     */
85
-    const type_sub_line_item = 'sub-item';
86
-
87
-    /**
88
-     * Line item indicating a sub-total (eg total for an event, or pre-tax subtotal).
89
-     * Direct children should be event subtotals.
90
-     * Should have quantity of 1, and a LIN_total and LIN_unit_price of the sum of all its sub-items' LIN_totals.
91
-     *
92
-     */
93
-    const type_sub_total = 'sub-total';
94
-
95
-    /**
96
-     * Line item for the grand total of an order. Its direct children
97
-     * should be tax subtotals and (pre-tax) subtotals, and possibly a regular line item
98
-     * indicating a transaction-wide discount/surcharge. Should have a quantity of 1, a LIN_total and LIN_unit_price of
99
-     * the entire order's mount.
100
-     */
101
-    const type_total = 'total';
102
-
103
-    /**
104
-     * When a line item is cancelled, a sub-line-item of type 'cancellation'
105
-     * should be created, indicating the quantity that were cancelled
106
-     * (because a line item could have a quantity of 1, and its cancellation item
107
-     * could be for 3, indicating that originally 4 were purchased, but 3 have been
108
-     * cancelled, and only one remains).
109
-     * When items are refunded, a cancellation line item should be made, which points
110
-     * to teh payment model object which actually refunded the payment.
111
-     * Cancellations should NOT have any children line items; the should NOT affect
112
-     * any calculations, and are only meant as a record that cancellations have occurred.
113
-     * Their LIN_percent should be 0.
114
-     */
115
-    const type_cancellation = 'cancellation';
116
-
117
-    // private instance of the EEM_Line_Item object
118
-    protected static $_instance = NULL;
119
-
120
-
121
-    /**
122
-     *        private constructor to prevent direct creation
123
-     * @Constructor
124
-     * @access protected
125
-     * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and any incoming timezone data that gets saved).  Note this just sends the timezone info to the date time model field objects.  Default is NULL (and will be assumed using the set timezone in the 'timezone_string' wp option)
126
-     * @return \EEM_Line_Item
127
-     */
128
-    protected function __construct($timezone)
129
-    {
130
-        $this->singular_item = __('Line Item', 'event_espresso');
131
-        $this->plural_item = __('Line Items', 'event_espresso');
132
-
133
-        $this->_tables = array(
134
-            'Line_Item' => new EE_Primary_Table('esp_line_item', 'LIN_ID')
135
-        );
136
-        $line_items_can_be_for = apply_filters('FHEE__EEM_Line_Item__line_items_can_be_for', array('Ticket', 'Price', 'Event'));
137
-        $this->_fields = array(
138
-            'Line_Item' => array(
139
-                'LIN_ID' => new EE_Primary_Key_Int_Field('LIN_ID', __("ID", "event_espresso")),
140
-                'LIN_code' => new EE_Slug_Field('LIN_code', __("Code for index into Cart", "event_espresso"), TRUE),
141
-                'TXN_ID' => new EE_Foreign_Key_Int_Field('TXN_ID', __("Transaction ID", "event_espresso"), TRUE, NULL, 'Transaction'),
142
-                'LIN_name' => new EE_Full_HTML_Field('LIN_name', __("Line Item Name", "event_espresso"), FALSE, ''),
143
-                'LIN_desc' => new EE_Full_HTML_Field('LIN_desc', __("Line Item Description", "event_espresso"), TRUE),
144
-                'LIN_unit_price' => new EE_Money_Field('LIN_unit_price', __("Unit Price", "event_espresso"), FALSE, 0),
145
-                'LIN_percent' => new EE_Float_Field('LIN_percent', __("Percent", "event_espresso"), FALSE, 0),
146
-                'LIN_is_taxable' => new EE_Boolean_Field('LIN_is_taxable', __("Taxable", "event_espresso"), FALSE, FALSE),
147
-                'LIN_order' => new EE_Integer_Field('LIN_order', __("Order of Application towards total of parent", "event_espresso"), FALSE, 1),
148
-                'LIN_total' => new EE_Money_Field('LIN_total', __("Total (unit price x quantity)", "event_espresso"), FALSE, 0),
149
-                'LIN_quantity' => new EE_Integer_Field('LIN_quantity', __("Quantity", "event_espresso"), TRUE, 1),
150
-                'LIN_parent' => new EE_Integer_Field('LIN_parent', __("Parent ID (this item goes towards that Line Item's total)", "event_espresso"), TRUE, NULL),
151
-                'LIN_type' => new EE_Enum_Text_Field('LIN_type', __("Type", "event_espresso"), FALSE, 'line-item', array(
152
-                        self::type_line_item => __("Line Item", "event_espresso"),
153
-                        self::type_sub_line_item => __("Sub-Item", "event_espresso"),
154
-                        self::type_sub_total => __("Subtotal", "event_espresso"),
155
-                        self::type_tax_sub_total => __("Tax Subtotal", "event_espresso"),
156
-                        self::type_tax => __("Tax", "event_espresso"),
157
-                        self::type_total => __("Total", "event_espresso"),
158
-                        self::type_cancellation => __('Cancellation', 'event_espresso')
159
-                    )
160
-                ),
161
-                'OBJ_ID' => new EE_Foreign_Key_Int_Field('OBJ_ID', __('ID of Item purchased.', 'event_espresso'), TRUE, NULL, $line_items_can_be_for),
162
-                'OBJ_type' => new EE_Any_Foreign_Model_Name_Field('OBJ_type', __("Model Name this Line Item is for", "event_espresso"), TRUE, NULL, $line_items_can_be_for),
163
-                'LIN_timestamp' => new EE_Datetime_Field('LIN_timestamp', __('When the line item was created', 'event_espresso'), false, EE_Datetime_Field::now, $timezone),
164
-            )
165
-        );
166
-        $this->_model_relations = array(
167
-            'Transaction' => new EE_Belongs_To_Relation(),
168
-            'Ticket' => new EE_Belongs_To_Any_Relation(),
169
-            'Price' => new EE_Belongs_To_Any_Relation(),
170
-            'Event' => new EE_Belongs_To_Any_Relation()
171
-        );
172
-        $this->_model_chain_to_wp_user = 'Transaction.Registration.Event';
173
-        $this->_caps_slug = 'transactions';
174
-        parent::__construct($timezone);
175
-    }
176
-
177
-
178
-    /**
179
-     * Gets all the line items for this transaction of the given type
180
-     * @param string $line_item_type like one of EEM_Line_Item::type_*
181
-     * @param EE_Transaction|int $transaction
182
-     * @return EE_Line_Item[]
183
-     */
184
-    public function get_all_of_type_for_transaction($line_item_type, $transaction)
185
-    {
186
-        $transaction = EEM_Transaction::instance()->ensure_is_ID($transaction);
187
-        return $this->get_all(array(array(
188
-            'LIN_type' => $line_item_type,
189
-            'TXN_ID' => $transaction
190
-        )));
191
-    }
192
-
193
-
194
-    /**
195
-     * Gets all line items unrelated to tickets that are normal line items
196
-     * (eg shipping, promotions, and miscellaneous other stuff should probably fit in this category)
197
-     * @param EE_Transaction|int $transaction
198
-     * @return EE_Line_Item[]
199
-     */
200
-    public function get_all_non_ticket_line_items_for_transaction($transaction)
201
-    {
202
-        $transaction = EEM_Transaction::instance()->ensure_is_ID($transaction);
203
-        return $this->get_all(array(array(
204
-            'LIN_type' => self::type_line_item,
205
-            'TXN_ID' => $transaction,
206
-            'OR' => array(
207
-                'OBJ_type*notticket' => array('!=', 'Ticket'),
208
-                'OBJ_type*null' => array('IS_NULL'))
209
-        )));
210
-    }
211
-
212
-    /**
213
-     * Deletes line items with no transaction who have passed the transaction cutoff time.
214
-     * This needs to be very efficient
215
-     * because if there are spam bots afoot there will be LOTS of line items
216
-     * @return int count of how many deleted
217
-     */
218
-    public function delete_line_items_with_no_transaction()
219
-    {
220
-        /** @type WPDB $wpdb */
221
-        global $wpdb;
222
-        $time_to_leave_alone = apply_filters(
223
-            'FHEE__EEM_Line_Item__delete_line_items_with_no_transaction__time_to_leave_alone', WEEK_IN_SECONDS
224
-        );
225
-        $query = $wpdb->prepare(
226
-            'DELETE li
50
+	/**
51
+	 * Tax sub-total is just the total of all the taxes, which should be children
52
+	 * of this line item. There should only ever be one tax sub-total, and it should
53
+	 * be a direct child of. Its quantity and LIN_unit_price = 1.
54
+	 */
55
+	const type_tax_sub_total = 'tax-sub-total';
56
+
57
+	/**
58
+	 * Tax line items indicate a tax applied to all the taxable line items.
59
+	 * Should not have any children line items. Its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal
60
+	 * (eg 10% tax = 10, not 0.1). Its LIN_total = LIN_unit_price * pre-tax-total. Quantity = 1.
61
+	 */
62
+	const type_tax = 'tax';
63
+
64
+	/**
65
+	 * Indicating individual items purchased, or discounts or surcharges.
66
+	 * The sum of all the regular line items  plus the tax items should equal
67
+	 * the grand total.
68
+	 * Possible children are sub-line-items and cancellations.
69
+	 * For flat items, LIN_unit_price * LIN_quantity = LIN_total. Its LIN_total is the sum of all the children
70
+	 * LIN_totals. Its LIN_percent = 0.
71
+	 * For percent items, its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal (eg 10% = 10, not 0.1).
72
+	 * Its LIN_total is LIN_percent / 100 * sum of lower-priority sibling line items. Quantity = 1.
73
+	 */
74
+	const type_line_item = 'line-item';
75
+
76
+	/**
77
+	 * Line item indicating all the factors that make a single line item.
78
+	 * Sub-line items should have NO children line items.
79
+	 * For flat sub-items, their quantity should match their parent item, their LIN_unit_price should be this sub-item's
80
+	 * contribution towards the price of ONE of their parent items, and its LIN_total should be
81
+	 *  = LIN_quantity * LIN_unit_price. Its LIN_percent = 0.
82
+	 * For percent sub-items, the quantity should be 1, LIN_unit_price should be 0, and its LIN_total should
83
+	 * = LIN_percent / 100 * sum of lower-priority sibling line items..
84
+	 */
85
+	const type_sub_line_item = 'sub-item';
86
+
87
+	/**
88
+	 * Line item indicating a sub-total (eg total for an event, or pre-tax subtotal).
89
+	 * Direct children should be event subtotals.
90
+	 * Should have quantity of 1, and a LIN_total and LIN_unit_price of the sum of all its sub-items' LIN_totals.
91
+	 *
92
+	 */
93
+	const type_sub_total = 'sub-total';
94
+
95
+	/**
96
+	 * Line item for the grand total of an order. Its direct children
97
+	 * should be tax subtotals and (pre-tax) subtotals, and possibly a regular line item
98
+	 * indicating a transaction-wide discount/surcharge. Should have a quantity of 1, a LIN_total and LIN_unit_price of
99
+	 * the entire order's mount.
100
+	 */
101
+	const type_total = 'total';
102
+
103
+	/**
104
+	 * When a line item is cancelled, a sub-line-item of type 'cancellation'
105
+	 * should be created, indicating the quantity that were cancelled
106
+	 * (because a line item could have a quantity of 1, and its cancellation item
107
+	 * could be for 3, indicating that originally 4 were purchased, but 3 have been
108
+	 * cancelled, and only one remains).
109
+	 * When items are refunded, a cancellation line item should be made, which points
110
+	 * to teh payment model object which actually refunded the payment.
111
+	 * Cancellations should NOT have any children line items; the should NOT affect
112
+	 * any calculations, and are only meant as a record that cancellations have occurred.
113
+	 * Their LIN_percent should be 0.
114
+	 */
115
+	const type_cancellation = 'cancellation';
116
+
117
+	// private instance of the EEM_Line_Item object
118
+	protected static $_instance = NULL;
119
+
120
+
121
+	/**
122
+	 *        private constructor to prevent direct creation
123
+	 * @Constructor
124
+	 * @access protected
125
+	 * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and any incoming timezone data that gets saved).  Note this just sends the timezone info to the date time model field objects.  Default is NULL (and will be assumed using the set timezone in the 'timezone_string' wp option)
126
+	 * @return \EEM_Line_Item
127
+	 */
128
+	protected function __construct($timezone)
129
+	{
130
+		$this->singular_item = __('Line Item', 'event_espresso');
131
+		$this->plural_item = __('Line Items', 'event_espresso');
132
+
133
+		$this->_tables = array(
134
+			'Line_Item' => new EE_Primary_Table('esp_line_item', 'LIN_ID')
135
+		);
136
+		$line_items_can_be_for = apply_filters('FHEE__EEM_Line_Item__line_items_can_be_for', array('Ticket', 'Price', 'Event'));
137
+		$this->_fields = array(
138
+			'Line_Item' => array(
139
+				'LIN_ID' => new EE_Primary_Key_Int_Field('LIN_ID', __("ID", "event_espresso")),
140
+				'LIN_code' => new EE_Slug_Field('LIN_code', __("Code for index into Cart", "event_espresso"), TRUE),
141
+				'TXN_ID' => new EE_Foreign_Key_Int_Field('TXN_ID', __("Transaction ID", "event_espresso"), TRUE, NULL, 'Transaction'),
142
+				'LIN_name' => new EE_Full_HTML_Field('LIN_name', __("Line Item Name", "event_espresso"), FALSE, ''),
143
+				'LIN_desc' => new EE_Full_HTML_Field('LIN_desc', __("Line Item Description", "event_espresso"), TRUE),
144
+				'LIN_unit_price' => new EE_Money_Field('LIN_unit_price', __("Unit Price", "event_espresso"), FALSE, 0),
145
+				'LIN_percent' => new EE_Float_Field('LIN_percent', __("Percent", "event_espresso"), FALSE, 0),
146
+				'LIN_is_taxable' => new EE_Boolean_Field('LIN_is_taxable', __("Taxable", "event_espresso"), FALSE, FALSE),
147
+				'LIN_order' => new EE_Integer_Field('LIN_order', __("Order of Application towards total of parent", "event_espresso"), FALSE, 1),
148
+				'LIN_total' => new EE_Money_Field('LIN_total', __("Total (unit price x quantity)", "event_espresso"), FALSE, 0),
149
+				'LIN_quantity' => new EE_Integer_Field('LIN_quantity', __("Quantity", "event_espresso"), TRUE, 1),
150
+				'LIN_parent' => new EE_Integer_Field('LIN_parent', __("Parent ID (this item goes towards that Line Item's total)", "event_espresso"), TRUE, NULL),
151
+				'LIN_type' => new EE_Enum_Text_Field('LIN_type', __("Type", "event_espresso"), FALSE, 'line-item', array(
152
+						self::type_line_item => __("Line Item", "event_espresso"),
153
+						self::type_sub_line_item => __("Sub-Item", "event_espresso"),
154
+						self::type_sub_total => __("Subtotal", "event_espresso"),
155
+						self::type_tax_sub_total => __("Tax Subtotal", "event_espresso"),
156
+						self::type_tax => __("Tax", "event_espresso"),
157
+						self::type_total => __("Total", "event_espresso"),
158
+						self::type_cancellation => __('Cancellation', 'event_espresso')
159
+					)
160
+				),
161
+				'OBJ_ID' => new EE_Foreign_Key_Int_Field('OBJ_ID', __('ID of Item purchased.', 'event_espresso'), TRUE, NULL, $line_items_can_be_for),
162
+				'OBJ_type' => new EE_Any_Foreign_Model_Name_Field('OBJ_type', __("Model Name this Line Item is for", "event_espresso"), TRUE, NULL, $line_items_can_be_for),
163
+				'LIN_timestamp' => new EE_Datetime_Field('LIN_timestamp', __('When the line item was created', 'event_espresso'), false, EE_Datetime_Field::now, $timezone),
164
+			)
165
+		);
166
+		$this->_model_relations = array(
167
+			'Transaction' => new EE_Belongs_To_Relation(),
168
+			'Ticket' => new EE_Belongs_To_Any_Relation(),
169
+			'Price' => new EE_Belongs_To_Any_Relation(),
170
+			'Event' => new EE_Belongs_To_Any_Relation()
171
+		);
172
+		$this->_model_chain_to_wp_user = 'Transaction.Registration.Event';
173
+		$this->_caps_slug = 'transactions';
174
+		parent::__construct($timezone);
175
+	}
176
+
177
+
178
+	/**
179
+	 * Gets all the line items for this transaction of the given type
180
+	 * @param string $line_item_type like one of EEM_Line_Item::type_*
181
+	 * @param EE_Transaction|int $transaction
182
+	 * @return EE_Line_Item[]
183
+	 */
184
+	public function get_all_of_type_for_transaction($line_item_type, $transaction)
185
+	{
186
+		$transaction = EEM_Transaction::instance()->ensure_is_ID($transaction);
187
+		return $this->get_all(array(array(
188
+			'LIN_type' => $line_item_type,
189
+			'TXN_ID' => $transaction
190
+		)));
191
+	}
192
+
193
+
194
+	/**
195
+	 * Gets all line items unrelated to tickets that are normal line items
196
+	 * (eg shipping, promotions, and miscellaneous other stuff should probably fit in this category)
197
+	 * @param EE_Transaction|int $transaction
198
+	 * @return EE_Line_Item[]
199
+	 */
200
+	public function get_all_non_ticket_line_items_for_transaction($transaction)
201
+	{
202
+		$transaction = EEM_Transaction::instance()->ensure_is_ID($transaction);
203
+		return $this->get_all(array(array(
204
+			'LIN_type' => self::type_line_item,
205
+			'TXN_ID' => $transaction,
206
+			'OR' => array(
207
+				'OBJ_type*notticket' => array('!=', 'Ticket'),
208
+				'OBJ_type*null' => array('IS_NULL'))
209
+		)));
210
+	}
211
+
212
+	/**
213
+	 * Deletes line items with no transaction who have passed the transaction cutoff time.
214
+	 * This needs to be very efficient
215
+	 * because if there are spam bots afoot there will be LOTS of line items
216
+	 * @return int count of how many deleted
217
+	 */
218
+	public function delete_line_items_with_no_transaction()
219
+	{
220
+		/** @type WPDB $wpdb */
221
+		global $wpdb;
222
+		$time_to_leave_alone = apply_filters(
223
+			'FHEE__EEM_Line_Item__delete_line_items_with_no_transaction__time_to_leave_alone', WEEK_IN_SECONDS
224
+		);
225
+		$query = $wpdb->prepare(
226
+			'DELETE li
227 227
 				FROM ' . $this->table() . ' li
228 228
 				LEFT JOIN ' . EEM_Transaction::instance()->table() . ' t ON li.TXN_ID = t.TXN_ID
229 229
 				WHERE t.TXN_ID IS NULL AND li.LIN_timestamp < %s',
230
-            // use GMT time because that's what TXN_timestamps are in
231
-            date('Y-m-d H:i:s', time() - $time_to_leave_alone)
232
-        );
233
-        return $wpdb->query($query);
234
-    }
235
-
236
-
237
-    /**
238
-     * get_line_item_for_transaction_object
239
-     * Gets a transaction's line item record for a specific object such as a EE_Event or EE_Ticket
240
-     *
241
-     * @param int $TXN_ID
242
-     * @param \EE_Base_Class $object
243
-     * @return EE_Line_Item[]
244
-     */
245
-    public function get_line_item_for_transaction_object($TXN_ID, EE_Base_Class $object)
246
-    {
247
-        return $this->get_all(array(array(
248
-            'TXN_ID' => $TXN_ID,
249
-            'OBJ_type' => str_replace('EE_', '', get_class($object)),
250
-            'OBJ_ID' => $object->ID()
251
-        )));
252
-    }
253
-
254
-
255
-    /**
256
-     * get_object_line_items_for_transaction
257
-     * Gets all of the the object line items for a transaction, based on an object type plus an array of object IDs
258
-     *
259
-     * @param int $TXN_ID
260
-     * @param string $OBJ_type
261
-     * @param array $OBJ_IDs
262
-     * @return EE_Line_Item[]
263
-     */
264
-    public function get_object_line_items_for_transaction($TXN_ID, $OBJ_type = 'Event', $OBJ_IDs = array())
265
-    {
266
-        $query_params = array(
267
-            'OBJ_type' => $OBJ_type,
268
-            // if incoming $OBJ_IDs is an array, then make sure it is formatted correctly for the query
269
-            'OBJ_ID' => is_array($OBJ_IDs) && !isset($OBJ_IDs['IN']) ? array('IN', $OBJ_IDs) : $OBJ_IDs
270
-        );
271
-        if ($TXN_ID) {
272
-            $query_params['TXN_ID'] = $TXN_ID;
273
-        }
274
-        return $this->get_all(array($query_params));
275
-    }
276
-
277
-
278
-    /**
279
-     * get_all_ticket_line_items_for_transaction
280
-     *
281
-     * @param EE_Transaction $transaction
282
-     * @return EE_Line_Item[]
283
-     */
284
-    public function get_all_ticket_line_items_for_transaction(EE_Transaction $transaction)
285
-    {
286
-        return $this->get_all(array(
287
-            array(
288
-                'TXN_ID' => $transaction->ID(),
289
-                'OBJ_type' => 'Ticket',
290
-            )
291
-        ));
292
-    }
293
-
294
-
295
-    /**
296
-     * get_ticket_line_item_for_transaction
297
-     *
298
-     * @param int $TXN_ID
299
-     * @param int $TKT_ID
300
-     * @return \EE_Line_Item
301
-     */
302
-    public function get_ticket_line_item_for_transaction($TXN_ID, $TKT_ID)
303
-    {
304
-        return $this->get_one(array(
305
-            array(
306
-                'TXN_ID' => EEM_Transaction::instance()->ensure_is_ID($TXN_ID),
307
-                'OBJ_ID' => $TKT_ID,
308
-                'OBJ_type' => 'Ticket',
309
-            )
310
-        ));
311
-    }
312
-
313
-
314
-    /**
315
-     * get_existing_promotion_line_item
316
-     * searches the cart for existing line items for the specified promotion
317
-     *
318
-     * @since   1.0.0
319
-     *
320
-     * @param EE_Line_Item $parent_line_item
321
-     * @param EE_Promotion $promotion
322
-     * @return EE_Line_Item
323
-     */
324
-    public function get_existing_promotion_line_item(EE_Line_Item $parent_line_item, EE_Promotion $promotion)
325
-    {
326
-        return $this->get_one(array(
327
-            array(
328
-                'TXN_ID' => $parent_line_item->TXN_ID(),
329
-                'LIN_parent' => $parent_line_item->ID(),
330
-                'OBJ_type' => 'Promotion',
331
-                'OBJ_ID' => $promotion->ID()
332
-            )
333
-        ));
334
-    }
335
-
336
-
337
-    /**
338
-     * get_all_promotion_line_items
339
-     * searches the cart for any and all existing promotion line items
340
-     *
341
-     * @since   1.0.0
342
-     *
343
-     * @param EE_Line_Item $parent_line_item
344
-     * @return EE_Line_Item[]
345
-     */
346
-    public function get_all_promotion_line_items(EE_Line_Item $parent_line_item)
347
-    {
348
-        return $this->get_all(array(
349
-            array(
350
-                'TXN_ID' => $parent_line_item->TXN_ID(),
351
-                'LIN_parent' => $parent_line_item->ID(),
352
-                'OBJ_type' => 'Promotion'
353
-            )
354
-        ));
355
-    }
356
-
357
-    /**
358
-     * Gets the registration's corresponding line item.
359
-     * Note: basically does NOT support having multiple line items for a single ticket,
360
-     * which would happen if some of the registrations had a price modifier while others didn't.
361
-     * In order to support that, we'd probably need a LIN_ID on registrations or something.
362
-     * @param EE_Registration $registration
363
-     * @return EE_Line_ITem
364
-     */
365
-    public function get_line_item_for_registration(EE_Registration $registration)
366
-    {
367
-        return $this->get_one($this->line_item_for_registration_query_params($registration));
368
-    }
369
-
370
-    /**
371
-     * Gets the query params used to retrieve a specific line item for the given registration
372
-     * @param EE_Registration $registration
373
-     * @param array $original_query_params any extra query params you'd like to be merged with
374
-     * @return array like EEM_Base::get_all()'s $query_params
375
-     */
376
-    public function line_item_for_registration_query_params(EE_Registration $registration, $original_query_params = array())
377
-    {
378
-        return array_replace_recursive($original_query_params, array(
379
-            array(
380
-                'OBJ_ID' => $registration->ticket_ID(),
381
-                'OBJ_type' => 'Ticket',
382
-                'TXN_ID' => $registration->transaction_ID()
383
-            )
384
-        ));
385
-    }
386
-
387
-
388
-    /**
389
-     * @return EE_Base_Class[]|EE_Line_Item[]
390
-     * @throws EE_Error
391
-     */
392
-    public function get_total_line_items_with_no_transaction()
393
-    {
394
-        return $this->get_total_line_items_for_carts();
395
-    }
396
-
397
-
398
-    /**
399
-     * @return EE_Base_Class[]|EE_Line_Item[]
400
-     * @throws EE_Error
401
-     */
402
-    public function get_total_line_items_for_active_carts()
403
-    {
404
-        return $this->get_total_line_items_for_carts(false);
405
-    }
406
-
407
-
408
-    /**
409
-     * @return EE_Base_Class[]|EE_Line_Item[]
410
-     * @throws EE_Error
411
-     */
412
-    public function get_total_line_items_for_expired_carts()
413
-    {
414
-        return $this->get_total_line_items_for_carts(true);
415
-    }
416
-
417
-
418
-    /**
419
-     * Returns an array of grand total line items where the TXN_ID is 0.
420
-     * If $expired is set to true, then only line items for expired sessions will be returned.
421
-     * If $expired is set to false, then only line items for active sessions will be returned.
422
-     *
423
-     * @param bool|null $expired
424
-     * @return EE_Base_Class[]|EE_Line_Item[]
425
-     * @throws InvalidInterfaceException
426
-     * @throws InvalidDataTypeException
427
-     * @throws EE_Error
428
-     * @throws InvalidArgumentException
429
-     */
430
-    private function get_total_line_items_for_carts($expired = null)
431
-    {
432
-        $where_params = array(
433
-            'TXN_ID' => 0,
434
-            'LIN_type' => 'total',
435
-        );
436
-        if ($expired !== null) {
437
-            /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
438
-            $session_lifespan = LoaderFactory::getLoader()->getShared(
439
-                'EventEspresso\core\domain\values\session\SessionLifespan'
440
-            );
441
-            $where_params['LIN_timestamp'] = array(
442
-                $expired ? '<=' : '>',
443
-                $session_lifespan->expiration(),
444
-            );
445
-        }
446
-        return $this->get_all(array($where_params));
447
-    }
230
+			// use GMT time because that's what TXN_timestamps are in
231
+			date('Y-m-d H:i:s', time() - $time_to_leave_alone)
232
+		);
233
+		return $wpdb->query($query);
234
+	}
235
+
236
+
237
+	/**
238
+	 * get_line_item_for_transaction_object
239
+	 * Gets a transaction's line item record for a specific object such as a EE_Event or EE_Ticket
240
+	 *
241
+	 * @param int $TXN_ID
242
+	 * @param \EE_Base_Class $object
243
+	 * @return EE_Line_Item[]
244
+	 */
245
+	public function get_line_item_for_transaction_object($TXN_ID, EE_Base_Class $object)
246
+	{
247
+		return $this->get_all(array(array(
248
+			'TXN_ID' => $TXN_ID,
249
+			'OBJ_type' => str_replace('EE_', '', get_class($object)),
250
+			'OBJ_ID' => $object->ID()
251
+		)));
252
+	}
253
+
254
+
255
+	/**
256
+	 * get_object_line_items_for_transaction
257
+	 * Gets all of the the object line items for a transaction, based on an object type plus an array of object IDs
258
+	 *
259
+	 * @param int $TXN_ID
260
+	 * @param string $OBJ_type
261
+	 * @param array $OBJ_IDs
262
+	 * @return EE_Line_Item[]
263
+	 */
264
+	public function get_object_line_items_for_transaction($TXN_ID, $OBJ_type = 'Event', $OBJ_IDs = array())
265
+	{
266
+		$query_params = array(
267
+			'OBJ_type' => $OBJ_type,
268
+			// if incoming $OBJ_IDs is an array, then make sure it is formatted correctly for the query
269
+			'OBJ_ID' => is_array($OBJ_IDs) && !isset($OBJ_IDs['IN']) ? array('IN', $OBJ_IDs) : $OBJ_IDs
270
+		);
271
+		if ($TXN_ID) {
272
+			$query_params['TXN_ID'] = $TXN_ID;
273
+		}
274
+		return $this->get_all(array($query_params));
275
+	}
276
+
277
+
278
+	/**
279
+	 * get_all_ticket_line_items_for_transaction
280
+	 *
281
+	 * @param EE_Transaction $transaction
282
+	 * @return EE_Line_Item[]
283
+	 */
284
+	public function get_all_ticket_line_items_for_transaction(EE_Transaction $transaction)
285
+	{
286
+		return $this->get_all(array(
287
+			array(
288
+				'TXN_ID' => $transaction->ID(),
289
+				'OBJ_type' => 'Ticket',
290
+			)
291
+		));
292
+	}
293
+
294
+
295
+	/**
296
+	 * get_ticket_line_item_for_transaction
297
+	 *
298
+	 * @param int $TXN_ID
299
+	 * @param int $TKT_ID
300
+	 * @return \EE_Line_Item
301
+	 */
302
+	public function get_ticket_line_item_for_transaction($TXN_ID, $TKT_ID)
303
+	{
304
+		return $this->get_one(array(
305
+			array(
306
+				'TXN_ID' => EEM_Transaction::instance()->ensure_is_ID($TXN_ID),
307
+				'OBJ_ID' => $TKT_ID,
308
+				'OBJ_type' => 'Ticket',
309
+			)
310
+		));
311
+	}
312
+
313
+
314
+	/**
315
+	 * get_existing_promotion_line_item
316
+	 * searches the cart for existing line items for the specified promotion
317
+	 *
318
+	 * @since   1.0.0
319
+	 *
320
+	 * @param EE_Line_Item $parent_line_item
321
+	 * @param EE_Promotion $promotion
322
+	 * @return EE_Line_Item
323
+	 */
324
+	public function get_existing_promotion_line_item(EE_Line_Item $parent_line_item, EE_Promotion $promotion)
325
+	{
326
+		return $this->get_one(array(
327
+			array(
328
+				'TXN_ID' => $parent_line_item->TXN_ID(),
329
+				'LIN_parent' => $parent_line_item->ID(),
330
+				'OBJ_type' => 'Promotion',
331
+				'OBJ_ID' => $promotion->ID()
332
+			)
333
+		));
334
+	}
335
+
336
+
337
+	/**
338
+	 * get_all_promotion_line_items
339
+	 * searches the cart for any and all existing promotion line items
340
+	 *
341
+	 * @since   1.0.0
342
+	 *
343
+	 * @param EE_Line_Item $parent_line_item
344
+	 * @return EE_Line_Item[]
345
+	 */
346
+	public function get_all_promotion_line_items(EE_Line_Item $parent_line_item)
347
+	{
348
+		return $this->get_all(array(
349
+			array(
350
+				'TXN_ID' => $parent_line_item->TXN_ID(),
351
+				'LIN_parent' => $parent_line_item->ID(),
352
+				'OBJ_type' => 'Promotion'
353
+			)
354
+		));
355
+	}
356
+
357
+	/**
358
+	 * Gets the registration's corresponding line item.
359
+	 * Note: basically does NOT support having multiple line items for a single ticket,
360
+	 * which would happen if some of the registrations had a price modifier while others didn't.
361
+	 * In order to support that, we'd probably need a LIN_ID on registrations or something.
362
+	 * @param EE_Registration $registration
363
+	 * @return EE_Line_ITem
364
+	 */
365
+	public function get_line_item_for_registration(EE_Registration $registration)
366
+	{
367
+		return $this->get_one($this->line_item_for_registration_query_params($registration));
368
+	}
369
+
370
+	/**
371
+	 * Gets the query params used to retrieve a specific line item for the given registration
372
+	 * @param EE_Registration $registration
373
+	 * @param array $original_query_params any extra query params you'd like to be merged with
374
+	 * @return array like EEM_Base::get_all()'s $query_params
375
+	 */
376
+	public function line_item_for_registration_query_params(EE_Registration $registration, $original_query_params = array())
377
+	{
378
+		return array_replace_recursive($original_query_params, array(
379
+			array(
380
+				'OBJ_ID' => $registration->ticket_ID(),
381
+				'OBJ_type' => 'Ticket',
382
+				'TXN_ID' => $registration->transaction_ID()
383
+			)
384
+		));
385
+	}
386
+
387
+
388
+	/**
389
+	 * @return EE_Base_Class[]|EE_Line_Item[]
390
+	 * @throws EE_Error
391
+	 */
392
+	public function get_total_line_items_with_no_transaction()
393
+	{
394
+		return $this->get_total_line_items_for_carts();
395
+	}
396
+
397
+
398
+	/**
399
+	 * @return EE_Base_Class[]|EE_Line_Item[]
400
+	 * @throws EE_Error
401
+	 */
402
+	public function get_total_line_items_for_active_carts()
403
+	{
404
+		return $this->get_total_line_items_for_carts(false);
405
+	}
406
+
407
+
408
+	/**
409
+	 * @return EE_Base_Class[]|EE_Line_Item[]
410
+	 * @throws EE_Error
411
+	 */
412
+	public function get_total_line_items_for_expired_carts()
413
+	{
414
+		return $this->get_total_line_items_for_carts(true);
415
+	}
416
+
417
+
418
+	/**
419
+	 * Returns an array of grand total line items where the TXN_ID is 0.
420
+	 * If $expired is set to true, then only line items for expired sessions will be returned.
421
+	 * If $expired is set to false, then only line items for active sessions will be returned.
422
+	 *
423
+	 * @param bool|null $expired
424
+	 * @return EE_Base_Class[]|EE_Line_Item[]
425
+	 * @throws InvalidInterfaceException
426
+	 * @throws InvalidDataTypeException
427
+	 * @throws EE_Error
428
+	 * @throws InvalidArgumentException
429
+	 */
430
+	private function get_total_line_items_for_carts($expired = null)
431
+	{
432
+		$where_params = array(
433
+			'TXN_ID' => 0,
434
+			'LIN_type' => 'total',
435
+		);
436
+		if ($expired !== null) {
437
+			/** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
438
+			$session_lifespan = LoaderFactory::getLoader()->getShared(
439
+				'EventEspresso\core\domain\values\session\SessionLifespan'
440
+			);
441
+			$where_params['LIN_timestamp'] = array(
442
+				$expired ? '<=' : '>',
443
+				$session_lifespan->expiration(),
444
+			);
445
+		}
446
+		return $this->get_all(array($where_params));
447
+	}
448 448
 
449 449
 
450 450
 }
Please login to merge, or discard this patch.