Completed
Branch BUG-9623-config-log (c144cd)
by
unknown
110:09 queued 92:18
created

EEH_Activation::validate_messages_system()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 0
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
1
<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) {exit('No direct script access allowed');}
2
/**
3
 * EEH_Activation Helper
4
 *
5
 * @package		Event Espresso
6
 * @subpackage	/helpers/
7
 * @author		Brent Christensen
8
 */
9
class EEH_Activation {
10
11
	/**
12
	 * constant used to indicate a cron task is no longer in use
13
	 */
14
	const cron_task_no_longer_in_use = 'no_longer_in_use';
15
16
	/**
17
	 * option name that will indicate whether or not we still
18
	 * need to create EE's folders in the uploads directory
19
	 * (because if EE was installed without file system access,
20
	 * we need to request credentials before we can create them)
21
	 */
22
	const upload_directories_incomplete_option_name = 'ee_upload_directories_incomplete';
23
24
	/**
25
	 * WP_User->ID
26
	 *
27
	 * @var int
28
	 */
29
	private static $_default_creator_id;
30
31
	/**
32
	 * indicates whether or not we've already verified core's default data during this request,
33
	 * because after migrations are done, any addons activated while in maintenance mode
34
	 * will want to setup their own default data, and they might hook into core's default data
35
	 * and trigger core to setup its default data. In which case they might all ask for core to init its default data.
36
	 * This prevents doing that for EVERY single addon.
37
	 * @var boolean
38
	 */
39
	protected static $_initialized_db_content_already_in_this_request = false;
40
41
42
43
	/**
44
	 *    _ensure_table_name_has_prefix
45
	 *
46
	 * @access public
47
	 * @static
48
	 * @param $table_name
49
	 * @return string
50
	 */
51
	public static function ensure_table_name_has_prefix( $table_name ) {
52
		global $wpdb;
53
		return strpos( $table_name, $wpdb->base_prefix ) === 0 ? $table_name : $wpdb->prefix . $table_name;
54
	}
55
56
57
	/**
58
	 * 	system_initialization
59
	 * 	ensures the EE configuration settings are loaded with at least default options set
60
	 * 	and that all critical EE pages have been generated with the appropriate shortcodes in place
61
	 *
62
	 * 	@access public
63
	 * 	@static
64
	 * 	@return void
65
	 */
66
	public static function system_initialization() {
67
		EEH_Activation::reset_and_update_config();
68
		//which is fired BEFORE activation of plugin anyways
69
		EEH_Activation::verify_default_pages_exist();
70
	}
71
72
73
74
	/**
75
	 * Sets the database schema and creates folders. This should
76
	 * be called on plugin activation and reactivation
77
	 *
78
	 * @return boolean success, whether the database and folders are setup properly
79
	 * @throws \EE_Error
80
	 */
81
	public static function initialize_db_and_folders(){
82
		$good_filesystem = EEH_Activation::create_upload_directories();
83
		$good_db = EEH_Activation::create_database_tables();
84
		return $good_filesystem && $good_db;
85
	}
86
87
88
89
	/**
90
	 * assuming we have an up-to-date database schema, this will populate it
91
	 * with default and initial data. This should be called
92
	 * upon activation of a new plugin, reactivation, and at the end
93
	 * of running migration scripts
94
	 *
95
	 * @throws \EE_Error
96
	 */
97
	public static function initialize_db_content(){
98
		//let's avoid doing all this logic repeatedly, especially when addons are requesting it
99
		if( EEH_Activation::$_initialized_db_content_already_in_this_request ) {
100
			return;
101
		}
102
		EEH_Activation::$_initialized_db_content_already_in_this_request = true;
103
104
		EEH_Activation::initialize_system_questions();
105
		EEH_Activation::insert_default_status_codes();
106
		EEH_Activation::generate_default_message_templates();
107
		EEH_Activation::create_no_ticket_prices_array();
108
		EE_Registry::instance()->CAP->init_caps();
109
110
		EEH_Activation::validate_messages_system();
111
		EEH_Activation::insert_default_payment_methods();
112
		//in case we've
113
		EEH_Activation::remove_cron_tasks();
114
		EEH_Activation::create_cron_tasks();
115
		// remove all TXN locks since that is being done via extra meta now
116
		delete_option( 'ee_locked_transactions' );
117
		//also, check for CAF default db content
118
		do_action( 'AHEE__EEH_Activation__initialize_db_content' );
119
		//also: EEM_Gateways::load_all_gateways() outputs a lot of success messages
120
		//which users really won't care about on initial activation
121
		EE_Error::overwrite_success();
122
	}
123
124
125
126
127
	/**
128
	 * Returns an array of cron tasks. Array values are the actions fired by the cron tasks (the "hooks"),
129
	 * values are the frequency (the "recurrence"). See http://codex.wordpress.org/Function_Reference/wp_schedule_event
130
	 * If the cron task should NO longer be used, it should have a value of EEH_Activation::cron_task_no_longer_in_use
131
	 * (null)
132
	 *
133
	 * @param string $which_to_include can be 'current' (ones that are currently in use),
134
	 *                          'old' (only returns ones that should no longer be used),or 'all',
135
	 * @return array
136
	 * @throws \EE_Error
137
	 */
138
	public static function get_cron_tasks( $which_to_include ) {
139
		$cron_tasks = apply_filters(
140
			'FHEE__EEH_Activation__get_cron_tasks',
141
			array(
142
				'AHEE__EE_Cron_Tasks__clean_up_junk_transactions' => 'hourly',
143
//				'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions' => EEH_Activation::cron_task_no_longer_in_use, actually this is still in use
144
				'AHEE__EE_Cron_Tasks__update_transaction_with_payment' => EEH_Activation::cron_task_no_longer_in_use, //there may have been a bug which prevented from these cron tasks from getting unscheduled, so we might want to remove these for a few updates
145
			)
146
		);
147
		if ( $which_to_include === 'old' ) {
148
			$cron_tasks = array_filter(
149
				$cron_tasks,
150
				function ( $value ) {
151
					return $value === EEH_Activation::cron_task_no_longer_in_use;
152
				}
153
			);
154
		} elseif ( $which_to_include === 'current' ) {
155
			$cron_tasks = array_filter( $cron_tasks );
156
		} elseif ( WP_DEBUG && $which_to_include !== 'all' ) {
157
			throw new EE_Error(
158
				sprintf(
159
					__(
160
						'Invalid argument of "%1$s" passed to EEH_Activation::get_cron_tasks. Valid values are "all", "old" and "current".',
161
						'event_espresso'
162
					),
163
					$which_to_include
164
				)
165
			);
166
		}
167
		return $cron_tasks;
168
	}
169
170
171
172
	/**
173
	 * Ensure cron tasks are setup (the removal of crons should be done by remove_crons())
174
	 *
175
	 * @throws \EE_Error
176
	 */
177
	public static function create_cron_tasks() {
178
179
		foreach( EEH_Activation::get_cron_tasks( 'current' ) as $hook_name => $frequency ) {
180
			if( ! wp_next_scheduled( $hook_name ) ) {
181
				wp_schedule_event( time(), $frequency, $hook_name );
182
			}
183
		}
184
185
	}
186
187
188
189
	/**
190
	 * Remove the currently-existing and now-removed cron tasks.
191
	 *
192
	 * @param boolean $remove_all whether to only remove the old ones, or remove absolutely ALL the EE ones
193
	 * @throws \EE_Error
194
	 */
195
	public static function remove_cron_tasks( $remove_all = true ) {
196
		$cron_tasks_to_remove = $remove_all ? 'all' : 'old';
197
		$crons = _get_cron_array();
198
		$crons = is_array( $crons ) ? $crons : array();
199
		/* reminder of what $crons look like:
200
		 * Top-level keys are timestamps, and their values are arrays.
201
		 * The 2nd level arrays have keys with each of the cron task hook names to run at that time
202
		 * and their values are arrays.
203
		 * The 3rd level level arrays are keys which are hashes of the cron task's arguments,
204
		 *  and their values are the UN-hashed arguments
205
		 * eg
206
		 * array (size=13)
207
		 *		1429903276 =>
208
		 *		  array (size=1)
209
		 *			'AHEE__EE_Cron_Tasks__update_transaction_with_payment' =>
210
		 *			  array (size=1)
211
		 *				'561299d6e42c8e079285870ade0e47e6' =>
212
		 *				  array (size=2)
213
		 *					...
214
		 *      ...
215
		 */
216
		$ee_cron_tasks_to_remove = EEH_Activation::get_cron_tasks( $cron_tasks_to_remove );
217
		foreach ( $crons as $timestamp => $hooks_to_fire_at_time ) {
218
			if ( is_array( $hooks_to_fire_at_time ) ) {
219
				foreach ( $hooks_to_fire_at_time as $hook_name => $hook_actions ) {
220
					if ( isset( $ee_cron_tasks_to_remove[ $hook_name ] )
221
					     && is_array( $ee_cron_tasks_to_remove[ $hook_name ] )
222
					) {
223
						unset( $crons[ $timestamp ][ $hook_name ] );
224
					}
225
				}
226
				//also take care of any empty cron timestamps.
227
				if ( empty( $hooks_to_fire_at_time ) ) {
228
					unset( $crons[ $timestamp ] );
229
				}
230
			}
231
		}
232
		_set_cron_array( $crons );
233
	}
234
235
236
237
	/**
238
	 * 	CPT_initialization
239
	 *	registers all EE CPTs ( Custom Post Types ) then flushes rewrite rules so that all endpoints exist
240
	 *
241
	 * 	@access public
242
	 * 	@static
243
	 * 	@return void
244
	 */
245
	public static function CPT_initialization() {
246
		// register Custom Post Types
247
		EE_Registry::instance()->load_core( 'Register_CPTs' );
248
		flush_rewrite_rules();
249
	}
250
251
252
253
	/**
254
	 * 	reset_and_update_config
255
	 *
256
	 * The following code was moved over from EE_Config so that it will no longer run on every request.
257
	 * If there is old calendar config data saved, then it will get converted on activation.
258
	 * This was basically a DMS before we had DMS's, and will get removed after a few more versions.
259
	 *
260
	 * 	@access public
261
	 * 	@static
262
	 * 	@return void
263
	 */
264
	public static function reset_and_update_config() {
265
		do_action( 'AHEE__EE_Config___load_core_config__start', array( 'EEH_Activation', 'load_calendar_config' ) );
266
		add_filter( 'FHEE__EE_Config___load_core_config__config_settings', array( 'EEH_Activation', 'migrate_old_config_data' ), 10, 3 );
267
		//EE_Config::reset();
268
	}
269
270
271
	/**
272
	 *    load_calendar_config
273
	 *
274
	 * @access    public
275
	 * @return    stdClass
276
	 */
277
	public static function load_calendar_config() {
278
		// grab array of all plugin folders and loop thru it
279
		$plugins = glob( WP_PLUGIN_DIR . DS . '*', GLOB_ONLYDIR );
280
		if ( empty( $plugins ) ) {
281
			return;
282
		}
283
		foreach ( $plugins as $plugin_path ) {
284
			// grab plugin folder name from path
285
			$plugin = basename( $plugin_path );
286
			// drill down to Espresso plugins
287
			// then to calendar related plugins
288
			if (
289
				strpos( $plugin, 'espresso' ) !== FALSE
290
				|| strpos( $plugin, 'Espresso' ) !== FALSE
291
				|| strpos( $plugin, 'ee4' ) !== FALSE
292
				|| strpos( $plugin, 'EE4' ) !== FALSE
293
				|| strpos( $plugin, 'calendar' ) !== false
294
			) {
295
				// this is what we are looking for
296
				$calendar_config = $plugin_path . DS . 'EE_Calendar_Config.php';
297
				// does it exist in this folder ?
298
				if ( is_readable( $calendar_config )) {
299
					// YEAH! let's load it
300
					require_once( $calendar_config );
301
				}
302
			}
303
		}
304
	}
305
306
307
	/**
308
	 *    _migrate_old_config_data
309
	 *
310
	 * @access    public
311
	 * @param array|stdClass $settings
312
	 * @param string         $config
313
	 * @param \EE_Config     $EE_Config
314
	 * @return \stdClass
315
	 */
316
	public static function migrate_old_config_data( $settings = array(), $config = '', EE_Config $EE_Config ) {
317
		$convert_from_array = array( 'addons' );
318
		// in case old settings were saved as an array
319
		if ( is_array( $settings ) && in_array( $config, $convert_from_array )) {
320
			// convert existing settings to an object
321
			$config_array = $settings;
322
			$settings = new stdClass();
323
			foreach ( $config_array as $key => $value ){
324
				if ( $key === 'calendar' && class_exists( 'EE_Calendar_Config' )) {
325
					$EE_Config->set_config( 'addons', 'EE_Calendar', 'EE_Calendar_Config', $value );
326
				} else {
327
					$settings->{$key} = $value;
328
				}
329
			}
330
			add_filter( 'FHEE__EE_Config___load_core_config__update_espresso_config', '__return_true' );
331
		}
332
		return $settings;
0 ignored issues
show
Bug Compatibility introduced by
The expression return $settings; of type stdClass|array is incompatible with the return type documented by EEH_Activation::migrate_old_config_data of type stdClass as it can also be of type array which is not included in this return type.
Loading history...
333
	}
334
335
336
337
	/**
338
	 * deactivate_event_espresso
339
	 *
340
	 * 	@access public
341
	 * 	@static
342
	 * 	@return void
343
	 */
344
	public static function deactivate_event_espresso() {
345
		// check permissions
346
		if ( current_user_can( 'activate_plugins' )) {
347
			deactivate_plugins( EE_PLUGIN_BASENAME, TRUE );
348
		}
349
	}
350
351
352
353
354
355
	/**
356
	 * verify_default_pages_exist
357
	 *
358
	 * 	@access public
359
	 * 	@static
360
	 * 	@return void
361
	 */
362
	public static function verify_default_pages_exist() {
363
364
		$critical_page_problem = FALSE;
365
366
		$critical_pages = array(
367
			array(
368
				'id' =>'reg_page_id',
369
				'name' => __( 'Registration Checkout', 'event_espresso' ),
370
				'post' => NULL,
371
				'code' => 'ESPRESSO_CHECKOUT'
372
			),
373
			array(
374
				'id' => 'txn_page_id',
375
				'name' => __( 'Transactions', 'event_espresso' ),
376
				'post' => NULL,
377
				'code' => 'ESPRESSO_TXN_PAGE'
378
			),
379
			array(
380
				'id' => 'thank_you_page_id',
381
				'name' => __( 'Thank You', 'event_espresso' ),
382
				'post' => NULL,
383
				'code' => 'ESPRESSO_THANK_YOU'
384
			),
385
			array(
386
				'id' => 'cancel_page_id',
387
				'name' => __( 'Registration Cancelled', 'event_espresso' ),
388
				'post' => NULL,
389
				'code' => 'ESPRESSO_CANCELLED'
390
			),
391
		);
392
393
		$EE_Core_Config = EE_Registry::instance()->CFG->core;
394
395
		foreach ( $critical_pages as $critical_page ) {
396
			// is critical page ID set in config ?
397
			if ( $EE_Core_Config->{$critical_page[ 'id' ]} !== FALSE ) {
398
				// attempt to find post by ID
399
				$critical_page['post'] = get_post( $EE_Core_Config->{$critical_page[ 'id' ]} );
400
			}
401
			// no dice?
402
			if ( $critical_page['post'] === null ) {
403
				// attempt to find post by title
404
				$critical_page['post'] = self::get_page_by_ee_shortcode( $critical_page['code'] );
405
				// still nothing?
406
				if ( $critical_page['post'] === null ) {
407
					$critical_page = EEH_Activation::create_critical_page( $critical_page );
408
					// REALLY? Still nothing ??!?!?
409 View Code Duplication
					if ( $critical_page['post'] === null ) {
410
						$msg = __( 'The Event Espresso critical page configuration settings could not be updated.', 'event_espresso' );
411
						EE_Error::add_error( $msg, __FILE__, __FUNCTION__, __LINE__ );
412
						break;
413
					}
414
				}
415
			}
416
			// track post_shortcodes
417
			if ( $critical_page['post'] ) {
418
				EEH_Activation::_track_critical_page_post_shortcodes( $critical_page );
419
			}
420
			// check that Post ID matches critical page ID in config
421
			if (
422
				isset( $critical_page['post']->ID )
423
				&& $critical_page['post']->ID !== $EE_Core_Config->{$critical_page[ 'id' ]}
424
			) {
425
				//update Config with post ID
426
				$EE_Core_Config->{$critical_page[ 'id' ]} = $critical_page['post']->ID;
427 View Code Duplication
				if ( ! EE_Config::instance()->update_espresso_config( FALSE, FALSE ) ) {
428
					$msg = __( 'The Event Espresso critical page configuration settings could not be updated.', 'event_espresso' );
429
					EE_Error::add_error( $msg, __FILE__, __FUNCTION__, __LINE__ );
430
				}
431
			}
432
433
			$critical_page_problem =
434
				! isset( $critical_page['post']->post_status )
435
				|| $critical_page['post']->post_status !== 'publish'
436
				|| strpos( $critical_page['post']->post_content, $critical_page['code'] ) === FALSE
437
					? TRUE
438
					: $critical_page_problem;
439
440
		}
441
442
		if ( $critical_page_problem ) {
443
			$msg = sprintf(
444
				__('A potential issue has been detected with one or more of your Event Espresso pages. Go to %s to view your Event Espresso pages.', 'event_espresso' ),
445
				'<a href="' . admin_url('admin.php?page=espresso_general_settings&action=critical_pages') . '">' . __('Event Espresso Critical Pages Settings', 'event_espresso') . '</a>'
446
			);
447
			EE_Error::add_persistent_admin_notice( 'critical_page_problem', $msg );
448
		}
449
		if ( EE_Error::has_notices() ) {
450
			EE_Error::get_notices( FALSE, TRUE, TRUE );
451
		}
452
	}
453
454
	/**
455
	 * Returns the first post which uses the specified shortcode
456
	 * @param string $ee_shortcode usually one of the critical pages shortcodes, eg
457
	 * ESPRESSO_THANK_YOU. So we will search fora post with the content "[ESPRESSO_THANK_YOU"
458
	 * (we don't search for the closing shortcode bracket because they might have added
459
	 * parameter to the shortcode
460
	 * @return WP_Post or NULl
461
	 */
462
	public static function get_page_by_ee_shortcode($ee_shortcode){
463
		global $wpdb;
464
		$shortcode_and_opening_bracket = '['.$ee_shortcode;
465
		$post_id = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_content LIKE '%$shortcode_and_opening_bracket%' LIMIT 1");
466
		if($post_id){
467
			return get_post($post_id);
468
		}else{
469
			return NULL;
470
		}
471
472
//		return $post_id;
473
	}
474
475
476
477
	/**
478
	 *    This function generates a post for critical espresso pages
479
	 *
480
	 * @access public
481
	 * @static
482
	 * @param array $critical_page
483
	 * @return array
484
	 */
485
	public static function create_critical_page( $critical_page ) {
486
487
		$post_args = array(
488
			'post_title' => $critical_page['name'],
489
			'post_status' => 'publish',
490
			'post_type' => 'page',
491
			'comment_status' => 'closed',
492
			'post_content' => '[' . $critical_page['code'] . ']'
493
		);
494
495
		$post_id = wp_insert_post( $post_args );
496
		if ( ! $post_id ) {
497
			$msg = sprintf(
498
				__( 'The Event Espresso  critical page entitled "%s" could not be created.', 'event_espresso' ),
499
				$critical_page['name']
500
			);
501
			EE_Error::add_error( $msg, __FILE__, __FUNCTION__, __LINE__ );
502
			return $critical_page;
503
		}
504
		// get newly created post's details
505
		if ( ! $critical_page['post'] = get_post( $post_id )) {
506
			$msg = sprintf(
507
				__( 'The Event Espresso critical page entitled "%s" could not be retrieved.', 'event_espresso' ),
508
				$critical_page['name']
509
			);
510
			EE_Error::add_error( $msg, __FILE__, __FUNCTION__, __LINE__ );
511
		}
512
513
		return $critical_page;
514
515
	}
516
517
518
519
520
521
	/**
522
	 *    This function adds a critical page's shortcode to the post_shortcodes array
523
	 *
524
	 * @access private
525
	 * @static
526
	 * @param array $critical_page
527
	 * @return void
528
	 */
529
	private static function _track_critical_page_post_shortcodes( $critical_page = array() ) {
530
		// check the goods
531 View Code Duplication
		if ( ! $critical_page['post'] instanceof WP_Post ) {
0 ignored issues
show
Bug introduced by
The class WP_Post does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
532
			$msg = sprintf(
533
				__( 'The Event Espresso critical page shortcode for the page %s can not be tracked because it is not a WP_Post object.', 'event_espresso' ),
534
				$critical_page['name']
535
			);
536
			EE_Error::add_error( $msg, __FILE__, __FUNCTION__, __LINE__ );
537
			return;
538
		}
539
		$EE_Core_Config = EE_Registry::instance()->CFG->core;
540
		// map shortcode to post
541
		$EE_Core_Config->post_shortcodes[ $critical_page['post']->post_name ][ $critical_page['code'] ] = $critical_page['post']->ID;
542
		// and make sure it's NOT added to the WP "Posts Page"
543
		// name of the WP Posts Page
544
		$posts_page = EE_Config::get_page_for_posts();
545
		if ( isset( $EE_Core_Config->post_shortcodes[ $posts_page ] )) {
546
			unset( $EE_Core_Config->post_shortcodes[ $posts_page ][ $critical_page['code'] ] );
547
		}
548
		if ( $posts_page !== 'posts' && isset( $EE_Core_Config->post_shortcodes['posts'] )) {
549
			unset( $EE_Core_Config->post_shortcodes['posts'][ $critical_page['code'] ] );
550
		}
551
		// update post_shortcode CFG
552
		if ( ! EE_Config::instance()->update_espresso_config( FALSE, FALSE )) {
553
			$msg = sprintf(
554
				__( 'The Event Espresso critical page shortcode for the %s page could not be configured properly.', 'event_espresso' ),
555
				$critical_page['name']
556
			);
557
			EE_Error::add_error( $msg, __FILE__, __FUNCTION__, __LINE__ );
558
		}
559
	}
560
561
562
563
	/**
564
	 * Tries to find the oldest admin for this site.  If there are no admins for this site then return NULL.
565
	 * The role being used to check is filterable.
566
	 *
567
	 * @since  4.6.0
568
	 * @global WPDB $wpdb
569
	 *
570
	 * @return mixed null|int WP_user ID or NULL
571
	 */
572
	public static function get_default_creator_id() {
573
		global $wpdb;
574
575
		if ( ! empty( self::$_default_creator_id ) ) {
576
			return self::$_default_creator_id;
577
		}/**/
578
579
		$role_to_check = apply_filters( 'FHEE__EEH_Activation__get_default_creator_id__role_to_check', 'administrator' );
580
581
		//let's allow pre_filtering for early exits by alternative methods for getting id.  We check for truthy result and if so then exit early.
582
		$pre_filtered_id = apply_filters( 'FHEE__EEH_Activation__get_default_creator_id__pre_filtered_id', false, $role_to_check );
583
		if ( $pre_filtered_id !== false ) {
584
			return (int) $pre_filtered_id;
585
		}
586
587
		$capabilities_key = EEH_Activation::ensure_table_name_has_prefix( 'capabilities' );
588
		$query = $wpdb->prepare( "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = '$capabilities_key' AND meta_value LIKE %s ORDER BY user_id ASC LIMIT 0,1", '%' . $role_to_check . '%' );
589
		$user_id = $wpdb->get_var( $query );
590
		 $user_id = apply_filters( 'FHEE__EEH_Activation_Helper__get_default_creator_id__user_id', $user_id );
591
		 if ( $user_id && (int)$user_id ) {
592
		 	self::$_default_creator_id = (int)$user_id;
593
		 	return self::$_default_creator_id;
594
		 } else {
595
		 	return NULL;
596
		 }
597
	}
598
599
600
601
602
603
	/**
604
	 * 	used by EE and EE addons during plugin activation
605
	 *
606
	 * 	@access public
607
	 * 	@static
608
	 * @param string $table_name without the $wpdb->prefix
609
	 * @param string $sql SQL for creating the table (contents between brackets in an SQL create table query)
610
	 * @param string $engine like 'ENGINE=MyISAM' or 'ENGINE=InnoDB'
611
	 * @param boolean $drop_pre_existing_table set to TRUE when you want to make SURE the table is completely empty
612
	 * and new once this function is done (ie, you really do want to CREATE a table, and
613
	 * expect it to be empty once you're done)
614
	 * leave as FALSE when you just want to verify the table exists and matches this definition (and if it
615
	 * HAS data in it you want to leave it be)
616
	 * 	@return void
617
	 * @throws EE_Error if there are database errors
618
	 */
619
	public static function create_table( $table_name, $sql, $engine = 'ENGINE=MyISAM ', $drop_pre_existing_table = false ) {
620
		if( apply_filters( 'FHEE__EEH_Activation__create_table__short_circuit', FALSE, $table_name, $sql ) ){
621
			return;
622
		}
623
		do_action( 'AHEE_log', __FILE__, __FUNCTION__, '' );
624
		if ( ! function_exists( 'dbDelta' )) {
625
			require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
626
		}
627
		/** @var WPDB $wpdb */
628
		global $wpdb;
629
		$wp_table_name = EEH_Activation::ensure_table_name_has_prefix( $table_name );
630
		// do we need to first delete an existing version of this table ?
631
		if ( $drop_pre_existing_table && EEH_Activation::table_exists( $wp_table_name ) ){
632
			// ok, delete the table... but ONLY if it's empty
633
			$deleted_safely = EEH_Activation::delete_db_table_if_empty( $wp_table_name );
634
			// table is NOT empty, are you SURE you want to delete this table ???
635
			if ( ! $deleted_safely && defined( 'EE_DROP_BAD_TABLES' ) && EE_DROP_BAD_TABLES ){
636
				EEH_Activation::delete_unused_db_table( $wp_table_name );
637
			} else if ( ! $deleted_safely ) {
638
				// so we should be more cautious rather than just dropping tables so easily
639
				EE_Error::add_persistent_admin_notice(
640
						'bad_table_' . $wp_table_name . '_detected',
641
						sprintf( __( 'Database table %1$s exists when it shouldn\'t, and may contain erroneous data. If you have previously restored your database from a backup that didn\'t remove the old tables, then we recommend adding %2$s to your %3$s file then restore to that backup again. This will clear out the invalid data from %1$s. Afterwards you should undo that change from your %3$s file. %4$sIf you cannot edit %3$s, you should remove the data from %1$s manually then restore to the backup again.', 'event_espresso' ),
642
								$wp_table_name,
643
								"<pre>define( 'EE_DROP_BAD_TABLES', TRUE );</pre>",
644
								'<b>wp-config.php</b>',
645
								'<br/>'),
646
								TRUE );
647
			}
648
		}
649
		// does $sql contain valid column information? ( LPT: https://regex101.com/ is great for working out regex patterns )
650
		if ( preg_match( '((((.*?))(,\s))+)', $sql, $valid_column_data ) ) {
651
			$SQL = "CREATE TABLE $wp_table_name ( $sql ) $engine DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;";
652
			//get $wpdb to echo errors, but buffer them. This way at least WE know an error
653
			//happened. And then we can choose to tell the end user
654
			$old_show_errors_policy = $wpdb->show_errors( TRUE );
655
			$old_error_suppression_policy = $wpdb->suppress_errors( FALSE );
656
			ob_start();
657
			dbDelta( $SQL );
658
			$output = ob_get_contents();
659
			ob_end_clean();
660
			$wpdb->show_errors( $old_show_errors_policy );
661
			$wpdb->suppress_errors( $old_error_suppression_policy );
662
			if( ! empty( $output ) ){
663
				throw new EE_Error( $output	);
664
			}
665
		} else {
666
			throw new EE_Error(
667
				sprintf(
668
					__( 'The following table creation SQL does not contain valid information about the table columns: %1$s %2$s', 'event_espresso' ),
669
					'<br />',
670
					$sql
671
				)
672
			);
673
		}
674
675
	}
676
677
678
679
	/**
680
	 *    add_column_if_it_doesn't_exist
681
	 *    Checks if this column already exists on the specified table. Handy for addons which want to add a column
682
	 *
683
	 * @access public
684
	 * @static
685
	 * @param string $table_name  (without "wp_", eg "esp_attendee"
686
	 * @param string $column_name
687
	 * @param string $column_info if your SQL were 'ALTER TABLE table_name ADD price VARCHAR(10)', this would be
688
	 *                            'VARCHAR(10)'
689
	 * @return bool|int
690
	 */
691 View Code Duplication
	public static function add_column_if_it_doesnt_exist($table_name,$column_name,$column_info='INT UNSIGNED NOT NULL'){
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
692
		if( apply_filters( 'FHEE__EEH_Activation__add_column_if_it_doesnt_exist__short_circuit', FALSE ) ){
693
			return FALSE;
694
		}
695
		global $wpdb;
696
		$full_table_name= EEH_Activation::ensure_table_name_has_prefix( $table_name );
697
		$fields = self::get_fields_on_table($table_name);
698
		if (!in_array($column_name, $fields)){
699
			$alter_query="ALTER TABLE $full_table_name ADD $column_name $column_info";
700
			//echo "alter query:$alter_query";
701
			return $wpdb->query($alter_query);
702
		}
703
		return TRUE;
704
	}
705
706
707
708
709
	/**
710
	 * get_fields_on_table
711
	 * Gets all the fields on the database table.
712
	 *
713
	 * 	@access public
714
	 * 	@static
715
	 * 	@param string $table_name, without prefixed $wpdb->prefix
0 ignored issues
show
Documentation introduced by
There is no parameter named $table_name,. Did you maybe mean $table_name?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
716
	 * 	@return array of database column names
717
	 */
718
	public static function get_fields_on_table( $table_name = NULL ) {
719
		global $wpdb;
720
		$table_name= EEH_Activation::ensure_table_name_has_prefix( $table_name );
721
		if ( ! empty( $table_name )) {
722
			$columns = $wpdb->get_results("SHOW COLUMNS FROM $table_name ");
723
			if ($columns !== FALSE) {
724
				$field_array = array();
725
				foreach($columns as $column ){
726
					$field_array[] = $column->Field;
727
				}
728
				return $field_array;
729
			}
730
		}
731
		return FALSE;
732
	}
733
734
735
736
	/**
737
	 * db_table_is_empty
738
	 *
739
	 * @access public
740
	 * @static
741
	 * @param string $table_name
742
	 * @return bool
743
	 */
744
	public static function db_table_is_empty( $table_name ) {
745
		global $wpdb;
746
		$table_name = EEH_Activation::ensure_table_name_has_prefix( $table_name );
747
		if ( EEH_Activation::table_exists( $table_name ) ) {
748
			$count = $wpdb->get_var( "SELECT COUNT(*) FROM $table_name" );
749
			return absint( $count ) === 0 ? true : false;
750
		}
751
		return false;
752
	}
753
754
755
756
	/**
757
	 * delete_db_table_if_empty
758
	 *
759
	 * @access public
760
	 * @static
761
	 * @param string $table_name
762
	 * @return bool | int
763
	 */
764
	public static function delete_db_table_if_empty( $table_name ) {
765
		if ( EEH_Activation::db_table_is_empty( $table_name ) ) {
766
			return EEH_Activation::delete_unused_db_table( $table_name );
767
		}
768
		return false;
769
	}
770
771
772
773
	/**
774
	 * delete_unused_db_table
775
	 *
776
	 * @access public
777
	 * @static
778
	 * @param string $table_name
779
	 * @return bool | int
780
	 */
781
	public static function delete_unused_db_table( $table_name ) {
782
		global $wpdb;
783
		if ( EEH_Activation::table_exists( $table_name ) ) {
784
			$table_name = EEH_Activation::ensure_table_name_has_prefix( $table_name );
785
			return $wpdb->query( "DROP TABLE IF EXISTS $table_name" );
786
		}
787
		return false;
788
	}
789
790
791
792
	/**
793
	 * drop_index
794
	 *
795
	 * @access public
796
	 * @static
797
	 * @param string $table_name
798
	 * @param string $index_name
799
	 * @return bool | int
800
	 */
801 View Code Duplication
	public static function drop_index( $table_name, $index_name ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
802
		if( apply_filters( 'FHEE__EEH_Activation__drop_index__short_circuit', FALSE ) ){
803
			return FALSE;
804
		}
805
		global $wpdb;
806
		$table_name = EEH_Activation::ensure_table_name_has_prefix( $table_name );
807
		$index_exists_query = "SHOW INDEX FROM $table_name WHERE Key_name = '$index_name'";
808
		if (
809
			EEH_Activation::table_exists(  $table_name )
810
			&& $wpdb->get_var( $index_exists_query ) === $table_name //using get_var with the $index_exists_query returns the table's name
811
		) {
812
			return $wpdb->query( "ALTER TABLE $table_name DROP INDEX $index_name" );
813
		}
814
		return TRUE;
815
	}
816
817
818
819
	/**
820
	 * create_database_tables
821
	 *
822
	 * @access public
823
	 * @static
824
	 * @throws EE_Error
825
	 * @return boolean success (whether database is setup properly or not)
826
	 */
827
	public static function create_database_tables() {
828
		EE_Registry::instance()->load_core( 'Data_Migration_Manager' );
829
		//find the migration script that sets the database to be compatible with the code
830
		$dms_name = EE_Data_Migration_Manager::instance()->get_most_up_to_date_dms();
831
		if( $dms_name ){
832
			$current_data_migration_script = EE_Registry::instance()->load_dms( $dms_name );
833
			$current_data_migration_script->set_migrating( false );
834
			$current_data_migration_script->schema_changes_before_migration();
835
			$current_data_migration_script->schema_changes_after_migration();
836 View Code Duplication
			if( $current_data_migration_script->get_errors() ){
837
				if( WP_DEBUG ){
838
					foreach( $current_data_migration_script->get_errors() as $error ){
839
						EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__ );
840
					}
841
				}else{
842
					EE_Error::add_error( __( 'There were errors creating the Event Espresso database tables and Event Espresso has been deactivated. To view the errors, please enable WP_DEBUG in your wp-config.php file.', 'event_espresso' ) );
843
				}
844
				return false;
845
			}
846
			EE_Data_Migration_Manager::instance()->update_current_database_state_to();
847
		}else{
848
			EE_Error::add_error( __( 'Could not determine most up-to-date data migration script from which to pull database schema structure. So database is probably not setup properly', 'event_espresso' ), __FILE__, __FUNCTION__, __LINE__);
849
			return false;
850
		}
851
		return true;
852
	}
