Completed
Branch FET-8284-automagic-dependency-... (a299cf)
by
unknown
556:45 queued 543:10
created

EEH_Activation::reset()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) exit('No direct script access allowed');
2
/**
3
 * Event Espresso
4
 *
5
 * Event Registration and Management Plugin for WordPress
6
 *
7
 * @ package			Event Espresso
8
 * @ author			Seth Shoultes
9
 * @ copyright		(c) 2008-2011 Event Espresso  All Rights Reserved.
10
 * @ license			http://eventespresso.com/support/terms-conditions/   * see Plugin Licensing *
11
 * @ link					http://www.eventespresso.com
12
 * @ version		 	4.0
13
 *
14
 * ------------------------------------------------------------------------
15
 *
16
 * EEH_Activation Helper
17
 *
18
 * @package			Event Espresso
19
 * @subpackage	/helpers/
20
 * @author				Brent Christensen
21
 *
22
 * ------------------------------------------------------------------------
23
 */
24
class EEH_Activation {
25
26
	/**
27
	 * constant used to indicate a cron task is no longer in use
28
	 */
29
	const cron_task_no_longer_in_use = 'no_longer_in_use';
30
31
	/**
32
	 * option name that will indicate whether or not we still
33
	 * need to create EE's folders in the uploads directory
34
	 * (because if EE was installed without file system access, 
35
	 * we need to request credentials before we can create them)
36
	 */
37
	const upload_directories_incomplete_option_name = 'ee_upload_directories_incomplete';
38
	private static $_default_creator_id = null;
39
40
	/**
41
	 * indicates whether or not we've already verified core's default data during this request,
42
	 * because after migrations are done, any addons activated while in maintenance mode
43
	 * will want to setup their own default data, and they might hook into core's default data
44
	 * and trigger core to setup its default data. In which case they might all ask for core to init its default data.
45
	 * This prevents doing that for EVERY single addon.
46
	 * @var boolean
47
	 */
48
	protected static $_initialized_db_content_already_in_this_request = false;
49
50
51
52
	/**
53
	 *    _ensure_table_name_has_prefix
54
	 *
55
	 * @access public
56
	 * @static
57
	 * @param $table_name
58
	 * @return string
59
	 */
60
	public static function ensure_table_name_has_prefix( $table_name ) {
61
		global $wpdb;
62
		return strpos( $table_name, $wpdb->prefix ) === 0 ? $table_name : $wpdb->prefix . $table_name;
63
	}
64
65
66
	/**
67
	 * 	system_initialization
68
	 * 	ensures the EE configuration settings are loaded with at least default options set
69
	 * 	and that all critical EE pages have been generated with the appropriate shortcodes in place
70
	 *
71
	 * 	@access public
72
	 * 	@static
73
	 * 	@return void
74
	 */
75
	public static function system_initialization() {
76
		EEH_Activation::reset_and_update_config();
77
		//which is fired BEFORE activation of plugin anyways
78
		EEH_Activation::verify_default_pages_exist();
79
	}
80
81
82
83
	/**
84
	 * Sets the database schema and creates folders. This should
85
	 * be called on plugin activation and reactivation
86
	 * @return boolean success, whether the database and folders are setup properly
87
	 */
88
	public static function initialize_db_and_folders(){
89
		$good_filesystem = EEH_Activation::create_upload_directories();
90
		$good_db = EEH_Activation::create_database_tables();
91
		return $good_filesystem && $good_db;
92
	}
93
94
95
96
	/**
97
	 * assuming we have an up-to-date database schema, this will populate it
98
	 * with default and initial data. This should be called
99
	 * upon activation of a new plugin, reactivation, and at the end
100
	 * of running migration scripts
101
	 */
102
	public static function initialize_db_content(){
103
		//let's avoid doing all this logic repeatedly, especially when addons are requesting it
104
		if( EEH_Activation::$_initialized_db_content_already_in_this_request ) {
105
			return;
106
		}
107
		EEH_Activation::$_initialized_db_content_already_in_this_request = true;
108
109
		EEH_Activation::initialize_system_questions();
110
		EEH_Activation::insert_default_status_codes();
111
		EEH_Activation::generate_default_message_templates();
112
		EEH_Activation::create_no_ticket_prices_array();
113
		EE_Registry::instance()->CAP->init_caps();
114
115
		EEH_Activation::validate_messages_system();
116
		EEH_Activation::insert_default_payment_methods();
117
		//in case we've
118
		EEH_Activation::remove_cron_tasks();
119
		EEH_Activation::create_cron_tasks();
120
		//also, check for CAF default db content
121
		do_action( 'AHEE__EEH_Activation__initialize_db_content' );
122
		//also: EEM_Gateways::load_all_gateways() outputs a lot of success messages
123
		//which users really won't care about on initial activation
124
		EE_Error::overwrite_success();
125
	}
126
127
128
129
130
	/**
131
	 * Returns an array of cron tasks. Array values are the actions fired by the cron tasks (the "hooks"),
132
	 * values are the frequency (the "recurrence"). See http://codex.wordpress.org/Function_Reference/wp_schedule_event
133
	 * If the cron task should NO longer be used, it should have a value of EEH_Activation::cron_task_no_longer_in_use (null)
134
	 *
135
	 * @param string $which_to_include can be 'current' (ones that are currently in use),
136
	 *                          'old' (only returns ones that should no longer be used),or 'all',
137
	 * @return array
138
	 * @throws \EE_Error
139
	 */
140
	public static function get_cron_tasks( $which_to_include ) {
141
		$cron_tasks = apply_filters(
142
			'FHEE__EEH_Activation__get_cron_tasks',
143
			array(
144
				'AHEE__EE_Cron_Tasks__clean_up_junk_transactions' => 'hourly',
145
//				'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions' => EEH_Activation::cron_task_no_longer_in_use, actually this is still in use
146
				'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
147
			)
148
		);
149
		if( $which_to_include === 'all' ) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
150
			//leave as-is
151
		}elseif( $which_to_include === 'old' ) {
152
			$cron_tasks = array_filter( $cron_tasks, function ( $value ) {
153
				return $value === EEH_Activation::cron_task_no_longer_in_use;
154
			});
155
		}elseif( $which_to_include === 'current' ) {
156
			$cron_tasks = array_filter( $cron_tasks );
157
		}elseif( WP_DEBUG ) {
158
			throw new EE_Error( sprintf( __( 'Invalidate argument of "%1$s" passed to EEH_Activation::get_cron_tasks. Valid values are "all", "old" and "current".', 'event_espresso' ), $which_to_include ) );
159
		}else{
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
160
			//leave as-is
161
		}
162
		return $cron_tasks;
163
	}
164
165
	/**
166
	 * Ensure cron tasks are setup (the removal of crons should be done by remove_crons())
167
	 */
168
	public static function create_cron_tasks() {
169
170
		foreach( EEH_Activation::get_cron_tasks( 'current' ) as $hook_name => $frequency ) {
171
			if( ! wp_next_scheduled( $hook_name ) ) {
172
				wp_schedule_event( time(), $frequency, $hook_name );
173
			}
174
		}
175
176
	}
177
178
	/**
179
	 * Remove the currently-existing and now-removed cron tasks.
180
	 * @param boolean $remove_all whether to only remove the old ones, or remove absolutely ALL the EE ones
181
	 */
182
	public static function remove_cron_tasks( $remove_all = true ) {
183
		$cron_tasks_to_remove = $remove_all ? 'all' : 'old';
184
		$crons = _get_cron_array();
185
		$crons = is_array( $crons ) ? $crons : array();
186
		/* reminder that $crons looks like: top-level keys are timestamps,
187
		 * and their values are arrays.
188
		 * The 2nd level arrays have keys with each of the cron task hooknames to run at that time
189
		 * and their values are arrays.
190
		 * The 3rd level level arrays are keys which are hashes of the cron task's arguments,
191
		 *  and their values are the UN-hashed arguments
192
		 * eg
193
		 * array (size=13)
194
		 *		1429903276 =>
195
		 *		  array (size=1)
196
		 *			'AHEE__EE_Cron_Tasks__update_transaction_with_payment' =>
197
		 *			  array (size=1)
198
		 *				'561299d6e42c8e079285870ade0e47e6' =>
199
		 *				  array (size=2)
200
		 *					...
201
		 *      ...
202
		 */
203
		foreach( EEH_Activation::get_cron_tasks( $cron_tasks_to_remove ) as $hook_name => $frequency ) {
204
			foreach( $crons as $timestamp => $hooks_to_fire_at_time ) {
205
				if ( array_key_exists( $hook_name, $hooks_to_fire_at_time ) )  {
206
					unset( $crons[ $timestamp ][ $hook_name ] );
207
				}
208
			}
209
		}
210
		_set_cron_array( $crons );
211
	}
