Completed
Branch FET-9046-messages-queue (d125c6)
by
unknown
486:55 queued 472:32
created

EEH_Activation::validate_messages_system()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 40
Code Lines 4

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 40
rs 8.8571
cc 1
eloc 4
nc 1
nop 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 View Code Duplication
					if ( $critical_page['post'] == NULL ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
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 ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
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 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...
Duplication introduced by
This code seems to be duplicated across 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...
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:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
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:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
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':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
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':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
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':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
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':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
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':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
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':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
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':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
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' :
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
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':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
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':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
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', 'MSN', 'MFL', 'MID', 'MRS', 'MIC' );";
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
					('MSN', 'SENT', 'message', 0, NULL, 0),
1190
					('MFL', 'FAIL', 'message', 0, NULL, 0),
1191
					('MID', 'IDLE', 'message', 0, NULL, 1),
1192
					('MRS', 'RESEND', 'message', 0, NULL, 1),
1193
					('MIC', 'INCOMPLETE', 'message', 0, NULL, 0);";
1194
			$wpdb->query($SQL);
1195
1196
		}
1197
1198
	}
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
	/**
1213
	 * create_upload_directories
1214
	 * Creates folders in the uploads directory to facilitate addons and templates
1215
	 *
1216
	 * 	@access public
1217
	 * 	@static
1218
	 * 	@return boolean success of verifying upload directories exist
1219
	 */
1220
	public static function create_upload_directories() {
1221
		EE_Registry::instance()->load_helper( 'File' );
1222
		// Create the required folders
1223
		$folders = array(
1224
				EVENT_ESPRESSO_TEMPLATE_DIR,
1225
				EVENT_ESPRESSO_GATEWAY_DIR,
1226
				EVENT_ESPRESSO_UPLOAD_DIR . 'logs/',
1227
				EVENT_ESPRESSO_UPLOAD_DIR . 'css/',
1228
				EVENT_ESPRESSO_UPLOAD_DIR . 'tickets/'
1229
		);
1230
		foreach ( $folders as $folder ) {
1231
			try {
1232
				EEH_File::ensure_folder_exists_and_is_writable( $folder );
1233
				@ 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...
1234
			} catch( EE_Error $e ){
1235
				EE_Error::add_error(
1236
					sprintf(
1237
						__(  'Could not create the folder at "%1$s" because: %2$s', 'event_espresso' ),
1238
						$folder,
1239
						'<br />' . $e->getMessage()
1240
					),
1241
					__FILE__, __FUNCTION__, __LINE__
1242
				);
1243
				//indicate we'll need to fix this later
1244
				update_option( EEH_Activation::upload_directories_incomplete_option_name, true );
1245
				return FALSE;
1246
			}
1247
		}
1248
		//just add the .htaccess file to the logs directory to begin with. Even if logging
1249
		//is disabled, there might be activation errors recorded in there
1250
		EEH_File::add_htaccess_deny_from_all( EVENT_ESPRESSO_UPLOAD_DIR . 'logs/' );
1251
		//remember EE's folders are all good
1252
		delete_option( EEH_Activation::upload_directories_incomplete_option_name );
1253
		return TRUE;
1254
	}
1255
1256
	/**
1257
	 * Whether the upload directories need to be fixed or not.
1258
	 * If EE is installed but filesystem access isn't initially available,
1259
	 * we need to get the user's filesystem credentials and THEN create them,
1260
	 * so there might be period of time when EE is installed but its
1261
	 * upload directories aren't available. This indicates such a state
1262
	 * @return boolean
1263
	 */
1264
	public static function upload_directories_incomplete() {
1265
		return get_option( EEH_Activation::upload_directories_incomplete_option_name, false );
1266
	}
1267
1268
1269
1270
1271
	/**
1272
	 * generate_default_message_templates
1273
	 *
1274
	 * 	@access public
1275
	 * 	@static
1276
	 * 	@return bool
1277
	 */