853
854
855
856
857
858
	/**
859
	 * initialize_system_questions
860
	 *
861
	 * 	@access public
862
	 * 	@static
863
	 * 	@return void
864
	 */
865
	public static function initialize_system_questions() {
866
		// QUESTION GROUPS
867
		global $wpdb;
868
		$table_name = EEH_Activation::ensure_table_name_has_prefix( 'esp_question_group' );
869
		$SQL = "SELECT QSG_system FROM $table_name WHERE QSG_system != 0";
870
		// what we have
871
		$question_groups = $wpdb->get_col( $SQL );
872
		// check the response
873
		$question_groups = is_array( $question_groups ) ? $question_groups : array();
874
		// what we should have
875
		$QSG_systems = array( 1, 2 );
876
		// loop thru what we should have and compare to what we have
877
		foreach ( $QSG_systems as $QSG_system ) {
878
			// reset values array
879
			$QSG_values = array();
880
			// if we don't have what we should have (but use $QST_system as as string because that's what we got from the db)
881
			if ( ! in_array( "$QSG_system", $question_groups )) {
882
				// add it
883
				switch ( $QSG_system ) {
884
885 View Code Duplication
					case 1:
886
							$QSG_values = array(
887
									'QSG_name' => __( 'Personal Information', 'event_espresso' ),
888
									'QSG_identifier' => 'personal-information-' . time(),
889
									'QSG_desc' => '',
890
									'QSG_order' => 1,
891
									'QSG_show_group_name' => 1,
892
									'QSG_show_group_desc' => 1,
893
									'QSG_system' => EEM_Question_Group::system_personal,
894
									'QSG_deleted' => 0
895
								);
896
						break;
897
898 View Code Duplication
					case 2:
899
							$QSG_values = array(
900
									'QSG_name' => __( 'Address Information','event_espresso' ),
901
									'QSG_identifier' => 'address-information-' . time(),
902
									'QSG_desc' => '',
903
									'QSG_order' => 2,
904
									'QSG_show_group_name' => 1,
905
									'QSG_show_group_desc' => 1,
906
									'QSG_system' => EEM_Question_Group::system_address,
907
									'QSG_deleted' => 0
908
								);
909
						break;
910
911
				}
912
				// make sure we have some values before inserting them
913
				if ( ! empty( $QSG_values )) {
914
					// insert system question
915
					$wpdb->insert(
916
						$table_name,
917
						$QSG_values,
918
						array('%s', '%s', '%s', '%d', '%d', '%d', '%d', '%d' )
919
					);
920
					$QSG_IDs[ $QSG_system ] = $wpdb->insert_id;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$QSG_IDs was never initialized. Although not strictly required by PHP, it is generally a good practice to add $QSG_IDs = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
921
				}
922
			}
923
		}
924
925
926
927
		// QUESTIONS
928
		global $wpdb;
929
		$table_name = EEH_Activation::ensure_table_name_has_prefix( 'esp_question' );
930
		$SQL = "SELECT QST_system FROM $table_name WHERE QST_system != ''";
931
		// what we have
932
		$questions = $wpdb->get_col( $SQL );
933
		// what we should have
934
		$QST_systems = array(
935
			'fname',
936
			'lname',
937
			'email',
938
			'address',
939
			'address2',
940
			'city',
941
			'state',
942
			'country',
943
			'zip',
944
			'phone'
945
		);
946
		$order_for_group_1 = 1;
947
		$order_for_group_2 = 1;
948
		// loop thru what we should have and compare to what we have
949
		foreach ( $QST_systems as $QST_system ) {
950
			// reset values array
951
			$QST_values = array();
952
			// if we don't have what we should have
953
			if ( ! in_array( $QST_system, $questions )) {
954
				// add it
955
				switch ( $QST_system ) {
956
957 View Code Duplication
					case 'fname':
958
							$QST_values = array(
959
									'QST_display_text' => __( 'First Name', 'event_espresso' ),
960
									'QST_admin_label' => __( 'First Name - System Question', 'event_espresso' ),
961
									'QST_system' => 'fname',
962
									'QST_type' => 'TEXT',
963
									'QST_required' => 1,
964
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
965
									'QST_order' => 1,
966
									'QST_admin_only' => 0,
967
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
968
									'QST_wp_user' => self::get_default_creator_id(),
969
									'QST_deleted' => 0
970
								);
971
						break;
972
973 View Code Duplication
					case 'lname':
974
							$QST_values = array(
975
									'QST_display_text' => __( 'Last Name', 'event_espresso' ),
976
									'QST_admin_label' => __( 'Last Name - System Question', 'event_espresso' ),
977
									'QST_system' => 'lname',
978
									'QST_type' => 'TEXT',
979
									'QST_required' => 1,
980
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
981
									'QST_order' => 2,
982
									'QST_admin_only' => 0,
983
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
984
									'QST_wp_user' => self::get_default_creator_id(),
985
									'QST_deleted' => 0
986
								);
987
						break;
988
989 View Code Duplication
					case 'email':
990
							$QST_values = array(
991
									'QST_display_text' => __( 'Email Address', 'event_espresso' ),
992
									'QST_admin_label' => __( 'Email Address - System Question', 'event_espresso' ),
993
									'QST_system' => 'email',
994
									'QST_type' => 'EMAIL',
995
									'QST_required' => 1,
996
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
997
									'QST_order' => 3,
998
									'QST_admin_only' => 0,
999
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
1000
									'QST_wp_user' => self::get_default_creator_id(),
1001
									'QST_deleted' => 0
1002
								);
1003
						break;
1004
1005 View Code Duplication
					case 'address':
1006
							$QST_values = array(
1007
									'QST_display_text' => __( 'Address', 'event_espresso' ),
1008
									'QST_admin_label' => __( 'Address - System Question', 'event_espresso' ),
1009
									'QST_system' => 'address',
1010
									'QST_type' => 'TEXT',
1011
									'QST_required' => 0,
1012
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
1013
									'QST_order' => 4,
1014
									'QST_admin_only' => 0,
1015
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
1016
									'QST_wp_user' => self::get_default_creator_id(),
1017
									'QST_deleted' => 0
1018
								);
1019
						break;
1020
1021 View Code Duplication
					case 'address2':
1022
							$QST_values = array(
1023
									'QST_display_text' => __( 'Address2', 'event_espresso' ),
1024
									'QST_admin_label' => __( 'Address2 - System Question', 'event_espresso' ),
1025
									'QST_system' => 'address2',
1026
									'QST_type' => 'TEXT',
1027
									'QST_required' => 0,
1028
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
1029
									'QST_order' => 5,
1030
									'QST_admin_only' => 0,
1031
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
1032
									'QST_wp_user' => self::get_default_creator_id(),
1033
									'QST_deleted' => 0
1034
								);
1035
						break;
1036
1037 View Code Duplication
					case 'city':
1038
							$QST_values = array(
1039
									'QST_display_text' => __( 'City', 'event_espresso' ),
1040
									'QST_admin_label' => __( 'City - System Question', 'event_espresso' ),
1041
									'QST_system' => 'city',
1042
									'QST_type' => 'TEXT',
1043
									'QST_required' => 0,
1044
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
1045
									'QST_order' => 6,
1046
									'QST_admin_only' => 0,
1047
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
1048
									'QST_wp_user' => self::get_default_creator_id(),
1049
									'QST_deleted' => 0
1050
								);
1051
						break;
1052
1053 View Code Duplication
					case 'state':
1054
							$QST_values = array(
1055
									'QST_display_text' => __( 'State/Province', 'event_espresso' ),
1056
									'QST_admin_label' => __( 'State/Province - System Question', 'event_espresso' ),
1057
									'QST_system' => 'state',
1058
									'QST_type' => 'STATE',
1059
									'QST_required' => 0,
1060
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
1061
									'QST_order' => 7,
1062
									'QST_admin_only' => 0,
1063
									'QST_wp_user' => self::get_default_creator_id(),
1064
									'QST_deleted' => 0
1065
								);
1066
						break;
1067
1068 View Code Duplication
					case 'country' :
1069
							$QST_values = array(
1070
									'QST_display_text' => __( 'Country', 'event_espresso' ),
1071
									'QST_admin_label' => __( 'Country - System Question', 'event_espresso' ),
1072
									'QST_system' => 'country',
1073
									'QST_type' => 'COUNTRY',
1074
									'QST_required' => 0,
1075
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
1076
									'QST_order' => 8,
1077
									'QST_admin_only' => 0,
1078
									'QST_wp_user' => self::get_default_creator_id(),
1079
									'QST_deleted' => 0
1080
								);
1081
						break;
1082
1083 View Code Duplication
					case 'zip':
1084
							$QST_values = array(
1085
									'QST_display_text' => __( 'Zip/Postal Code', 'event_espresso' ),
1086
									'QST_admin_label' => __( 'Zip/Postal Code - System Question', 'event_espresso' ),
1087
									'QST_system' => 'zip',
1088
									'QST_type' => 'TEXT',
1089
									'QST_required' => 0,
1090
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
1091
									'QST_order' => 9,
1092
									'QST_admin_only' => 0,
1093
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
1094
									'QST_wp_user' => self::get_default_creator_id(),
1095
									'QST_deleted' => 0
1096
								);
1097
						break;
1098
1099 View Code Duplication
					case 'phone':
1100
							$QST_values = array(
1101
									'QST_display_text' => __( 'Phone Number', 'event_espresso' ),
1102
									'QST_admin_label' => __( 'Phone Number - System Question', 'event_espresso' ),
1103
									'QST_system' => 'phone',
1104
									'QST_type' => 'TEXT',
1105
									'QST_required' => 0,
1106
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
1107
									'QST_order' => 10,
1108
									'QST_admin_only' => 0,
1109
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
1110
									'QST_wp_user' => self::get_default_creator_id(),
1111
									'QST_deleted' => 0
1112
								);
1113
						break;
1114
1115
				}
1116
				if ( ! empty( $QST_values )) {
1117
					// insert system question
1118
					$wpdb->insert(
1119
						$table_name,
1120
						$QST_values,
1121
						array( '%s', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%d', '%d' )
1122
					);
1123
					$QST_ID = $wpdb->insert_id;
1124
1125
					// QUESTION GROUP QUESTIONS
1126
					if(  in_array( $QST_system, array( 'fname', 'lname', 'email' ) ) ) {
1127
						$system_question_we_want = EEM_Question_Group::system_personal;
1128
					} else {
1129
						$system_question_we_want = EEM_Question_Group::system_address;
1130
					}
1131
					if( isset( $QSG_IDs[ $system_question_we_want ] ) ) {
1132
						$QSG_ID = $QSG_IDs[ $system_question_we_want ];
1133
					} else {
1134
						$id_col = EEM_Question_Group::instance()->get_col( array( array( 'QSG_system' => $system_question_we_want ) ) );
1135
						if( is_array( $id_col ) ) {
1136
							$QSG_ID = reset( $id_col );
1137
						} else {
1138
							//ok so we didn't find it in the db either?? that's weird because we should have inserted it at the start of this method
1139
                                                        EE_Log::instance()->log(
1140
                                                                __FILE__,
1141
                                                                __FUNCTION__,
1142
                                                                sprintf(
1143
                                                                        __( 'Could not associate question %1$s to a question group because no system question group existed', 'event_espresso'),
1144
                                                                        $QST_ID ),
1145
                                                                'error' );
1146
                                                        continue;
1147
						}
1148
					}
1149
1150
					// add system questions to groups
1151
					$wpdb->insert(
1152
						EEH_Activation::ensure_table_name_has_prefix( 'esp_question_group_question' ),
1153
						array( 'QSG_ID'    => $QSG_ID,
1154
						       'QST_ID'    => $QST_ID,
1155
						       'QGQ_order' => ( $QSG_ID === 1 ) ? $order_for_group_1++ : $order_for_group_2++
1156
						),
1157
						array( '%d', '%d', '%d' )
1158
					);
1159
				}
1160
			}
1161
		}
1162
1163
	}
1164
1165
1166
1167
	/**
1168
	 * Makes sure the default payment method (Invoice) is active.
1169
	 * This used to be done automatically as part of constructing the old gateways config
1170
	 *
1171
	 * @throws \EE_Error
1172
	 */
1173
	public static function insert_default_payment_methods(){
1174
		if( ! EEM_Payment_Method::instance()->count_active( EEM_Payment_Method::scope_cart ) ){
1175
			EE_Registry::instance()->load_lib( 'Payment_Method_Manager' );
1176
			EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type( 'Invoice' );
1177
		}else{
1178
			EEM_Payment_Method::instance()->verify_button_urls();
1179
		}
1180
	}
1181
1182
	/**
1183
	 * insert_default_status_codes
1184
	 *
1185
	 * 	@access public
1186
	 * 	@static
1187
	 * 	@return void
1188
	 */
1189
	public static function insert_default_status_codes() {
1190
1191
		global $wpdb;
1192
1193
		if ( EEH_Activation::table_exists( EEM_Status::instance()->table() ) ) {
1194
1195
			$table_name = EEM_Status::instance()->table();
1196
1197
			$SQL = "DELETE FROM $table_name WHERE STS_ID IN ( 'ACT', 'NAC', 'NOP', 'OPN', 'CLS', 'PND', 'ONG', 'SEC', 'DRF', 'DEL', 'DEN', 'EXP', 'RPP', 'RCN', 'RDC', 'RAP', 'RNA', 'TAB', 'TIN', 'TFL', 'TCM', 'TOP', 'PAP', 'PCN', 'PFL', 'PDC', 'EDR', 'ESN', 'PPN', 'RIC', 'MSN', 'MFL', 'MID', 'MRS', 'MIC' );";
1198
			$wpdb->query($SQL);
1199
1200
			$SQL = "INSERT INTO $table_name
1201
					(STS_ID, STS_code, STS_type, STS_can_edit, STS_desc, STS_open) VALUES
1202
					('ACT', 'ACTIVE', 'event', 0, NULL, 1),
1203
					('NAC', 'NOT_ACTIVE', 'event', 0, NULL, 0),
1204
					('NOP', 'REGISTRATION_NOT_OPEN', 'event', 0, NULL, 1),
1205
					('OPN', 'REGISTRATION_OPEN', 'event', 0, NULL, 1),
1206
					('CLS', 'REGISTRATION_CLOSED', 'event', 0, NULL, 0),
1207
					('PND', 'PENDING', 'event', 0, NULL, 1),
1208
					('ONG', 'ONGOING', 'event', 0, NULL, 1),
1209
					('SEC', 'SECONDARY', 'event', 0, NULL, 1),
1210
					('DRF', 'DRAFT', 'event', 0, NULL, 0),
1211
					('DEL', 'DELETED', 'event', 0, NULL, 0),
1212
					('DEN', 'DENIED', 'event', 0, NULL, 0),
1213
					('EXP', 'EXPIRED', 'event', 0, NULL, 0),
1214
					('RPP', 'PENDING_PAYMENT', 'registration', 0, NULL, 1),
1215
					('RAP', 'APPROVED', 'registration', 0, NULL, 1),
1216
					('RCN', 'CANCELLED', 'registration', 0, NULL, 0),
1217
					('RDC', 'DECLINED', 'registration', 0, NULL, 0),
1218
					('RNA', 'NOT_APPROVED', 'registration', 0, NULL, 1),
1219
					('RIC', 'INCOMPLETE', 'registration', 0, NULL, 1),
1220
					('TFL', 'FAILED', 'transaction', 0, NULL, 0),
1221
					('TAB', 'ABANDONED', 'transaction', 0, NULL, 0),
1222
					('TIN', 'INCOMPLETE', 'transaction', 0, NULL, 1),
1223
					('TCM', 'COMPLETE', 'transaction', 0, NULL, 1),
1224
					('TOP',	'OVERPAID', 'transaction', 0, NULL, 1),
1225
					('PAP', 'APPROVED', 'payment', 0, NULL, 1),
1226
					('PPN', 'PENDING', 'payment', 0, NULL, 1),
1227
					('PCN', 'CANCELLED', 'payment', 0, NULL, 0),
1228
					('PFL', 'FAILED', 'payment', 0, NULL, 0),
1229
					('PDC', 'DECLINED', 'payment', 0, NULL, 0),
1230
					('EDR', 'DRAFT', 'email', 0, NULL, 0),
1231
					('ESN', 'SENT', 'email', 0, NULL, 1),
1232
					('MSN', 'SENT', 'message', 0, NULL, 0),
1233
					('MFL', 'FAIL', 'message', 0, NULL, 0),
1234
					('MID', 'IDLE', 'message', 0, NULL, 1),
1235
					('MRS', 'RESEND', 'message', 0, NULL, 1),
1236
					('MIC', 'INCOMPLETE', 'message', 0, NULL, 0);";
1237
			$wpdb->query($SQL);
1238
1239
		}
1240
1241
	}
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
	/**
1256
	 * create_upload_directories
1257
	 * Creates folders in the uploads directory to facilitate addons and templates
1258
	 *
1259
	 * 	@access public
1260
	 * 	@static
1261
	 * 	@return boolean success of verifying upload directories exist
1262
	 */
1263
	public static function create_upload_directories() {
1264
		// Create the required folders
1265
		$folders = array(
1266
				EVENT_ESPRESSO_TEMPLATE_DIR,
1267
				EVENT_ESPRESSO_GATEWAY_DIR,
1268
				EVENT_ESPRESSO_UPLOAD_DIR . 'logs/',
1269
				EVENT_ESPRESSO_UPLOAD_DIR . 'css/',
1270
				EVENT_ESPRESSO_UPLOAD_DIR . 'tickets/'
1271
		);
1272
		foreach ( $folders as $folder ) {
1273
			try {
1274
				EEH_File::ensure_folder_exists_and_is_writable( $folder );
1275
				@ chmod( $folder, 0755 );
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1276
			} catch( EE_Error $e ){
1277
				EE_Error::add_error(
1278
					sprintf(
1279
						__(  'Could not create the folder at "%1$s" because: %2$s', 'event_espresso' ),
1280
						$folder,
1281
						'<br />' . $e->getMessage()
1282
					),
1283
					__FILE__, __FUNCTION__, __LINE__
1284
				);
1285
				//indicate we'll need to fix this later
1286
				update_option( EEH_Activation::upload_directories_incomplete_option_name, true );
1287
				return FALSE;
1288
			}
1289
		}
1290
		//just add the .htaccess file to the logs directory to begin with. Even if logging
1291
		//is disabled, there might be activation errors recorded in there
1292
		EEH_File::add_htaccess_deny_from_all( EVENT_ESPRESSO_UPLOAD_DIR . 'logs/' );
1293
		//remember EE's folders are all good
1294
		delete_option( EEH_Activation::upload_directories_incomplete_option_name );
1295
		return TRUE;
1296
	}
1297
1298
	/**
1299
	 * Whether the upload directories need to be fixed or not.
1300
	 * If EE is installed but filesystem access isn't initially available,
1301
	 * we need to get the user's filesystem credentials and THEN create them,
1302
	 * so there might be period of time when EE is installed but its
1303
	 * upload directories aren't available. This indicates such a state
1304
	 * @return boolean
1305
	 */
1306
	public static function upload_directories_incomplete() {
1307
		return get_option( EEH_Activation::upload_directories_incomplete_option_name, false );
1308
	}
1309
1310
1311
1312
	/**
1313
	 * generate_default_message_templates
1314
	 *
1315
	 * @static
1316
	 * @throws EE_Error
1317
	 * @return bool     true means new templates were created.
1318
	 *                  false means no templates were created.
1319
	 *                  This is NOT an error flag. To check for errors you will want
1320
	 *                  to use either EE_Error or a try catch for an EE_Error exception.
1321
	 */
1322
	public static function generate_default_message_templates() {
1323
		/** @type EE_Message_Resource_Manager $message_resource_manager */
1324
		$message_resource_manager = EE_Registry::instance()->load_lib( 'Message_Resource_Manager' );
1325
		/*
1326
		 * This first method is taking care of ensuring any default messengers
1327
		 * that should be made active and have templates generated are done.
1328
		 */
1329
		$new_templates_created_for_messenger = self::_activate_and_generate_default_messengers_and_message_templates(
1330
			$message_resource_manager
1331
		);
1332
		/**
1333
		 * This method is verifying there are no NEW default message types
1334
		 * for ACTIVE messengers that need activated (and corresponding templates setup).
1335
		 */
1336
		$new_templates_created_for_message_type = self::_activate_new_message_types_for_active_messengers_and_generate_default_templates(
1337
			$message_resource_manager
1338
		);
1339
		//after all is done, let's persist these changes to the db.
1340
		$message_resource_manager->update_has_activated_messengers_option();
1341
		$message_resource_manager->update_active_messengers_option();
1342
		// will return true if either of these are true.  Otherwise will return false.
1343
		return $new_templates_created_for_message_type || $new_templates_created_for_messenger;
1344
	}
1345
1346
1347
1348
	/**
1349
	 * @param \EE_Message_Resource_Manager $message_resource_manager
1350
	 * @return array|bool
1351
	 * @throws \EE_Error
1352
	 */
1353
	protected static function _activate_new_message_types_for_active_messengers_and_generate_default_templates(
1354
		EE_Message_Resource_Manager $message_resource_manager
1355
	) {
1356
		/** @type EE_messenger[] $active_messengers */
1357
		$active_messengers = $message_resource_manager->active_messengers();
1358
		$installed_message_types = $message_resource_manager->installed_message_types();
1359
		$templates_created = false;
1360
		foreach ( $active_messengers as $active_messenger ) {
1361
			$default_message_type_names_for_messenger = $active_messenger->get_default_message_types();
1362
			$default_message_type_names_to_activate = array();
1363
			// looping through each default message type reported by the messenger
1364
			// and setup the actual message types to activate.
1365
			foreach ( $default_message_type_names_for_messenger as $default_message_type_name_for_messenger ) {
1366
				// if already active or has already been activated before we skip
1367
				// (otherwise we might reactivate something user's intentionally deactivated.)
1368
				// we also skip if the message type is not installed.
1369
				if (
1370
					$message_resource_manager->has_message_type_been_activated_for_messenger( $default_message_type_name_for_messenger, $active_messenger->name )
1371
					|| $message_resource_manager->is_message_type_active_for_messenger(
1372
						$active_messenger->name,
1373
						$default_message_type_name_for_messenger
1374
					)
1375
					|| ! isset( $installed_message_types[ $default_message_type_name_for_messenger ] )
1376
				) {
1377
					continue;
1378
				}
1379
				$default_message_type_names_to_activate[] = $default_message_type_name_for_messenger;
1380
			}
1381
			//let's activate!
1382
			$message_resource_manager->ensure_message_types_are_active(
1383
				$default_message_type_names_to_activate,
1384
				$active_messenger->name,
1385
				false
1386
			);
1387
			//activate the templates for these message types
1388
			if ( ! empty( $default_message_type_names_to_activate ) ) {
1389
				$templates_created = EEH_MSG_Template::generate_new_templates(
1390
					$active_messenger->name,
1391
					$default_message_type_names_for_messenger,
1392
					'',
1393
					true
1394
				);
1395
			}
1396
		}
1397
		return $templates_created;
1398
	}
1399
1400
1401
1402
	/**
1403
	 * This will activate and generate default messengers and default message types for those messengers.
1404
	 *
1405
	 * @param EE_message_Resource_Manager $message_resource_manager
1406
	 * @return array|bool  True means there were default messengers and message type templates generated.
1407
	 *                     False means that there were no templates generated
1408
	 *                     (which could simply mean there are no default message types for a messenger).
1409
	 * @throws EE_Error
1410
	 */
1411
	protected static function _activate_and_generate_default_messengers_and_message_templates(
1412
		EE_Message_Resource_Manager $message_resource_manager
1413
	) {
1414
		/** @type EE_messenger[] $messengers_to_generate */
1415
		$messengers_to_generate = self::_get_default_messengers_to_generate_on_activation( $message_resource_manager );
1416
		$installed_message_types = $message_resource_manager->installed_message_types();
1417
		$templates_generated = false;
1418
		foreach ( $messengers_to_generate as $messenger_to_generate ) {
1419
			$default_message_type_names_for_messenger = $messenger_to_generate->get_default_message_types();
1420
			//verify the default message types match an installed message type.
1421
			foreach ( $default_message_type_names_for_messenger as $key => $name ) {
1422
				if (
1423
					! isset( $installed_message_types[ $name ] )
1424
					|| $message_resource_manager->has_message_type_been_activated_for_messenger( $name, $messenger_to_generate->name )
1425
				) {
1426
					unset( $default_message_type_names_for_messenger[ $key ] );
1427
				}
1428
			}
1429
			// in previous iterations, the active_messengers option in the db
1430
			// needed updated before calling create templates. however with the changes this may not be necessary.
1431
			// This comment is left here just in case we discover that we _do_ need to update before
1432
			// passing off to create templates (after the refactor is done).
1433
			// @todo remove this comment when determined not necessary.
1434
			$message_resource_manager->activate_messenger(
1435
				$messenger_to_generate->name,
1436
				$default_message_type_names_for_messenger,
1437
				false
1438
			);
1439
			//create any templates needing created (or will reactivate templates already generated as necessary).
1440
			if ( ! empty( $default_message_type_names_for_messenger ) ) {
1441
				$templates_generated = EEH_MSG_Template::generate_new_templates(
1442
					$messenger_to_generate->name,
1443
					$default_message_type_names_for_messenger,
1444
					'',
1445
					true
1446
				);
1447
			}
1448
		}
1449
		return $templates_generated;
1450
	}
1451
1452
1453
1454
	/**
1455
	 * This returns the default messengers to generate templates for on activation of EE.
1456
	 * It considers:
1457
	 * - whether a messenger is already active in the db.
1458
	 * - whether a messenger has been made active at any time in the past.
1459
	 *
1460
	 * @static
1461
	 * @param  EE_Message_Resource_Manager $message_resource_manager
1462
	 * @return EE_messenger[]
1463
	 */
1464
	protected static function _get_default_messengers_to_generate_on_activation(
1465
		EE_Message_Resource_Manager $message_resource_manager
1466
	) {
1467
		$active_messengers = $message_resource_manager->active_messengers();
1468
		$installed_messengers = $message_resource_manager->installed_messengers();
1469
		$has_activated = $message_resource_manager->get_has_activated_messengers_option();
1470
1471
		$messengers_to_generate = array();
1472
		foreach ( $installed_messengers as $installed_messenger ) {
1473
			//if installed messenger is a messenger that should be activated on install
1474
			//and is not already active
1475
			//and has never been activated
1476
			if (
1477
				! $installed_messenger->activate_on_install
1478
				|| isset( $active_messengers[ $installed_messenger->name ] )
1479
				|| isset( $has_activated[ $installed_messenger->name ] )
1480
			) {
1481
				continue;
1482
			}
1483
			$messengers_to_generate[ $installed_messenger->name ] = $installed_messenger;
1484
		}
1485
		return $messengers_to_generate;
1486
	}
1487
1488
1489
1490
1491
1492
1493
	/**
1494
	 * This simply validates active message types to ensure they actually match installed
1495
	 * message types.  If there's a mismatch then we deactivate the message type and ensure all related db
1496
	 * rows are set inactive.
1497
	 *
1498
	 * Note: Messengers are no longer validated here as of 4.9.0 because they get validated automatically whenever
1499
	 * EE_Messenger_Resource_Manager is constructed.  Message Types are a bit more resource heavy for validation so they
1500
	 * are still handled in here.
1501
	 *
1502
	 * @since 4.3.1
1503
	 *
1504
	 * @return void
1505
	 */
1506
	public static function validate_messages_system() {
1507
		/** @type EE_Message_Resource_Manager $message_resource_manager */
1508
		$message_resource_manager = EE_Registry::instance()->load_lib( 'Message_Resource_Manager' );
1509
		$message_resource_manager->validate_active_message_types_are_installed();
1510
		do_action( 'AHEE__EEH_Activation__validate_messages_system' );
1511
	}
1512
1513
1514
1515
1516
	/**
1517
	 * create_no_ticket_prices_array
1518
	 *
1519
	 * 	@access public
1520
	 * 	@static
1521
	 * 	@return void
1522
	 */
1523
	public static function create_no_ticket_prices_array(){
1524
		// this creates an array for tracking events that have no active ticket prices created
1525
		// this allows us to warn admins of the situation so that it can be corrected
1526
		$espresso_no_ticket_prices = get_option( 'ee_no_ticket_prices', FALSE );
1527
		if ( ! $espresso_no_ticket_prices ) {
1528
			add_option( 'ee_no_ticket_prices', array(), '', FALSE );
1529
		}
1530
	}
1531
1532
1533
1534
	/**
1535
	 * plugin_deactivation
1536
	 *
1537
	 * 	@access public
1538
	 * 	@static
1539
	 * 	@return void
1540
	 */
1541
	public static function plugin_deactivation() {
1542
	}
1543
1544
1545
1546
	/**
1547
	 * Finds all our EE4 custom post types, and deletes them and their associated data
1548
	 * (like post meta or term relations)
1549
	 *
1550
	 * @global wpdb $wpdb
1551
	 * @throws \EE_Error
1552
	 */
1553
	public static function delete_all_espresso_cpt_data(){
1554
		global $wpdb;
1555
		//get all the CPT post_types
1556
		$ee_post_types = array();
1557
		foreach(EE_Registry::instance()->non_abstract_db_models as $model_name){
1558
			if ( method_exists( $model_name, 'instance' )) {
1559
				$model_obj = call_user_func( array( $model_name, 'instance' ));
1560
				if ( $model_obj instanceof EEM_CPT_Base ) {
1561
					$ee_post_types[] = $wpdb->prepare("%s",$model_obj->post_type());
1562
				}
1563
			}
1564
		}
1565
		//get all our CPTs
1566
		$query = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (".implode(",",$ee_post_types).")";
1567
		$cpt_ids = $wpdb->get_col($query);
1568
		//delete each post meta and term relations too
1569
		foreach($cpt_ids as $post_id){
1570
			wp_delete_post($post_id,true);
1571
		}
1572
	}
1573
1574
1575
1576
	/**
1577
	 * plugin_uninstall
1578
	 *
1579
	 * @access public
1580
	 * @static
1581
	 * @param bool $remove_all
1582
	 * @return void
1583
	 */
1584
	public static function delete_all_espresso_tables_and_data( $remove_all = true ) {
1585
		global $wpdb;
1586
		$undeleted_tables = array();
1587
1588
		// load registry
1589
		foreach( EE_Registry::instance()->non_abstract_db_models as $model_name ){
1590
			if ( method_exists( $model_name, 'instance' )) {
1591
				$model_obj = call_user_func( array( $model_name, 'instance' ));
1592
				if ( $model_obj instanceof EEM_Base ) {
1593
					foreach ( $model_obj->get_tables() as $table ) {
1594
						if ( strpos( $table->get_table_name(), 'esp_' )) {
1595
							switch ( EEH_Activation::delete_unused_db_table( $table->get_table_name() )) {
1596
								case false :
1597
									$undeleted_tables[] = $table->get_table_name();
1598
								break;
1599
								case 0 :
1600
									// echo '<h4 style="color:red;">the table : ' . $table->get_table_name() . ' was not deleted  <br /></h4>';
1601
								break;
1602
								default:
1603
									// echo '<h4>the table : ' . $table->get_table_name() . ' was deleted successfully <br /></h4>';
1604
							}
1605
						}
1606
					}
1607
				}
1608
			}
1609
		}
1610
1611
		//there are some tables whose models were removed.
1612
		//they should be removed when removing all EE core's data
1613
		$tables_without_models = array(
1614
			'esp_promotion',
1615
			'esp_promotion_applied',
1616
			'esp_promotion_object',
1617
			'esp_promotion_rule',
1618
			'esp_rule'
1619
		);
1620
		foreach( $tables_without_models as $table ){
1621
			EEH_Activation::delete_db_table_if_empty( $table );
1622
		}
1623
1624
1625
		$wp_options_to_delete = array(
1626
			'ee_no_ticket_prices' => true,
1627
			'ee_active_messengers' => true,
1628
			'ee_has_activated_messenger' => true,
1629
			'ee_flush_rewrite_rules' => true,
1630
			'ee_config' => false,
1631
			'ee_data_migration_current_db_state' => true,
1632
			'ee_data_migration_mapping_' => false,
1633
			'ee_data_migration_script_' => false,
1634
			'ee_data_migrations' => true,
1635
			'ee_dms_map' => false,
1636
			'ee_notices' => true,
1637
			'lang_file_check_' => false,
1638
			'ee_maintenance_mode' => true,
1639
			'ee_ueip_optin' => true,
1640
			'ee_ueip_has_notified' => true,
1641
			'ee_plugin_activation_errors' => true,
1642
			'ee_id_mapping_from' => false,
1643
			'espresso_persistent_admin_notices' => true,
1644
			'ee_encryption_key' => true,
1645
			'pue_force_upgrade_' => false,
1646
			'pue_json_error_' => false,
1647
			'pue_install_key_' => false,
1648
			'pue_verification_error_' => false,
1649
			'pu_dismissed_upgrade_' => false,
1650
			'external_updates-' => false,
1651
			'ee_extra_data' => true,
1652
			'ee_ssn_' => false,
1653
			'ee_rss_' => false,
1654
			'ee_rte_n_tx_' => false,
1655
			'ee_pers_admin_notices' => true,
1656
			'ee_job_parameters_' => false,
1657
			'ee_upload_directories_incomplete' => true,
1658
		);
1659
		if( is_main_site() ) {
1660
			$wp_options_to_delete[ 'ee_network_config' ] = true;
1661
		}
1662
1663
		$undeleted_options = array();
1664
		foreach ( $wp_options_to_delete as $option_name => $no_wildcard ) {
1665
1666
			if( $no_wildcard ){
1667
				if( ! delete_option( $option_name ) ){
1668
					$undeleted_options[] = $option_name;
1669
				}
1670
			}else{
1671
				$option_names_to_delete_from_wildcard = $wpdb->get_col( "SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%$option_name%'" );
1672
				foreach($option_names_to_delete_from_wildcard as $option_name_from_wildcard ){
1673
					if( ! delete_option( $option_name_from_wildcard ) ){
1674
						$undeleted_options[] = $option_name_from_wildcard;
1675
					}
1676
				}
1677
			}
1678
		}
1679
                //also, let's make sure the "ee_config_option_names" wp option stays out by removing the action that adds it
1680
                remove_action( 'shutdown', array( EE_Config::instance(), 'shutdown' ), 10 );
1681
1682
		if ( $remove_all && $espresso_db_update = get_option( 'espresso_db_update' )) {
1683
			$db_update_sans_ee4 = array();
1684
			foreach($espresso_db_update as $version => $times_activated){
1685
				if( (string)$version[0] === '3'){//if its NON EE4
1686
					$db_update_sans_ee4[$version] = $times_activated;
1687
				}
1688
			}
1689
			update_option( 'espresso_db_update', $db_update_sans_ee4 );
1690
		}
1691
1692
		$errors = '';
1693
		if ( ! empty( $undeleted_tables )) {
1694
			$errors .= sprintf(
1695
				__( 'The following tables could not be deleted: %s%s', 'event_espresso' ),
1696
				'<br/>',
1697
				implode( ',<br/>', $undeleted_tables )
1698
			);
1699
		}
1700
		if ( ! empty( $undeleted_options )) {
1701
			$errors .= ! empty( $undeleted_tables ) ? '<br/>' : '';
1702
			$errors .= sprintf(
1703
				__( 'The following wp-options could not be deleted: %s%s', 'event_espresso' ),
1704
				'<br/>',
1705
				implode( ',<br/>', $undeleted_options )
1706
			);
1707
1708
		}
1709
		if ( ! empty( $errors ) ) {
1710
			EE_Error::add_attention( $errors, __FILE__, __FUNCTION__, __LINE__ );
1711
		}
1712
	}
1713
1714
	/**
1715
	 * Checks that the database table exists. Also works on temporary tables (for unit tests mostly).
1716
	 * @global wpdb $wpdb
1717
	 * @param string $table_name with or without $wpdb->prefix
1718
	 * @return boolean
1719
	 */
1720
	public static function table_exists( $table_name ){
1721
		global $wpdb, $EZSQL_ERROR;
1722
		$table_name = EEH_Activation::ensure_table_name_has_prefix( $table_name );
1723
		//ignore if this causes an sql error
1724
		$old_error = $wpdb->last_error;
1725
		$old_suppress_errors = $wpdb->suppress_errors();
1726
		$old_show_errors_value = $wpdb->show_errors( FALSE );
1727
		$ezsql_error_cache = $EZSQL_ERROR;
1728
		$wpdb->get_results( "SELECT * from $table_name LIMIT 1");
1729
		$wpdb->show_errors( $old_show_errors_value );
1730
		$wpdb->suppress_errors( $old_suppress_errors );
1731
		$new_error = $wpdb->last_error;
1732
		$wpdb->last_error = $old_error;
1733
		$EZSQL_ERROR = $ezsql_error_cache;
1734
		if( empty( $new_error ) ){
1735
			return TRUE;
1736
		}else{
1737
			return FALSE;
1738
		}
1739
	}
1740
1741
	/**
1742
	 * Resets the cache on EEH_Activation
1743
	 */
1744
	public static function reset(){
1745
		self::$_default_creator_id = NULL;
1746
		self::$_initialized_db_content_already_in_this_request = false;
1747
	}
1748
}
1749
// End of file EEH_Activation.helper.php
1750
// Location: /helpers/EEH_Activation.core.php
1751