212
213
214
215
	/**
216
	 * 	CPT_initialization
217
	 *	registers all EE CPTs ( Custom Post Types ) then flushes rewrite rules so that all endpoints exist
218
	 *
219
	 * 	@access public
220
	 * 	@static
221
	 * 	@return void
222
	 */
223
	public static function CPT_initialization() {
224
		// register Custom Post Types
225
		EE_Registry::instance()->load_core( 'Register_CPTs' );
226
		flush_rewrite_rules();
227
	}
228
229
230
231
	/**
232
	 * 	reset_and_update_config
233
	 *
234
	 * The following code was moved over from EE_Config so that it will no longer run on every request.
235
	 * If there is old calendar config data saved, then it will get converted on activation.
236
	 * This was basically a DMS before we had DMS's, and will get removed after a few more versions.
237
	 *
238
	 * 	@access public
239
	 * 	@static
240
	 * 	@return void
241
	 */
242
	public static function reset_and_update_config() {
243
		do_action( 'AHEE__EE_Config___load_core_config__start', array( 'EEH_Activation', 'load_calendar_config' ) );
244
		add_filter( 'FHEE__EE_Config___load_core_config__config_settings', array( 'EEH_Activation', 'migrate_old_config_data' ), 10, 3 );
245
		//EE_Config::reset();
246
	}
247
248
249
	/**
250
	 *    load_calendar_config
251
	 *
252
	 * @access    public
253
	 * @return    stdClass
254
	 */
255
	public static function load_calendar_config() {
256
		// grab array of all plugin folders and loop thru it
257
		$plugins = glob( WP_PLUGIN_DIR . DS . '*', GLOB_ONLYDIR );
258
		if ( empty( $plugins ) ) {
259
			return;
260
		}
261
		foreach ( $plugins as $plugin_path ) {
262
			// grab plugin folder name from path
263
			$plugin = basename( $plugin_path );
264
			// drill down to Espresso plugins
265
			if ( strpos( $plugin, 'espresso' ) !== FALSE || strpos( $plugin, 'Espresso' ) !== FALSE || strpos( $plugin, 'ee4' ) !== FALSE || strpos( $plugin, 'EE4' ) !== FALSE ) {
266
				// then to calendar related plugins
267
				if ( strpos( $plugin, 'calendar' ) !== FALSE ) {
268
					// this is what we are looking for
269
					$calendar_config = $plugin_path . DS . 'EE_Calendar_Config.php';
270
					// does it exist in this folder ?
271
					if ( is_readable( $calendar_config )) {
272
						// YEAH! let's load it
273
						require_once( $calendar_config );
274
					}
275
				}
276
			}
277
		}
278
	}
279
280
281
	/**
282
	 *    _migrate_old_config_data
283
	 *
284
	 * @access    public
285
	 * @param array      $settings
286
	 * @param string     $config
287
	 * @param \EE_Config $EE_Config
288
	 * @return \stdClass
289
	 */
290
	public static function migrate_old_config_data( $settings = array(), $config = '', EE_Config $EE_Config ) {
291
		$convert_from_array = array( 'addons' );
292
		// in case old settings were saved as an array
293
		if ( is_array( $settings ) && in_array( $config, $convert_from_array )) {
294
			// convert existing settings to an object
295
			$config_array = $settings;
296
			$settings = new stdClass();
297
			foreach ( $config_array as $key => $value ){
298
				if ( $key == 'calendar' && class_exists( 'EE_Calendar_Config' )) {
299
					$EE_Config->set_config( 'addons', 'EE_Calendar', 'EE_Calendar_Config', $value );
300
				} else {
301
					$settings->$key = $value;
302
				}
303
			}
304
			add_filter( 'FHEE__EE_Config___load_core_config__update_espresso_config', '__return_true' );
305
		}
306
		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...
307
	}
308
309
310
311
	/**
312
	 * deactivate_event_espresso
313
	 *
314
	 * 	@access public
315
	 * 	@static
316
	 * 	@return void
317
	 */
318
	public static function deactivate_event_espresso() {
319
		// check permissions
320
		if ( current_user_can( 'activate_plugins' )) {
321
			deactivate_plugins( EE_PLUGIN_BASENAME, TRUE );
322
		}
323
	}
324
325
326
327
328
329
	/**
330
	 * verify_default_pages_exist
331
	 *
332
	 * 	@access public
333
	 * 	@static
334
	 * 	@return void
335
	 */
336
	public static function verify_default_pages_exist() {
337
338
		$critical_page_problem = FALSE;
339
340
		$critical_pages = array(
341
			array(
342
				'id' =>'reg_page_id',
343
				'name' => __( 'Registration Checkout', 'event_espresso' ),
344
				'post' => NULL,
345
				'code' => 'ESPRESSO_CHECKOUT'
346
			),
347
			array(
348
				'id' => 'txn_page_id',
349
				'name' => __( 'Transactions', 'event_espresso' ),
350
				'post' => NULL,
351
				'code' => 'ESPRESSO_TXN_PAGE'
352
			),
353
			array(
354
				'id' => 'thank_you_page_id',
355
				'name' => __( 'Thank You', 'event_espresso' ),
356
				'post' => NULL,
357
				'code' => 'ESPRESSO_THANK_YOU'
358
			),
359
			array(
360
				'id' => 'cancel_page_id',
361
				'name' => __( 'Registration Cancelled', 'event_espresso' ),
362
				'post' => NULL,
363
				'code' => 'ESPRESSO_CANCELLED'
364
			),
365
		);
366
367
		foreach ( $critical_pages as $critical_page ) {
368
			// is critical page ID set in config ?
369
			if ( EE_Registry::instance()->CFG->core->$critical_page['id'] !== FALSE ) {
370
				// attempt to find post by ID
371
				$critical_page['post'] = get_post( EE_Registry::instance()->CFG->core->$critical_page['id'] );
372
			}
373
			// no dice?
374
			if ( $critical_page['post'] == NULL ) {
375
				// attempt to find post by title
376
				$critical_page['post'] = self::get_page_by_ee_shortcode( $critical_page['code'] );
377
				// still nothing?
378
				if ( $critical_page['post'] == NULL ) {
379
					$critical_page = EEH_Activation::create_critical_page( $critical_page );
380
					// REALLY? Still nothing ??!?!?
381
					if ( $critical_page['post'] == NULL ) {
382
						$msg = __( 'The Event Espresso critical page configuration settings could not be updated.', 'event_espresso' );
383
						EE_Error::add_error( $msg, __FILE__, __FUNCTION__, __LINE__ );
384
						break;
385
					}
386
				}
387
			}
388
			// track post_shortcodes
389
			if ( $critical_page['post'] ) {
390
				EEH_Activation::_track_critical_page_post_shortcodes( $critical_page );
391
			}
392
			// check that Post ID matches critical page ID in config
393
			if ( isset( $critical_page['post']->ID ) && $critical_page['post']->ID != EE_Registry::instance()->CFG->core->$critical_page['id'] ) {
394
				//update Config with post ID
395
				EE_Registry::instance()->CFG->core->$critical_page['id'] = $critical_page['post']->ID;
396 View Code Duplication
				if ( ! EE_Config::instance()->update_espresso_config( FALSE, FALSE ) ) {
397
					$msg = __( 'The Event Espresso critical page configuration settings could not be updated.', 'event_espresso' );
398
					EE_Error::add_error( $msg, __FILE__, __FUNCTION__, __LINE__ );
399
				}
400
			}
401
402
			$critical_page_problem =  ! isset( $critical_page['post']->post_status ) || $critical_page['post']->post_status != 'publish' || strpos( $critical_page['post']->post_content, $critical_page['code'] ) === FALSE ? TRUE : $critical_page_problem;
403
404
		}
405
406
		if ( $critical_page_problem ) {
407
			$msg = sprintf(
408
				__('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' ),
409
				'<a href="' . admin_url('admin.php?page=espresso_general_settings&action=critical_pages') . '">' . __('Event Espresso Critical Pages Settings', 'event_espresso') . '</a>'
410
			);
411
			EE_Error::add_persistent_admin_notice( 'critical_page_problem', $msg );
412
		}
413
414
		if ( EE_Error::has_notices() ) {
415
			EE_Error::get_notices( FALSE, TRUE, TRUE );
416
		}
417
418
	}
419
420
	/**
421
	 * Returns the first post which uses the specified shortcode
422
	 * @param string $ee_shortcode usually one of the critical pages shortcodes, eg
423
	 * ESPRESSO_THANK_YOU. So we will search fora post with the content "[ESPRESSO_THANK_YOU"
424
	 * (we don't search for the closing shortcode bracket because they might have added
425
	 * parameter to the shortcode
426
	 * @return WP_Post or NULl
427
	 */