1278
	public static function generate_default_message_templates() {
1279
		EE_Registry::instance()->load_helper( 'MSG_Template' );
1280
		/** @type EE_Message_Resource_Manager $message_resource_manager */
1281
		$message_resource_manager = EE_Registry::instance()->load_lib( 'Message_Resource_Manager' );
1282
		//get all installed messenger objects
1283
		$installed_messengers = $message_resource_manager->installed_messengers();
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 $messenger ) {
1286
			if ( $messenger instanceof EE_Messenger && $messenger->activate_on_install ) {
1287
				$default_message_types = $messenger->get_default_message_types();
1288
				if ( ! empty( $default_message_types ) ) {
1289
					EEH_MSG_Template::generate_new_templates( $messenger->name, $default_message_types );
1290
				}
1291
			}
1292
		}
1293
		return true;
1294
	}
1295
1296
1297
1298
1299
1300
1301
	/**
1302
	 * 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.
1303
	 *
1304
	 * @since 4.3.1
1305
	 *
1306
	 * @return void
1307
	 */
1308
	public static function validate_messages_system() {
1309
		/** @type EE_Message_Resource_Manager $message_resource_manager */
1310
		$message_resource_manager = EE_Registry::instance()->load_lib( 'Message_Resource_Manager' );
0 ignored issues
show
Unused Code introduced by
$message_resource_manager is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1311
		// ********************************************************
1312
		// as soon as EE_Message_Resource_Manager is instantiated,
1313
		// it runs _set_active_messengers_and_message_types()
1314
		// which effectively accomplishes the same thing
1315
		// as all of the following code... so I commented it out
1316
		// ********************************************************
1317
1318
		//get active and installed  messengers/message types.
1319
		//$active_messengers = $message_resource_manager->get_active_messengers_option();
1320
		//$installed_messengers = $message_resource_manager->installed_messengers();
1321
		//$installed_mts = $message_resource_manager->installed_message_types();
1322
		//
1323
		////now let's loop through the active array and validate
1324
		//foreach( $active_messengers as $messenger => $active_details ) {
1325
		//	//first let's see if this messenger is installed.
1326
		//	if ( ! isset( $installed_messengers[$messenger] ) ) {
1327
		//		//not set so let's just remove from actives and make sure templates are inactive.
1328
		//		unset( $active_messengers[$messenger] );
1329
		//		EEH_MSG_Template::update_to_inactive( $messenger );
1330
		//		continue;
1331
		//	}
1332
		//
1333
		//	//messenger is active, so let's just make sure that any active message types not installed are deactivated.
1334
		//	$mts = ! empty( $active_details['settings'][$messenger . '-message_types'] ) ? $active_details['settings'][$messenger . '-message_types'] : array();
1335
		//	foreach ( $mts as $mt_name => $mt ) {
1336
		//		if ( ! isset( $installed_mts[$mt_name] )  ) {
1337
		//			unset( $active_messengers[$messenger]['settings'][$messenger . '-message_types'][$mt_name] );
1338
		//			EEH_MSG_Template::update_to_inactive( $messenger, $mt_name );
1339
		//		}
1340
		//	}
1341
		//}
1342
		//
1343
		////all done! let's update the active_messengers.
1344
		//EEH_MSG_Template::update_active_messengers_in_db( $active_messengers );
1345
		do_action( 'AHEE__EEH_Activation__validate_messages_system' );
1346
		return;
1347
	}
1348
1349
1350
1351
1352
	/**
1353
	 * create_no_ticket_prices_array
1354
	 *
1355
	 * 	@access public
1356
	 * 	@static
1357
	 * 	@return void
1358
	 */
1359
	public static function create_no_ticket_prices_array(){
1360
		// this creates an array for tracking events that have no active ticket prices created
1361
		// this allows us to warn admins of the situation so that it can be corrected
1362
		$espresso_no_ticket_prices = get_option( 'ee_no_ticket_prices', FALSE );
1363
		if ( ! $espresso_no_ticket_prices ) {
1364
			add_option( 'ee_no_ticket_prices', array(), '', FALSE );
1365
		}
1366
	}
1367
1368
1369
1370
	/**
1371
	 * plugin_deactivation
1372
	 *
1373
	 * 	@access public
1374
	 * 	@static
1375
	 * 	@return void
1376
	 */
1377
	public static function plugin_deactivation() {
1378
	}
1379
1380
1381
1382
	/**
1383
	 * Finds all our EE4 custom post types, and deletes them and their associated data (like post meta or term relations)/
1384
	 * @global wpdb $wpdb
1385
	 */
1386
	public static function delete_all_espresso_cpt_data(){
1387
		global $wpdb;
1388
		//get all the CPT post_types
1389
		$ee_post_types = array();
1390
		foreach(EE_Registry::instance()->non_abstract_db_models as $model_name){
1391
			if ( method_exists( $model_name, 'instance' )) {
1392
				$model_obj = call_user_func( array( $model_name, 'instance' ));
1393
				if ( $model_obj instanceof EEM_CPT_Base ) {
1394
					$ee_post_types[] = $wpdb->prepare("%s",$model_obj->post_type());
1395
				}
1396
			}
1397
		}
1398
		//get all our CPTs
1399
		$query = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (".implode(",",$ee_post_types).")";
1400
		$cpt_ids = $wpdb->get_col($query);
1401
		//delete each post meta and term relations too
1402
		foreach($cpt_ids as $post_id){
1403
			wp_delete_post($post_id,true);
1404
		}
1405
	}
1406
1407
1408
1409
	/**
1410
	 * plugin_uninstall
1411
	 *
1412
	 * @access public
1413
	 * @static
1414
	 * @param bool $remove_all
1415
	 * @return void
1416
	 */
1417
	public static function delete_all_espresso_tables_and_data( $remove_all = true ) {
1418
		global $wpdb;
1419
		$undeleted_tables = array();
1420
1421
		// load registry
1422
		foreach( EE_Registry::instance()->non_abstract_db_models as $model_name ){
1423
			if ( method_exists( $model_name, 'instance' )) {
1424
				$model_obj = call_user_func( array( $model_name, 'instance' ));
1425
				if ( $model_obj instanceof EEM_Base ) {
1426
					foreach ( $model_obj->get_tables() as $table ) {
1427
						if ( strpos( $table->get_table_name(), 'esp_' )) {
1428
							switch ( EEH_Activation::delete_unused_db_table( $table->get_table_name() )) {
1429
								case false :
1430
									$undeleted_tables[] = $table->get_table_name();
1431
								break;
1432
								case 0 :
1433
									// echo '<h4 style="color:red;">the table : ' . $table->get_table_name() . ' was not deleted  <br /></h4>';
1434
								break;
1435
								default:
1436
									// echo '<h4>the table : ' . $table->get_table_name() . ' was deleted successfully <br /></h4>';
1437
							}
1438
						}
1439
					}
1440
				}
1441
			}
1442
		}
1443
1444
		//there are some tables whose models were removed.
1445
		//they should be removed when removing all EE core's data
1446
		$tables_without_models = array(
1447
			'esp_promotion',
1448
			'esp_promotion_applied',
1449
			'esp_promotion_object',
1450
			'esp_promotion_rule',
1451
			'esp_rule'
1452
		);
1453
		foreach( $tables_without_models as $table ){
1454
			EEH_Activation::delete_db_table_if_empty( $table );
1455
		}
1456
1457
1458
		$wp_options_to_delete = array(
1459
			'ee_no_ticket_prices' => true,
1460
			'ee_active_messengers' => true,
1461
			'ee_has_activated_messenger' => true,
1462
			'ee_flush_rewrite_rules' => true,
1463
			'ee_config' => false,
1464
			'ee_data_migration_current_db_state' => true,
1465
			'ee_data_migration_mapping_' => false,
1466
			'ee_data_migration_script_' => false,
1467
			'ee_data_migrations' => true,
1468
			'ee_dms_map' => false,
1469
			'ee_notices' => true,
1470
			'lang_file_check_' => false,
1471
			'ee_maintenance_mode' => true,
1472
			'ee_ueip_optin' => true,
1473
			'ee_ueip_has_notified' => true,
1474
			'ee_plugin_activation_errors' => true,
1475
			'ee_id_mapping_from' => false,
1476
			'espresso_persistent_admin_notices' => true,
1477
			'ee_encryption_key' => true,
1478
			'pue_force_upgrade_' => false,
1479
			'pue_json_error_' => false,
1480
			'pue_install_key_' => false,
1481
			'pue_verification_error_' => false,
1482
			'pu_dismissed_upgrade_' => false,
1483
			'external_updates-' => false,
1484
			'ee_extra_data' => true,
1485
			'ee_ssn_' => false,
1486
			'ee_rss_' => false,
1487
			'ee_rte_n_tx_' => false,
1488
			'ee_pers_admin_notices' => true,
1489
			'ee_job_parameters_' => false,
1490
			'ee_upload_directories_incomplete' => true,
1491
		);
1492
		if( is_main_site() ) {
1493
			$wp_options_to_delete[ 'ee_network_config' ] = true;
1494
		}
1495
1496
		$undeleted_options = array();
1497
		foreach ( $wp_options_to_delete as $option_name => $no_wildcard ) {
1498
1499
			if( $no_wildcard ){
1500
				if( ! delete_option( $option_name ) ){
1501
					$undeleted_options[] = $option_name;
1502
				}
1503
			}else{
1504
				$option_names_to_delete_from_wildcard = $wpdb->get_col( "SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%$option_name%'" );
1505
				foreach($option_names_to_delete_from_wildcard as $option_name_from_wildcard ){
1506
					if( ! delete_option( $option_name_from_wildcard ) ){
1507
						$undeleted_options[] = $option_name_from_wildcard;
1508
					}
1509
				}
1510
			}
1511
		}
1512
                //also, let's make sure the "ee_config_option_names" wp option stays out by removing the action that adds it
1513
                remove_action( 'shutdown', array( EE_Config::instance(), 'shutdown' ), 10 );
1514
1515
		if ( $remove_all && $espresso_db_update = get_option( 'espresso_db_update' )) {
1516
			$db_update_sans_ee4 = array();
1517
			foreach($espresso_db_update as $version => $times_activated){
1518
				if( $version[0] =='3'){//if its NON EE4
1519
					$db_update_sans_ee4[$version] = $times_activated;
1520
				}
1521
			}
1522
			update_option( 'espresso_db_update', $db_update_sans_ee4 );
1523
		}
1524
1525
		$errors = '';
1526
		if ( ! empty( $undeleted_tables )) {
1527
			$errors .= sprintf(
1528
				__( 'The following tables could not be deleted: %s%s', 'event_espresso' ),
1529
				'<br/>',
1530
				implode( ',<br/>', $undeleted_tables )
1531
			);
1532
		}
1533
		if ( ! empty( $undeleted_options )) {
1534
			$errors .= ! empty( $undeleted_tables ) ? '<br/>' : '';
1535
			$errors .= sprintf(
1536
				__( 'The following wp-options could not be deleted: %s%s', 'event_espresso' ),
1537
				'<br/>',
1538
				implode( ',<br/>', $undeleted_options )
1539
			);
1540
1541
		}
1542
		if ( $errors != '' ) {
1543
			EE_Error::add_attention( $errors, __FILE__, __FUNCTION__, __LINE__ );
1544
		}
1545
	}