428
	public static function get_page_by_ee_shortcode($ee_shortcode){
429
		global $wpdb;
430
		$shortcode_and_opening_bracket = '['.$ee_shortcode;
431
		$post_id = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_content LIKE '%$shortcode_and_opening_bracket%' LIMIT 1");
432
		if($post_id){
433
			return get_post($post_id);
434
		}else{
435
			return NULL;
436
		}
437
438
//		return $post_id;
439
	}
440
441
442
443
	/**
444
	 *    This function generates a post for critical espresso pages
445
	 *
446
	 * @access public
447
	 * @static
448
	 * @param array $critical_page
449
	 * @return array
450
	 */
451
	public static function create_critical_page( $critical_page ) {
452
453
		$post_args = array(
454
			'post_title' => $critical_page['name'],
455
			'post_status' => 'publish',
456
			'post_type' => 'page',
457
			'comment_status' => 'closed',
458
			'post_content' => '[' . $critical_page['code'] . ']'
459
		);
460
461
		$post_id = wp_insert_post( $post_args );
462
		if ( ! $post_id ) {
463
			$msg = sprintf(
464
				__( 'The Event Espresso  critical page entitled "%s" could not be created.', 'event_espresso' ),
465
				$critical_page['name']
466
			);
467
			EE_Error::add_error( $msg, __FILE__, __FUNCTION__, __LINE__ );
468
			return $critical_page;
469
		}
470
		// get newly created post's details
471
		if ( ! $critical_page['post'] = get_post( $post_id )) {
472
			$msg = sprintf(
473
				__( 'The Event Espresso critical page entitled "%s" could not be retrieved.', 'event_espresso' ),
474
				$critical_page['name']
475
			);
476
			EE_Error::add_error( $msg, __FILE__, __FUNCTION__, __LINE__ );
477
		}
478
479
		return $critical_page;
480
481
	}
482
483
484
485
486
487
	/**
488
	 *    This function adds a critical page's shortcode to the post_shortcodes array
489
	 *
490
	 * @access private
491
	 * @static
492
	 * @param array $critical_page
493
	 * @return void
494
	 */
495
	private static function _track_critical_page_post_shortcodes( $critical_page = array() ) {
496
		// check the goods
497
		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...
498
			$msg = sprintf(
499
				__( 'The Event Espresso critical page shortcode for the page %s can not be tracked because it is not a WP_Post object.', 'event_espresso' ),
500
				$critical_page['name']
501
			);
502
			EE_Error::add_error( $msg, __FILE__, __FUNCTION__, __LINE__ );
503
			return;
504
		}
505
		// map shortcode to post
506
		EE_Registry::instance()->CFG->core->post_shortcodes[ $critical_page['post']->post_name ][ $critical_page['code'] ] = $critical_page['post']->ID;
507
		// and make sure it's NOT added to the WP "Posts Page"
508
		// name of the WP Posts Page
509
		$posts_page = EE_Registry::instance()->CFG->get_page_for_posts();
510
		if ( isset( EE_Registry::instance()->CFG->core->post_shortcodes[ $posts_page ] )) {
511
			unset( EE_Registry::instance()->CFG->core->post_shortcodes[ $posts_page ][ $critical_page['code'] ] );
512
		}
513
		if ( $posts_page != 'posts' && isset( EE_Registry::instance()->CFG->core->post_shortcodes['posts'] )) {
514
			unset( EE_Registry::instance()->CFG->core->post_shortcodes['posts'][ $critical_page['code'] ] );
515
		}
516
		// update post_shortcode CFG
517
		if ( ! EE_Config::instance()->update_espresso_config( FALSE, FALSE )) {
518
			$msg = sprintf(
519
				__( 'The Event Espresso critical page shortcode for the %s page could not be configured properly.', 'event_espresso' ),
520
				$critical_page['name']
521
			);
522
			EE_Error::add_error( $msg, __FILE__, __FUNCTION__, __LINE__ );
523
		}
524
	}
525
526
527
528
	/**
529
	 * Tries to find the oldest admin for this site.  If there are no admins for this site then return NULL.
530
	 * The role being used to check is filterable.
531
	 *
532
	 * @since  4.6.0
533
	 * @global WPDB $wpdb
534
	 *
535
	 * @return mixed null|int WP_user ID or NULL
536
	 */
537
	public static function get_default_creator_id() {
538
		global $wpdb;
539
540
		if ( ! empty( self::$_default_creator_id ) ) {
541
			return self::$_default_creator_id;
542
		}/**/
543
544
		$role_to_check = apply_filters( 'FHEE__EEH_Activation__get_default_creator_id__role_to_check', 'administrator' );
545
546
		//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.
547
		$pre_filtered_id = apply_filters( 'FHEE__EEH_Activation__get_default_creator_id__pre_filtered_id', false, $role_to_check );
548
		if ( $pre_filtered_id !== false ) {
549
			return (int) $pre_filtered_id;
550
		}
551
552
		$capabilities_key = EEH_Activation::ensure_table_name_has_prefix( 'capabilities' );
553
		$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 . '%' );
554
		$user_id = $wpdb->get_var( $query );
555
		 $user_id = apply_filters( 'FHEE__EEH_Activation_Helper__get_default_creator_id__user_id', $user_id );
556
		 if ( $user_id && intval( $user_id ) ) {
557
		 	self::$_default_creator_id =  intval( $user_id );
558
		 	return self::$_default_creator_id;
559
		 } else {
560
		 	return NULL;
561
		 }
562
	}
563
564
565
566
567
568
	/**
569
	 * 	used by EE and EE addons during plugin activation
570
	 *
571
	 * 	@access public
572
	 * 	@static
573
	 * @param string $table_name without the $wpdb->prefix
574
	 * @param string $sql SQL for creating the table (contents between brackets in an SQL create table query)
575
	 * @param string $engine like 'ENGINE=MyISAM' or 'ENGINE=InnoDB'
576
	 * @param boolean $drop_pre_existing_table set to TRUE when you want to make SURE the table is completely empty
577
	 * and new once this function is done (ie, you really do want to CREATE a table, and
578
	 * expect it to be empty once you're done)
579
	 * leave as FALSE when you just want to verify the table exists and matches this definition (and if it
580
	 * HAS data in it you want to leave it be)
581
	 * 	@return void
582
	 * @throws EE_Error if there are database errors
583
	 */
584
	public static function create_table( $table_name, $sql, $engine = 'ENGINE=MyISAM ', $drop_pre_existing_table = false ) {
585
		if( apply_filters( 'FHEE__EEH_Activation__create_table__short_circuit', FALSE, $table_name, $sql ) ){
586
			return;
587
		}
588
		do_action( 'AHEE_log', __FILE__, __FUNCTION__, '' );
589
		if ( ! function_exists( 'dbDelta' )) {
590
			require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
591
		}
592
		/** @var WPDB $wpdb */
593
		global $wpdb;
594
		$wp_table_name = EEH_Activation::ensure_table_name_has_prefix( $table_name );
595
		// do we need to first delete an existing version of this table ?
596
		if ( $drop_pre_existing_table && EEH_Activation::table_exists( $wp_table_name ) ){
597
			// ok, delete the table... but ONLY if it's empty
598
			$deleted_safely = EEH_Activation::delete_db_table_if_empty( $wp_table_name );
599
			// table is NOT empty, are you SURE you want to delete this table ???
600
			if ( ! $deleted_safely && defined( 'EE_DROP_BAD_TABLES' ) && EE_DROP_BAD_TABLES ){
601
				EEH_Activation::delete_unused_db_table( $wp_table_name );
602
			} else if ( ! $deleted_safely ) {
603
				// so we should be more cautious rather than just dropping tables so easily
604
				EE_Error::add_persistent_admin_notice(
605
						'bad_table_' . $wp_table_name . '_detected',
606
						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' ),
607
								$wp_table_name,
608
								"<pre>define( 'EE_DROP_BAD_TABLES', TRUE );</pre>",
609
								'<b>wp-config.php</b>',
610
								'<br/>'),
611
								TRUE );
612
			}
613
		}
614
		// does $sql contain valid column information? ( LPT: https://regex101.com/ is great for working out regex patterns )
615
		if ( preg_match( '((((.*?))(,\s))+)', $sql, $valid_column_data ) ) {
616
			$SQL = "CREATE TABLE $wp_table_name ( $sql ) $engine DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;";
617
			//get $wpdb to echo errors, but buffer them. This way at least WE know an error
618
			//happened. And then we can choose to tell the end user
619
			$old_show_errors_policy = $wpdb->show_errors( TRUE );
620
			$old_error_suppression_policy = $wpdb->suppress_errors( FALSE );
621
			ob_start();
622
			dbDelta( $SQL );
623
			$output = ob_get_contents();
624
			ob_end_clean();
625
			$wpdb->show_errors( $old_show_errors_policy );
626
			$wpdb->suppress_errors( $old_error_suppression_policy );
627
			if( ! empty( $output ) ){
628
				throw new EE_Error( $output	);
629
			}
630
		} else {
631
			throw new EE_Error(
632
				sprintf(
633
					__( 'The following table creation SQL does not contain valid information about the table columns: %1$s %2$s', 'event_espresso' ),
634
					'<br />',
635
					$sql
636
				)
637
			);
638
		}
639
640
	}
641
642
643
644
	/**
645
	 *    add_column_if_it_doesn't_exist
646
	 *    Checks if this column already exists on the specified table. Handy for addons which want to add a column
647
	 *
648
	 * @access public
649
	 * @static
650
	 * @param string $table_name  (without "wp_", eg "esp_attendee"
651
	 * @param string $column_name
652
	 * @param string $column_info if your SQL were 'ALTER TABLE table_name ADD price VARCHAR(10)', this would be 'VARCHAR(10)'
653
	 * @return bool|int
654
	 */
655
	public static function add_column_if_it_doesnt_exist($table_name,$column_name,$column_info='INT UNSIGNED NOT NULL'){
656
		if( apply_filters( 'FHEE__EEH_Activation__add_column_if_it_doesnt_exist__short_circuit', FALSE ) ){
657
			return FALSE;
658
		}
659
		global $wpdb;
660
		$full_table_name= EEH_Activation::ensure_table_name_has_prefix( $table_name );
661
		$fields = self::get_fields_on_table($table_name);
662
		if (!in_array($column_name, $fields)){
663
			$alter_query="ALTER TABLE $full_table_name ADD $column_name $column_info";
664
			//echo "alter query:$alter_query";
665
			return $wpdb->query($alter_query);
666
		}
667
		return TRUE;
668
	}
669
670
671
672
673
	/**
674
	 * get_fields_on_table
675
	 * Gets all the fields on the database table.
676
	 *
677
	 * 	@access public
678
	 * 	@static
679
	 * 	@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...
680
	 * 	@return array of database column names
681
	 */
682
	public static function get_fields_on_table( $table_name = NULL ) {
683
		global $wpdb;
684
		$table_name= EEH_Activation::ensure_table_name_has_prefix( $table_name );
685
		if ( ! empty( $table_name )) {
686
			$columns = $wpdb->get_results("SHOW COLUMNS FROM $table_name ");
687
			if ($columns !== FALSE) {
688
				$field_array = array();
689
				foreach($columns as $column ){
690
					$field_array[] = $column->Field;;
691
				}
692
				return $field_array;
693
			}
694
		}
695
		return FALSE;
696
	}
697
698
699
700
	/**
701
	 * db_table_is_empty
702
	 *
703
	 * @access public
704
	 * @static
705
	 * @param string $table_name
706
	 * @return bool
707
	 */
708
	public static function db_table_is_empty( $table_name ) {
709
		global $wpdb;
710
		$table_name = EEH_Activation::ensure_table_name_has_prefix( $table_name );
711
		if ( EEH_Activation::table_exists( $table_name ) ) {
712
			$count = $wpdb->get_var( "SELECT COUNT(*) FROM $table_name" );
713
			return absint( $count ) === 0 ? true : false;
714
		}
715
		return false;
716
	}
717
718
719
720
	/**
721
	 * delete_db_table_if_empty
722
	 *
723
	 * @access public
724
	 * @static
725
	 * @param string $table_name
726
	 * @return bool | int
727
	 */
728
	public static function delete_db_table_if_empty( $table_name ) {
729
		if ( EEH_Activation::db_table_is_empty( $table_name ) ) {
730
			return EEH_Activation::delete_unused_db_table( $table_name );
731
		}
732
		return false;
733
	}
734
735
736
737
	/**
738
	 * delete_unused_db_table
739
	 *
740
	 * @access public
741
	 * @static
742
	 * @param string $table_name
743
	 * @return bool | int
744
	 */
745
	public static function delete_unused_db_table( $table_name ) {
746
		global $wpdb;
747
		if ( EEH_Activation::table_exists( $table_name ) ) {
748
			$table_name = EEH_Activation::ensure_table_name_has_prefix( $table_name );
749
			return $wpdb->query( "DROP TABLE IF EXISTS $table_name" );
750
		}
751
		return false;
752
	}
753
754
755
756
	/**
757
	 * drop_index
758
	 *
759
	 * @access public
760
	 * @static
761
	 * @param string $table_name
762
	 * @param string $index_name
763
	 * @return bool | int
764
	 */
765
	public static function drop_index( $table_name, $index_name ) {
766
		if( apply_filters( 'FHEE__EEH_Activation__drop_index__short_circuit', FALSE ) ){
767
			return FALSE;
768
		}
769
		global $wpdb;
770
		$table_name = EEH_Activation::ensure_table_name_has_prefix( $table_name );
771
		$index_exists_query = "SHOW INDEX FROM $table_name WHERE Key_name = '$index_name'";
772
		if (
773
			$wpdb->get_var( "SHOW TABLES LIKE '$table_name'" ) == $table_name
774
			&& $wpdb->get_var( $index_exists_query ) == $table_name //using get_var with the $index_exists_query returns the table's name
775
		) {
776
			return $wpdb->query( "ALTER TABLE $table_name DROP INDEX $index_name" );
777
		}
778
		return TRUE;
779
	}
780
781
782
783
	/**
784
	 * create_database_tables
785
	 *
786
	 * @access public
787
	 * @static
788
	 * @throws EE_Error
789
	 * @return boolean success (whether database is setup properly or not)
790
	 */
791
	public static function create_database_tables() {
792
		EE_Registry::instance()->load_core( 'Data_Migration_Manager' );
793
		//find the migration script that sets the database to be compatible with the code
794
		$dms_name = EE_Data_Migration_Manager::instance()->get_most_up_to_date_dms();
795
		if( $dms_name ){
796
			$current_data_migration_script = EE_Registry::instance()->load_dms( $dms_name );
797
			$current_data_migration_script->set_migrating( false );
798
			$current_data_migration_script->schema_changes_before_migration();
799
			$current_data_migration_script->schema_changes_after_migration();
800
			if( $current_data_migration_script->get_errors() ){
801
				if( WP_DEBUG ){
802
					foreach( $current_data_migration_script->get_errors() as $error ){
803
						EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__ );
804
					}
805
				}else{
806
					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' ) );
807
				}
808
				return false;
809
			}
810
			EE_Data_Migration_Manager::instance()->update_current_database_state_to();
811
		}else{
812
			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__);
813
			return false;
814
		}
815
		return true;
816
	}
817
818
819
820
821
822
	/**
823
	 * initialize_system_questions
824
	 *
825
	 * 	@access public
826
	 * 	@static
827
	 * 	@return void
828
	 */