1546
1547
	/**
1548
	 * Checks that the database table exists. Also works on temporary tables (for unit tests mostly).
1549
	 * @global wpdb $wpdb
1550
	 * @param string $table_name with or without $wpdb->prefix
1551
	 * @return boolean
1552
	 */
1553
	public static function table_exists( $table_name ){
1554
		global $wpdb, $EZSQL_ERROR;
1555
		$table_name = EEH_Activation::ensure_table_name_has_prefix( $table_name );
1556
		//ignore if this causes an sql error
1557
		$old_error = $wpdb->last_error;
1558
		$old_suppress_errors = $wpdb->suppress_errors();
1559
		$old_show_errors_value = $wpdb->show_errors( FALSE );
1560
		$ezsql_error_cache = $EZSQL_ERROR;
1561
		$wpdb->get_results( "SELECT * from $table_name LIMIT 1");
1562
		$wpdb->show_errors( $old_show_errors_value );
1563
		$wpdb->suppress_errors( $old_suppress_errors );
1564
		$new_error = $wpdb->last_error;
1565
		$wpdb->last_error = $old_error;
1566
		$EZSQL_ERROR = $ezsql_error_cache;
1567
		if( empty( $new_error ) ){
1568
			return TRUE;
1569
		}else{
1570
			return FALSE;
1571
		}
1572
	}
1573
1574
	/**
1575
	 * Resets the cache on EEH_Activation
1576
	 */
1577
	public static function reset(){
1578
		self::$_default_creator_id = NULL;
1579
		self::$_initialized_db_content_already_in_this_request = false;
1580
	}
1581
}
1582
// End of file EEH_Activation.helper.php
1583
// Location: /helpers/EEH_Activation.core.php
1584