829
	public static function initialize_system_questions() {
830
		// QUESTION GROUPS
831
		global $wpdb;
832
		$table_name = EEH_Activation::ensure_table_name_has_prefix( 'esp_question_group' );
833
		$SQL = "SELECT QSG_system FROM $table_name WHERE QSG_system != 0";
834
		// what we have
835
		$question_groups = $wpdb->get_col( $SQL );
836
		// check the response
837
		$question_groups = is_array( $question_groups ) ? $question_groups : array();
838
		// what we should have
839
		$QSG_systems = array( 1, 2 );
840
		// loop thru what we should have and compare to what we have
841
		foreach ( $QSG_systems as $QSG_system ) {
842
			// reset values array
843
			$QSG_values = array();
844
			// 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)
845
			if ( ! in_array( "$QSG_system", $question_groups )) {
846
				// add it
847
				switch ( $QSG_system ) {
848
849 View Code Duplication
					case 1:
850
							$QSG_values = array(
851
									'QSG_name' => __( 'Personal Information', 'event_espresso' ),
852
									'QSG_identifier' => 'personal-information-' . time(),
853
									'QSG_desc' => '',
854
									'QSG_order' => 1,
855
									'QSG_show_group_name' => 1,
856
									'QSG_show_group_desc' => 1,
857
									'QSG_system' => EEM_Question_Group::system_personal,
858
									'QSG_deleted' => 0
859
								);
860
						break;
861
862 View Code Duplication
					case 2:
863
							$QSG_values = array(
864
									'QSG_name' => __( 'Address Information','event_espresso' ),
865
									'QSG_identifier' => 'address-information-' . time(),
866
									'QSG_desc' => '',
867
									'QSG_order' => 2,
868
									'QSG_show_group_name' => 1,
869
									'QSG_show_group_desc' => 1,
870
									'QSG_system' => EEM_Question_Group::system_address,
871
									'QSG_deleted' => 0
872
								);
873
						break;
874
875
				}
876
				// make sure we have some values before inserting them
877
				if ( ! empty( $QSG_values )) {
878
					// insert system question
879
					$wpdb->insert(
880
						$table_name,
881
						$QSG_values,
882
						array('%s', '%s', '%s', '%d', '%d', '%d', '%d', '%d' )
883
					);
884
					$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...
885
				}
886
			}
887
		}
888
889
890
891
		// QUESTIONS
892
		global $wpdb;
893
		$table_name = EEH_Activation::ensure_table_name_has_prefix( 'esp_question' );
894
		$SQL = "SELECT QST_system FROM $table_name WHERE QST_system != ''";
895
		// what we have
896
		$questions = $wpdb->get_col( $SQL );
897
		// what we should have
898
		$QST_systems = array(
899
			'fname',
900
			'lname',
901
			'email',
902
			'address',
903
			'address2',
904
			'city',
905
			'state',
906
			'country',
907
			'zip',
908
			'phone'
909
		);
910
		$order_for_group_1 = 1;
911
		$order_for_group_2 = 1;
912
		// loop thru what we should have and compare to what we have
913
		foreach ( $QST_systems as $QST_system ) {
914
			// reset values array
915
			$QST_values = array();
916
			// if we don't have what we should have
917
			if ( ! in_array( $QST_system, $questions )) {
918
				// add it
919
				switch ( $QST_system ) {
920
921 View Code Duplication
					case 'fname':
922
							$QST_values = array(
923
									'QST_display_text' => __( 'First Name', 'event_espresso' ),
924
									'QST_admin_label' => __( 'First Name - System Question', 'event_espresso' ),
925
									'QST_system' => 'fname',
926
									'QST_type' => 'TEXT',
927
									'QST_required' => 1,
928
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
929
									'QST_order' => 1,
930
									'QST_admin_only' => 0,
931
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
932
									'QST_wp_user' => self::get_default_creator_id(),
933
									'QST_deleted' => 0
934
								);
935
						break;
936
937 View Code Duplication
					case 'lname':
938
							$QST_values = array(
939
									'QST_display_text' => __( 'Last Name', 'event_espresso' ),
940
									'QST_admin_label' => __( 'Last Name - System Question', 'event_espresso' ),
941
									'QST_system' => 'lname',
942
									'QST_type' => 'TEXT',
943
									'QST_required' => 1,
944
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
945
									'QST_order' => 2,
946
									'QST_admin_only' => 0,
947
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
948
									'QST_wp_user' => self::get_default_creator_id(),
949
									'QST_deleted' => 0
950
								);
951
						break;
952
953 View Code Duplication
					case 'email':
954
							$QST_values = array(
955
									'QST_display_text' => __( 'Email Address', 'event_espresso' ),
956
									'QST_admin_label' => __( 'Email Address - System Question', 'event_espresso' ),
957
									'QST_system' => 'email',
958
									'QST_type' => 'TEXT',
959
									'QST_required' => 1,
960
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
961
									'QST_order' => 3,
962
									'QST_admin_only' => 0,
963
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
964
									'QST_wp_user' => self::get_default_creator_id(),
965
									'QST_deleted' => 0
966
								);
967
						break;
968
969 View Code Duplication
					case 'address':
970
							$QST_values = array(
971
									'QST_display_text' => __( 'Address', 'event_espresso' ),
972
									'QST_admin_label' => __( 'Address - System Question', 'event_espresso' ),
973
									'QST_system' => 'address',
974
									'QST_type' => 'TEXT',
975
									'QST_required' => 0,
976
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
977
									'QST_order' => 4,
978
									'QST_admin_only' => 0,
979
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
980
									'QST_wp_user' => self::get_default_creator_id(),
981
									'QST_deleted' => 0
982
								);
983
						break;
984
985 View Code Duplication
					case 'address2':
986
							$QST_values = array(
987
									'QST_display_text' => __( 'Address2', 'event_espresso' ),
988
									'QST_admin_label' => __( 'Address2 - System Question', 'event_espresso' ),
989
									'QST_system' => 'address2',
990
									'QST_type' => 'TEXT',
991
									'QST_required' => 0,
992
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
993
									'QST_order' => 5,
994
									'QST_admin_only' => 0,
995
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
996
									'QST_wp_user' => self::get_default_creator_id(),
997
									'QST_deleted' => 0
998
								);
999
						break;
1000
1001 View Code Duplication
					case 'city':
1002
							$QST_values = array(
1003
									'QST_display_text' => __( 'City', 'event_espresso' ),
1004
									'QST_admin_label' => __( 'City - System Question', 'event_espresso' ),
1005
									'QST_system' => 'city',
1006
									'QST_type' => 'TEXT',
1007
									'QST_required' => 0,
1008
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
1009
									'QST_order' => 6,
1010
									'QST_admin_only' => 0,
1011
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
1012
									'QST_wp_user' => self::get_default_creator_id(),
1013
									'QST_deleted' => 0
1014
								);
1015
						break;
1016
1017 View Code Duplication
					case 'state':
1018
							$QST_values = array(
1019
									'QST_display_text' => __( 'State/Province', 'event_espresso' ),
1020
									'QST_admin_label' => __( 'State/Province - System Question', 'event_espresso' ),
1021
									'QST_system' => 'state',
1022
									'QST_type' => 'STATE',
1023
									'QST_required' => 0,
1024
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
1025
									'QST_order' => 7,
1026
									'QST_admin_only' => 0,
1027
									'QST_wp_user' => self::get_default_creator_id(),
1028
									'QST_deleted' => 0
1029
								);
1030
						break;
1031
1032 View Code Duplication
					case 'country' :
1033
							$QST_values = array(
1034
									'QST_display_text' => __( 'Country', 'event_espresso' ),
1035
									'QST_admin_label' => __( 'Country - System Question', 'event_espresso' ),
1036
									'QST_system' => 'country',
1037
									'QST_type' => 'COUNTRY',
1038
									'QST_required' => 0,
1039
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
1040
									'QST_order' => 8,
1041
									'QST_admin_only' => 0,
1042
									'QST_wp_user' => self::get_default_creator_id(),
1043
									'QST_deleted' => 0
1044
								);
1045
						break;
1046
1047 View Code Duplication
					case 'zip':
1048
							$QST_values = array(
1049
									'QST_display_text' => __( 'Zip/Postal Code', 'event_espresso' ),
1050
									'QST_admin_label' => __( 'Zip/Postal Code - System Question', 'event_espresso' ),
1051
									'QST_system' => 'zip',
1052
									'QST_type' => 'TEXT',
1053
									'QST_required' => 0,
1054
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
1055
									'QST_order' => 9,
1056
									'QST_admin_only' => 0,
1057
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
1058
									'QST_wp_user' => self::get_default_creator_id(),
1059
									'QST_deleted' => 0
1060
								);
1061
						break;
1062
1063 View Code Duplication
					case 'phone':
1064
							$QST_values = array(
1065
									'QST_display_text' => __( 'Phone Number', 'event_espresso' ),
1066
									'QST_admin_label' => __( 'Phone Number - System Question', 'event_espresso' ),
1067
									'QST_system' => 'phone',
1068
									'QST_type' => 'TEXT',
1069
									'QST_required' => 0,
1070
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
1071
									'QST_order' => 10,
1072
									'QST_admin_only' => 0,
1073
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
1074
									'QST_wp_user' => self::get_default_creator_id(),
1075
									'QST_deleted' => 0
1076
								);
1077
						break;
1078
1079
				}
1080
				if ( ! empty( $QST_values )) {
1081
					// insert system question
1082
					$wpdb->insert(
1083
						$table_name,
1084
						$QST_values,
1085
						array( '%s', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%d', '%d' )
1086
					);
1087
					$QST_ID = $wpdb->insert_id;
1088
1089
					// QUESTION GROUP QUESTIONS
1090
					if(  in_array( $QST_system, array( 'fname', 'lname', 'email' ) ) ) {
1091
						$system_question_we_want = EEM_Question_Group::system_personal;
1092
					} else {
1093
						$system_question_we_want = EEM_Question_Group::system_address;
1094
					}
1095
					if( isset( $QSG_IDs[ $system_question_we_want ] ) ) {
1096
						$QSG_ID = $QSG_IDs[ $system_question_we_want ];
1097
					} else {
1098
						$id_col = EEM_Question_Group::instance()->get_col( array( array( 'QSG_system' => $system_question_we_want ) ) );
1099
						if( is_array( $id_col ) ) {
1100
							$QSG_ID = reset( $id_col );
1101
						} else {
1102
							//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
1103
                                                        EE_Log::instance()->log( 
1104
                                                                __FILE__, 
1105
                                                                __FUNCTION__, 
1106
                                                                sprintf( 
1107
                                                                        __( 'Could not associate question %1$s to a question group because no system question group existed', 'event_espresso'), 
1108
                                                                        $QST_ID ), 
1109
                                                                'error' );
1110
                                                        continue;
1111
						}
1112
					}
1113
                                        
1114
					// add system questions to groups
1115
					$wpdb->insert(
1116
						EEH_Activation::ensure_table_name_has_prefix( 'esp_question_group_question' ),
1117
						array( 'QSG_ID' => $QSG_ID , 'QST_ID' => $QST_ID, 'QGQ_order'=>($QSG_ID==1)? $order_for_group_1++ : $order_for_group_2++ ),
1118
						array( '%d', '%d','%d' )
1119
					);
1120
				}
1121
			}
1122
		}
1123
1124
	}
1125
1126
	/**
1127
	 * Makes sure the default payment method (Invoice) is active.
1128
	 * This used to be done automatically as part of constructing the old gateways config
1129
	 */
1130
	public static function insert_default_payment_methods(){
1131
		if( ! EEM_Payment_Method::instance()->count_active( EEM_Payment_Method::scope_cart ) ){
1132
			EE_Registry::instance()->load_lib( 'Payment_Method_Manager' );
1133
			EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type( 'Invoice' );
1134
		}else{
1135
			EEM_Payment_Method::instance()->verify_button_urls();
1136
		}
1137
	}
1138
1139
	/**
1140
	 * insert_default_status_codes
1141
	 *
1142
	 * 	@access public
1143
	 * 	@static
1144
	 * 	@return void
1145
	 */
1146
	public static function insert_default_status_codes() {
1147
1148
		global $wpdb;
1149
1150
		if ( EEH_Activation::table_exists( EEM_Status::instance()->table() ) ) {
1151
1152
			$table_name = EEM_Status::instance()->table();
1153
1154
			$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' );";
1155
			$wpdb->query($SQL);
1156
1157
			$SQL = "INSERT INTO $table_name
1158
					(STS_ID, STS_code, STS_type, STS_can_edit, STS_desc, STS_open) VALUES
1159
					('ACT', 'ACTIVE', 'event', 0, NULL, 1),
1160
					('NAC', 'NOT_ACTIVE', 'event', 0, NULL, 0),
1161
					('NOP', 'REGISTRATION_NOT_OPEN', 'event', 0, NULL, 1),
1162
					('OPN', 'REGISTRATION_OPEN', 'event', 0, NULL, 1),
1163
					('CLS', 'REGISTRATION_CLOSED', 'event', 0, NULL, 0),
1164
					('PND', 'PENDING', 'event', 0, NULL, 1),
1165
					('ONG', 'ONGOING', 'event', 0, NULL, 1),
1166
					('SEC', 'SECONDARY', 'event', 0, NULL, 1),
1167
					('DRF', 'DRAFT', 'event', 0, NULL, 0),
1168
					('DEL', 'DELETED', 'event', 0, NULL, 0),
1169
					('DEN', 'DENIED', 'event', 0, NULL, 0),
1170
					('EXP', 'EXPIRED', 'event', 0, NULL, 0),
1171
					('RPP', 'PENDING_PAYMENT', 'registration', 0, NULL, 1),
1172
					('RAP', 'APPROVED', 'registration', 0, NULL, 1),
1173
					('RCN', 'CANCELLED', 'registration', 0, NULL, 0),
1174
					('RDC', 'DECLINED', 'registration', 0, NULL, 0),
1175
					('RNA', 'NOT_APPROVED', 'registration', 0, NULL, 1),
1176
					('RIC', 'INCOMPLETE', 'registration', 0, NULL, 1),
1177
					('TFL', 'FAILED', 'transaction', 0, NULL, 0),
1178
					('TAB', 'ABANDONED', 'transaction', 0, NULL, 0),
1179
					('TIN', 'INCOMPLETE', 'transaction', 0, NULL, 1),
1180
					('TCM', 'COMPLETE', 'transaction', 0, NULL, 1),
1181
					('TOP',	'OVERPAID', 'transaction', 0, NULL, 1),
1182
					('PAP', 'APPROVED', 'payment', 0, NULL, 1),
1183
					('PPN', 'PENDING', 'payment', 0, NULL, 1),
1184
					('PCN', 'CANCELLED', 'payment', 0, NULL, 0),
1185
					('PFL', 'FAILED', 'payment', 0, NULL, 0),
1186
					('PDC', 'DECLINED', 'payment', 0, NULL, 0),
1187
					('EDR', 'DRAFT', 'email', 0, NULL, 0),
1188
					('ESN', 'SENT', 'email', 0, NULL, 1);";
1189
			$wpdb->query($SQL);
1190
1191
		}
1192
1193
	}
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
	/**
1208
	 * create_upload_directories
1209
	 * Creates folders in the uploads directory to facilitate addons and templates
1210
	 *
1211
	 * 	@access public
1212
	 * 	@static
1213
	 * 	@return boolean success of verifying upload directories exist
1214
	 */
1215
	public static function create_upload_directories() {
1216
		EE_Registry::instance()->load_helper( 'File' );
1217
		// Create the required folders
1218
		$folders = array(
1219
				EVENT_ESPRESSO_TEMPLATE_DIR,
1220
				EVENT_ESPRESSO_GATEWAY_DIR,
1221
				EVENT_ESPRESSO_UPLOAD_DIR . 'logs/',
1222
				EVENT_ESPRESSO_UPLOAD_DIR . 'css/',
1223
				EVENT_ESPRESSO_UPLOAD_DIR . 'tickets/'
1224
		);
1225
		foreach ( $folders as $folder ) {
1226
			try {
1227
				EEH_File::ensure_folder_exists_and_is_writable( $folder );
1228
				@ 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...
1229
			} catch( EE_Error $e ){
1230
				EE_Error::add_error(
1231
					sprintf(
1232
						__(  'Could not create the folder at "%1$s" because: %2$s', 'event_espresso' ),
1233
						$folder,
1234
						'<br />' . $e->getMessage()
1235
					),
1236
					__FILE__, __FUNCTION__, __LINE__
1237
				);
1238
				//indicate we'll need to fix this later
1239
				update_option( EEH_Activation::upload_directories_incomplete_option_name, true );
1240
				return FALSE;
1241
			}
1242
		}
1243
		//just add the .htaccess file to the logs directory to begin with. Even if logging
1244
		//is disabled, there might be activation errors recorded in there
1245
		EEH_File::add_htaccess_deny_from_all( EVENT_ESPRESSO_UPLOAD_DIR . 'logs/' );
1246
		//remember EE's folders are all good
1247
		delete_option( EEH_Activation::upload_directories_incomplete_option_name );
1248
		return TRUE;
1249
	}
1250
	
1251
	/**
1252
	 * Whether the upload directories need to be fixed or not.
1253
	 * If EE is installed but filesystem access isn't initially available,
1254
	 * we need to get the user's filesystem credentials and THEN create them,
1255
	 * so there might be period of time when EE is installed but its 
1256
	 * upload directories aren't available. This indicates such a state
1257
	 * @return boolean
1258
	 */
1259
	public static function upload_directories_incomplete() {
1260
		return get_option( EEH_Activation::upload_directories_incomplete_option_name, false );
1261
	}
1262
1263
1264
1265
1266
	/**
1267
	 * generate_default_message_templates
1268
	 *
1269
	 * 	@access public
1270
	 * 	@static
1271
	 * 	@return bool | array
1272
	 */
1273
	public static function generate_default_message_templates() {
1274
1275
		$success = FALSE;
1276
		$installed_messengers = $default_messengers = array();
1277
1278
		//include our helper
1279
		EE_Registry::instance()->load_helper( 'MSG_Template' );
1280
1281
		//get all installed messenger objects
1282
		$installed = EEH_MSG_Template::get_installed_message_objects();
1283
1284
		//let's setup the $installed messengers in an array AND the messengers that are set to be activated on install.
1285
		foreach ( $installed['messengers'] as $msgr ) {
1286
			if ( $msgr instanceof EE_messenger ) {
1287
				$installed_messengers[$msgr->name] = $msgr;
1288
				if ( $msgr->activate_on_install ) {
1289
					$default_messengers[] = $msgr->name;
1290
				}
1291
			}
1292
		}
1293
1294
		//let's determine if we've already got an active messengers option
1295
		$active_messengers = EEH_MSG_Template::get_active_messengers_in_db();
1296
1297
		//things that have already been activated before
1298
		$has_activated = get_option( 'ee_has_activated_messenger' );
1299
1300
		//do an initial loop to determine if we need to continue
1301
		$def_ms = array();
1302
		foreach ( $default_messengers as $msgr ) {
1303
			if ( isset($active_messengers[$msgr] ) || isset( $has_activated[$msgr] ) ) continue;
1304
			$def_ms[] = $msgr;
1305
		}
1306
1307
		//setup the $installed_mts in an array
1308
		foreach ( $installed['message_types'] as $imt ) {
1309
			if ( $imt instanceof EE_message_type ) {
1310
				$installed_mts[$imt->name] = $imt;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$installed_mts was never initialized. Although not strictly required by PHP, it is generally a good practice to add $installed_mts = 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...
1311
			}
1312
		}
1313
1314
		//loop through default array for default messengers (if present)
1315
		if ( ! empty( $def_ms ) ) {
1316
			foreach ( $def_ms as $messenger ) {
1317
				//all is good so let's setup the default stuff. We need to use the given messenger object (if exists) to get the default message type for the messenger.
1318
				if ( ! isset( $installed_messengers[$messenger] )) {
1319
					continue;
1320
				}
1321
				/** @var EE_messenger[] $installed_messengers  */
1322
				$default_mts = $installed_messengers[$messenger]->get_default_message_types();
1323
				$active_messengers[$messenger]['obj'] = $installed_messengers[$messenger];
1324
				foreach ( $default_mts as $index => $mt ) {
1325
					//is there an installed_mt matching the default string?  If not then nothing to do here.
1326
					if ( ! isset( $installed_mts[$mt] ) ) {
1327
						unset( $default_mts[$index] );
1328
						continue;
1329
					}
1330
1331
1332
					//we need to setup any initial settings for message types
1333
					/** @var EE_message_type[] $installed_mts */
1334
					$settings_fields = $installed_mts[$mt]->get_admin_settings_fields();
1335
					$settings = array();
1336 View Code Duplication
					if ( is_array( $settings_fields ) ) {
1337
						foreach ( $settings_fields as $field => $values ) {
1338
							if ( isset( $values['default'] ) ) {
1339
								$settings[$field] = $values['default'];
1340
							}
1341
						}
1342
					}
1343
1344
					$active_messengers[$messenger]['settings'][$messenger . '-message_types'][$mt]['settings'] = $settings;
1345
					$has_activated[$messenger][] = $mt;
1346
				}
1347
1348
				//setup any initial settings for the messenger
1349
				$msgr_settings = $installed_messengers[$messenger]->get_admin_settings_fields();
1350
1351 View Code Duplication
				if ( !empty( $msgr_settings ) ) {
1352
					foreach ( $msgr_settings as $field => $value ) {
1353
						$active_messengers[$messenger]['settings'][$field] = $value;
1354
					}
1355
				}
1356
1357
				//now let's save the settings for this messenger! Must do now because the validator checks the db for active messengers to validate.
1358
				EEH_MSG_Template::update_active_messengers_in_db( $active_messengers );
1359
1360
				//let's generate all the templates but only if the messenger has default_mts (otherwise its just activated).
1361
				if ( !empty( $default_mts ) ) {
1362
					$success = EEH_MSG_Template::generate_new_templates( $messenger, $default_mts, '', TRUE );
1363
				}
1364
			}
1365
		} //end check for empty( $def_ms )
1366
1367
		//still need to see if there are any message types to activate for active messengers
1368
		foreach ( $active_messengers as $messenger => $settings ) {
1369
			$msg_obj = $settings['obj'];
1370
			if ( ! $msg_obj instanceof EE_messenger ) {
1371
				continue;
1372
			}
1373
1374
			$all_default_mts = $msg_obj->get_default_message_types();
1375
			$new_default_mts = array();
1376
1377
			//loop through each default mt reported by the messenger and make sure its set in its active db entry.
1378
			foreach( $all_default_mts as $index => $mt ) {
1379
				//already active? already has generated templates? || has already been activated before (we dont' want to reactivate things users intentionally deactivated).
1380
				if ( ( isset( $has_activated[$messenger] ) && in_array($mt, $has_activated[$messenger]) ) || isset( $active_messengers[$messenger]['settings'][$messenger . '-message_types'][$mt] ) ||  EEH_MSG_Template::already_generated( $messenger, $mt, 0, FALSE ) ) {
1381
					continue;
1382
				}
1383
1384
				//is there an installed_mt matching the default string?  If not then nothing to do here.
1385
				if ( ! isset( $installed_mts[$mt] ) ) {
1386
					unset( $all_default_mts[$mt] );
1387
					continue;
1388
				}
1389
1390
				$settings_fields = $installed_mts[$mt]->get_admin_settings_fields();
1391
				$settings = array();
1392 View Code Duplication
				if ( is_array( $settings_fields ) ) {
1393
					foreach ( $settings_fields as $field => $values ) {
1394
						if ( isset( $values['default'] ) ) {
1395
							$settings[$field] = $values['default'];
1396
						}
1397
					}
1398
				}
1399
1400
				$active_messengers[$messenger]['settings'][$messenger . '-message_types'][$mt]['settings'] = $settings;
1401
				$new_default_mts[] = $mt;
1402
				$has_activated[$messenger][] = $mt;
1403
			}
1404
1405
1406
			if ( ! empty( $new_default_mts ) ) {
1407
				$success = EEH_MSG_Template::generate_new_templates( $messenger, $new_default_mts, '', TRUE );
1408
			}
1409
1410
		}
1411
1412
		//now let's save the settings for this messenger!
1413
		EEH_MSG_Template::update_active_messengers_in_db( $active_messengers );
1414
1415
		//update $has_activated record
1416
		update_option( 'ee_has_activated_messenger', $has_activated );
1417
1418
		//that's it!
1419
		return $success;
1420
	}
1421
1422
1423
1424
1425
1426
1427
	/**
1428
	 * This simply validates active messengers and message types to ensure they actually match installed messengers and message types.  If there's a mismatch then we deactivate the messenger/message type and ensure all related db rows are set inactive.
1429
	 *
1430
	 * @since 4.3.1
1431
	 *
1432
	 * @return void
1433
	 */
1434
	public static function validate_messages_system() {
1435
		//include our helper
1436
		EE_Registry::instance()->load_helper( 'MSG_Template' );
1437
1438
		//get active and installed  messengers/message types.
1439
		$active_messengers = EEH_MSG_Template::get_active_messengers_in_db();
1440
		$installed = EEH_MSG_Template::get_installed_message_objects();
1441
		$installed_messengers = $installed_mts = array();
1442
		//set up the arrays so they can be handled easier.
1443
		foreach( $installed['messengers'] as $im ) {
1444
			if ( $im instanceof EE_messenger ) {
1445
				$installed_messengers[$im->name] = $im;
1446
			}
1447
		}
1448
		foreach( $installed['message_types'] as $imt ) {
1449
			if ( $imt instanceof EE_message_type ) {
1450
				$installed_mts[$imt->name] = $imt;
1451
			}
1452
		}
1453
1454
		//now let's loop through the active array and validate
1455
		foreach( $active_messengers as $messenger => $active_details ) {
1456
			//first let's see if this messenger is installed.
1457
			if ( ! isset( $installed_messengers[$messenger] ) ) {
1458
				//not set so let's just remove from actives and make sure templates are inactive.
1459
				unset( $active_messengers[$messenger] );
1460
				EEH_MSG_Template::update_to_inactive( $messenger );
1461
				continue;
1462
			}
1463
1464
			//messenger is active, so let's just make sure that any active message types not installed are deactivated.
1465
			$mts = ! empty( $active_details['settings'][$messenger . '-message_types'] ) ? $active_details['settings'][$messenger . '-message_types'] : array();
1466
			foreach ( $mts as $mt_name => $mt ) {
1467
				if ( ! isset( $installed_mts[$mt_name] )  ) {
1468
					unset( $active_messengers[$messenger]['settings'][$messenger . '-message_types'][$mt_name] );
1469
					EEH_MSG_Template::update_to_inactive( $messenger, $mt_name );
1470
				}
1471
			}
1472
		}
1473
1474
		//all done! let's update the active_messengers.
1475
		EEH_MSG_Template::update_active_messengers_in_db( $active_messengers );
1476
		do_action( 'AHEE__EEH_Activation__validate_messages_system' );
1477
		return;
1478
	}
1479
1480
1481
1482
1483
	/**
1484
	 * create_no_ticket_prices_array
1485
	 *
1486
	 * 	@access public
1487
	 * 	@static
1488
	 * 	@return void
1489
	 */
1490
	public static function create_no_ticket_prices_array(){
1491
		// this creates an array for tracking events that have no active ticket prices created
1492
		// this allows us to warn admins of the situation so that it can be corrected
1493
		$espresso_no_ticket_prices = get_option( 'ee_no_ticket_prices', FALSE );
1494
		if ( ! $espresso_no_ticket_prices ) {
1495
			add_option( 'ee_no_ticket_prices', array(), '', FALSE );
1496
		}
1497
	}
1498
1499
1500
1501
	/**
1502
	 * plugin_deactivation
1503
	 *
1504
	 * 	@access public
1505
	 * 	@static
1506
	 * 	@return void
1507
	 */
1508
	public static function plugin_deactivation() {
1509
	}
1510
1511
1512
1513
	/**
1514
	 * Finds all our EE4 custom post types, and deletes them and their associated data (like post meta or term relations)/
1515
	 * @global wpdb $wpdb
1516
	 */
1517
	public static function delete_all_espresso_cpt_data(){
1518
		global $wpdb;
1519
		//get all the CPT post_types
1520
		$ee_post_types = array();
1521
		foreach(EE_Registry::instance()->non_abstract_db_models as $model_name){
1522
			if ( method_exists( $model_name, 'instance' )) {
1523
				$model_obj = call_user_func( array( $model_name, 'instance' ));
1524
				if ( $model_obj instanceof EEM_CPT_Base ) {
1525
					$ee_post_types[] = $wpdb->prepare("%s",$model_obj->post_type());
1526
				}
1527
			}
1528
		}
1529
		//get all our CPTs
1530
		$query = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (".implode(",",$ee_post_types).")";
1531
		$cpt_ids = $wpdb->get_col($query);
1532
		//delete each post meta and term relations too
1533
		foreach($cpt_ids as $post_id){
1534
			wp_delete_post($post_id,true);
1535
		}
1536
	}
1537
1538
1539
1540
	/**
1541
	 * plugin_uninstall
1542
	 *
1543
	 * @access public
1544
	 * @static
1545
	 * @param bool $remove_all
1546
	 * @return void
1547
	 */
1548
	public static function delete_all_espresso_tables_and_data( $remove_all = true ) {
1549
		global $wpdb;
1550
		$undeleted_tables = array();
1551
1552
		// load registry
1553
		foreach( EE_Registry::instance()->non_abstract_db_models as $model_name ){
1554
			if ( method_exists( $model_name, 'instance' )) {
1555
				$model_obj = call_user_func( array( $model_name, 'instance' ));
1556
				if ( $model_obj instanceof EEM_Base ) {
1557
					foreach ( $model_obj->get_tables() as $table ) {
1558
						if ( strpos( $table->get_table_name(), 'esp_' )) {
1559
							switch ( EEH_Activation::delete_unused_db_table( $table->get_table_name() )) {
1560
								case false :
1561
									$undeleted_tables[] = $table->get_table_name();
1562
								break;
1563
								case 0 :
1564
									// echo '<h4 style="color:red;">the table : ' . $table->get_table_name() . ' was not deleted  <br /></h4>';
1565
								break;
1566
								default:
1567
									// echo '<h4>the table : ' . $table->get_table_name() . ' was deleted successfully <br /></h4>';
1568
							}
1569
						}
1570
					}
1571
				}
1572
			}
1573
		}
1574
1575
		//there are some tables whose models were removed.
1576
		//they should be removed when removing all EE core's data
1577
		$tables_without_models = array(
1578
			'esp_promotion',
1579
			'esp_promotion_applied',
1580
			'esp_promotion_object',
1581
			'esp_promotion_rule',
1582
			'esp_rule'
1583
		);
1584
		foreach( $tables_without_models as $table ){
1585
			EEH_Activation::delete_db_table_if_empty( $table );
1586
		}
1587
1588
1589
		$wp_options_to_delete = array(
1590
			'ee_no_ticket_prices' => true,
1591
			'ee_active_messengers' => true,
1592
			'ee_has_activated_messenger' => true,
1593
			'ee_flush_rewrite_rules' => true,
1594
			'ee_config' => false,
1595
			'ee_data_migration_current_db_state' => true,
1596
			'ee_data_migration_mapping_' => false,
1597
			'ee_data_migration_script_' => false,
1598
			'ee_data_migrations' => true,
1599
			'ee_dms_map' => false,
1600
			'ee_notices' => true,
1601
			'lang_file_check_' => false,
1602
			'ee_maintenance_mode' => true,
1603
			'ee_ueip_optin' => true,
1604
			'ee_ueip_has_notified' => true,
1605
			'ee_plugin_activation_errors' => true,
1606
			'ee_id_mapping_from' => false,
1607
			'espresso_persistent_admin_notices' => true,
1608
			'ee_encryption_key' => true,
1609
			'pue_force_upgrade_' => false,
1610
			'pue_json_error_' => false,
1611
			'pue_install_key_' => false,
1612
			'pue_verification_error_' => false,
1613
			'pu_dismissed_upgrade_' => false,
1614
			'external_updates-' => false,
1615
			'ee_extra_data' => true,
1616
			'ee_ssn_' => false,
1617
			'ee_rss_' => false,
1618
			'ee_rte_n_tx_' => false,
1619
			'ee_pers_admin_notices' => true,
1620
			'ee_job_parameters_' => false,
1621
			'ee_upload_directories_incomplete' => true,
1622
		);
1623
		if( is_main_site() ) {
1624
			$wp_options_to_delete[ 'ee_network_config' ] = true;
1625
		}
1626
1627
		$undeleted_options = array();
1628
		foreach ( $wp_options_to_delete as $option_name => $no_wildcard ) {
1629
1630
			if( $no_wildcard ){
1631
				if( ! delete_option( $option_name ) ){
1632
					$undeleted_options[] = $option_name;
1633
				}
1634
			}else{
1635
				$option_names_to_delete_from_wildcard = $wpdb->get_col( "SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%$option_name%'" );
1636
				foreach($option_names_to_delete_from_wildcard as $option_name_from_wildcard ){
1637
					if( ! delete_option( $option_name_from_wildcard ) ){
1638
						$undeleted_options[] = $option_name_from_wildcard;
1639
					}
1640
				}
1641
			}
1642
		}
1643
                //also, let's make sure the "ee_config_option_names" wp option stays out by removing the action that adds it
1644
                remove_action( 'shutdown', array( EE_Config::instance(), 'shutdown' ), 10 );
1645
1646
		if ( $remove_all && $espresso_db_update = get_option( 'espresso_db_update' )) {
1647
			$db_update_sans_ee4 = array();
1648
			foreach($espresso_db_update as $version => $times_activated){
1649
				if( $version[0] =='3'){//if its NON EE4
1650
					$db_update_sans_ee4[$version] = $times_activated;
1651
				}
1652
			}
1653
			update_option( 'espresso_db_update', $db_update_sans_ee4 );
1654
		}
1655
1656
		$errors = '';
1657
		if ( ! empty( $undeleted_tables )) {
1658
			$errors .= sprintf(
1659
				__( 'The following tables could not be deleted: %s%s', 'event_espresso' ),
1660
				'<br/>',
1661
				implode( ',<br/>', $undeleted_tables )
1662
			);
1663
		}
1664
		if ( ! empty( $undeleted_options )) {
1665
			$errors .= ! empty( $undeleted_tables ) ? '<br/>' : '';
1666
			$errors .= sprintf(
1667
				__( 'The following wp-options could not be deleted: %s%s', 'event_espresso' ),
1668
				'<br/>',
1669
				implode( ',<br/>', $undeleted_options )
1670
			);
1671
1672
		}
1673
		if ( $errors != '' ) {
1674
			EE_Error::add_attention( $errors, __FILE__, __FUNCTION__, __LINE__ );
1675
		}
1676
	}
1677
1678
	/**
1679
	 * Checks that the database table exists. Also works on temporary tables (for unit tests mostly).
1680
	 * @global wpdb $wpdb
1681
	 * @param string $table_name with or without $wpdb->prefix
1682
	 * @return boolean
1683
	 */
1684
	public static function table_exists( $table_name ){
1685
		global $wpdb, $EZSQL_ERROR;
1686
		$table_name = EEH_Activation::ensure_table_name_has_prefix( $table_name );
1687
		//ignore if this causes an sql error
1688
		$old_error = $wpdb->last_error;
1689
		$old_suppress_errors = $wpdb->suppress_errors();
1690
		$old_show_errors_value = $wpdb->show_errors( FALSE );
1691
		$ezsql_error_cache = $EZSQL_ERROR;
1692
		$wpdb->get_results( "SELECT * from $table_name LIMIT 1");
1693
		$wpdb->show_errors( $old_show_errors_value );
1694
		$wpdb->suppress_errors( $old_suppress_errors );
1695
		$new_error = $wpdb->last_error;
1696
		$wpdb->last_error = $old_error;
1697
		$EZSQL_ERROR = $ezsql_error_cache;
1698
		if( empty( $new_error ) ){
1699
			return TRUE;
1700
		}else{
1701
			return FALSE;
1702
		}
1703
	}
1704
1705
	/**
1706
	 * Resets the cache on EEH_Activation
1707
	 */
1708
	public static function reset(){
1709
		self::$_default_creator_id = NULL;
1710
		self::$_initialized_db_content_already_in_this_request = false;
1711
	}
1712
}
1713
// End of file EEH_Activation.helper.php
1714
// Location: /helpers/EEH_Activation.core.php
1715