Completed
Branch BUG-9548-transaction-completio... (b10ae2)
by
unknown
558:48 queued 538:36
created

EEH_Activation::get_cron_tasks()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 31
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
dl 0
loc 31
rs 8.439
c 2
b 1
f 0
cc 5
eloc 21
nc 4
nop 1
1
<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) {exit('No direct script access allowed');}
2
/**
3
 * EEH_Activation Helper
4
 *
5
 * @package		Event Espresso
6
 * @subpackage	/helpers/
7
 * @author		Brent Christensen
8
 */
9
class EEH_Activation {
10
11
	/**
12
	 * constant used to indicate a cron task is no longer in use
13
	 */
14
	const cron_task_no_longer_in_use = 'no_longer_in_use';
15
16
	/**
17
	 * option name that will indicate whether or not we still
18
	 * need to create EE's folders in the uploads directory
19
	 * (because if EE was installed without file system access,
20
	 * we need to request credentials before we can create them)
21
	 */
22
	const upload_directories_incomplete_option_name = 'ee_upload_directories_incomplete';
23
24
	/**
25
	 * WP_User->ID
26
	 *
27
	 * @var int
28
	 */
29
	private static $_default_creator_id;
30
31
	/**
32
	 * indicates whether or not we've already verified core's default data during this request,
33
	 * because after migrations are done, any addons activated while in maintenance mode
34
	 * will want to setup their own default data, and they might hook into core's default data
35
	 * and trigger core to setup its default data. In which case they might all ask for core to init its default data.
36
	 * This prevents doing that for EVERY single addon.
37
	 * @var boolean
38
	 */
39
	protected static $_initialized_db_content_already_in_this_request = false;
40
41
42
43
	/**
44
	 *    _ensure_table_name_has_prefix
45
	 *
46
	 * @access public
47
	 * @static
48
	 * @param $table_name
49
	 * @return string
50
	 */
51
	public static function ensure_table_name_has_prefix( $table_name ) {
52
		global $wpdb;
53
		return strpos( $table_name, $wpdb->prefix ) === 0 ? $table_name : $wpdb->prefix . $table_name;
54
	}
55
56
57
	/**
58
	 * 	system_initialization
59
	 * 	ensures the EE configuration settings are loaded with at least default options set
60
	 * 	and that all critical EE pages have been generated with the appropriate shortcodes in place
61
	 *
62
	 * 	@access public
63
	 * 	@static
64
	 * 	@return void
65
	 */
66
	public static function system_initialization() {
67
		EEH_Activation::reset_and_update_config();
68
		//which is fired BEFORE activation of plugin anyways
69
		EEH_Activation::verify_default_pages_exist();
70
	}
71
72
73
74
	/**
75
	 * Sets the database schema and creates folders. This should
76
	 * be called on plugin activation and reactivation
77
	 *
78
	 * @return boolean success, whether the database and folders are setup properly
79
	 * @throws \EE_Error
80
	 */
81
	public static function initialize_db_and_folders(){
82
		$good_filesystem = EEH_Activation::create_upload_directories();
83
		$good_db = EEH_Activation::create_database_tables();
84
		return $good_filesystem && $good_db;
85
	}
86
87
88
89
	/**
90
	 * assuming we have an up-to-date database schema, this will populate it
91
	 * with default and initial data. This should be called
92
	 * upon activation of a new plugin, reactivation, and at the end
93
	 * of running migration scripts
94
	 *
95
	 * @throws \EE_Error
96
	 */
97
	public static function initialize_db_content(){
98
		//let's avoid doing all this logic repeatedly, especially when addons are requesting it
99
		if( EEH_Activation::$_initialized_db_content_already_in_this_request ) {
100
			return;
101
		}
102
		EEH_Activation::$_initialized_db_content_already_in_this_request = true;
103
104
		EEH_Activation::initialize_system_questions();
105
		EEH_Activation::insert_default_status_codes();
106
		EEH_Activation::generate_default_message_templates();
107
		EEH_Activation::create_no_ticket_prices_array();
108
		EE_Registry::instance()->CAP->init_caps();
109
110
		EEH_Activation::validate_messages_system();
111
		EEH_Activation::insert_default_payment_methods();
112
		//in case we've
113
		EEH_Activation::remove_cron_tasks();
114
		EEH_Activation::create_cron_tasks();
115
		// remove all TXN locks since that is being done via extra meta now
116
		delete_option( 'ee_locked_transactions' );
117
		//also, check for CAF default db content
118
		do_action( 'AHEE__EEH_Activation__initialize_db_content' );
119
		//also: EEM_Gateways::load_all_gateways() outputs a lot of success messages
120
		//which users really won't care about on initial activation
121
		EE_Error::overwrite_success();
122
	}
123
124
125
126
127
	/**
128
	 * Returns an array of cron tasks. Array values are the actions fired by the cron tasks (the "hooks"),
129
	 * values are the frequency (the "recurrence"). See http://codex.wordpress.org/Function_Reference/wp_schedule_event
130
	 * If the cron task should NO longer be used, it should have a value of EEH_Activation::cron_task_no_longer_in_use (null)
131
	 *
132
	 * @param string $which_to_include can be 'current' (ones that are currently in use),
133
	 *                          'old' (only returns ones that should no longer be used),or 'all',
134
	 * @return array
135
	 * @throws \EE_Error
136
	 */
137
	public static function get_cron_tasks( $which_to_include ) {
138
		$cron_tasks = apply_filters(
139
			'FHEE__EEH_Activation__get_cron_tasks',
140
			array(
141
				'AHEE__EE_Cron_Tasks__clean_up_junk_transactions' => 'hourly',
142
//				'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions' => EEH_Activation::cron_task_no_longer_in_use, actually this is still in use
143
				'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
144
			)
145
		);
146
		if ( $which_to_include === 'old' ) {
147
			$cron_tasks = array_filter(
148
				$cron_tasks,
149
				function ( $value ) {
150
					return $value === EEH_Activation::cron_task_no_longer_in_use;
151
				}
152
			);
153
		} elseif ( $which_to_include === 'current' ) {
154
			$cron_tasks = array_filter( $cron_tasks );
155
		} elseif ( WP_DEBUG && $which_to_include !== 'all' ) {
156
			throw new EE_Error(
157
				sprintf(
158
					__(
159
						'Invalid argument of "%1$s" passed to EEH_Activation::get_cron_tasks. Valid values are "all", "old" and "current".',
160
						'event_espresso'
161
					),
162
					$which_to_include
163
				)
164
			);
165
		}
166
		return $cron_tasks;
167
	}
168
169
170
171
	/**
172
	 * Ensure cron tasks are setup (the removal of crons should be done by remove_crons())
173
	 *
174
	 * @throws \EE_Error
175
	 */
176
	public static function create_cron_tasks() {
177
178
		foreach( EEH_Activation::get_cron_tasks( 'current' ) as $hook_name => $frequency ) {
179
			if( ! wp_next_scheduled( $hook_name ) ) {
180
				wp_schedule_event( time(), $frequency, $hook_name );
181
			}
182
		}
183
184
	}
185
186
187
188
	/**
189
	 * Remove the currently-existing and now-removed cron tasks.
190
	 *
191
	 * @param boolean $remove_all whether to only remove the old ones, or remove absolutely ALL the EE ones
192
	 * @throws \EE_Error
193
	 */
194
	public static function remove_cron_tasks( $remove_all = true ) {
195
		$cron_tasks_to_remove = $remove_all ? 'all' : 'old';
196
		$crons = _get_cron_array();
197
		$crons = is_array( $crons ) ? $crons : array();
198
		/* reminder of what $crons look like:
199
		 * Top-level keys are timestamps, and their values are arrays.
200
		 * The 2nd level arrays have keys with each of the cron task hook names to run at that time
201
		 * and their values are arrays.
202
		 * The 3rd level level arrays are keys which are hashes of the cron task's arguments,
203
		 *  and their values are the UN-hashed arguments
204
		 * eg
205
		 * array (size=13)
206
		 *		1429903276 =>
207
		 *		  array (size=1)
208
		 *			'AHEE__EE_Cron_Tasks__update_transaction_with_payment' =>
209
		 *			  array (size=1)
210
		 *				'561299d6e42c8e079285870ade0e47e6' =>
211
		 *				  array (size=2)
212
		 *					...
213
		 *      ...
214
		 */
215
		$ee_cron_tasks_to_remove = EEH_Activation::get_cron_tasks( $cron_tasks_to_remove );
216
		foreach ( $crons as $timestamp => $hooks_to_fire_at_time ) {
217
			if ( is_array( $hooks_to_fire_at_time ) ) {
218
				foreach ( $hooks_to_fire_at_time as $hook_name => $hook_actions ) {
219
					if ( isset( $ee_cron_tasks_to_remove[ $hook_name ] )
220
					     && is_array( $ee_cron_tasks_to_remove[ $hook_name ] )
221
					) {
222
						unset( $crons[ $timestamp ][ $hook_name ] );
223
					}
224
				}
225
				//also take care of any empty cron timestamps.
226
				if ( empty( $hooks_to_fire_at_time ) ) {
227
					unset( $crons[ $timestamp ] );
228
				}
229
			}
230
		}
231
		_set_cron_array( $crons );
232
	}
233
234
235
236
	/**
237
	 * 	CPT_initialization
238
	 *	registers all EE CPTs ( Custom Post Types ) then flushes rewrite rules so that all endpoints exist
239
	 *
240
	 * 	@access public
241
	 * 	@static
242
	 * 	@return void
243
	 */
244
	public static function CPT_initialization() {
245
		// register Custom Post Types
246
		EE_Registry::instance()->load_core( 'Register_CPTs' );
247
		flush_rewrite_rules();
248
	}
249
250
251
252
	/**
253
	 * 	reset_and_update_config
254
	 *
255
	 * The following code was moved over from EE_Config so that it will no longer run on every request.
256
	 * If there is old calendar config data saved, then it will get converted on activation.
257
	 * This was basically a DMS before we had DMS's, and will get removed after a few more versions.
258
	 *
259
	 * 	@access public
260
	 * 	@static
261
	 * 	@return void
262
	 */
263
	public static function reset_and_update_config() {
264
		do_action( 'AHEE__EE_Config___load_core_config__start', array( 'EEH_Activation', 'load_calendar_config' ) );
265
		add_filter( 'FHEE__EE_Config___load_core_config__config_settings', array( 'EEH_Activation', 'migrate_old_config_data' ), 10, 3 );
266
		//EE_Config::reset();
267
	}
268
269
270
	/**
271
	 *    load_calendar_config
272
	 *
273
	 * @access    public
274
	 * @return    stdClass
275
	 */
276
	public static function load_calendar_config() {
277
		// grab array of all plugin folders and loop thru it
278
		$plugins = glob( WP_PLUGIN_DIR . DS . '*', GLOB_ONLYDIR );
279
		if ( empty( $plugins ) ) {
280
			return;
281
		}
282
		foreach ( $plugins as $plugin_path ) {
283
			// grab plugin folder name from path
284
			$plugin = basename( $plugin_path );
285
			// drill down to Espresso plugins
286
			// then to calendar related plugins
287
			if (
288
				strpos( $plugin, 'espresso' ) !== FALSE
289
				|| strpos( $plugin, 'Espresso' ) !== FALSE
290
				|| strpos( $plugin, 'ee4' ) !== FALSE
291
				|| strpos( $plugin, 'EE4' ) !== FALSE
292
				|| strpos( $plugin, 'calendar' ) !== false
293
			) {
294
				// this is what we are looking for
295
				$calendar_config = $plugin_path . DS . 'EE_Calendar_Config.php';
296
				// does it exist in this folder ?
297
				if ( is_readable( $calendar_config )) {
298
					// YEAH! let's load it
299
					require_once( $calendar_config );
300
				}
301
			}
302
		}
303
	}
304
305
306
	/**
307
	 *    _migrate_old_config_data
308
	 *
309
	 * @access    public
310
	 * @param array|stdClass $settings
311
	 * @param string         $config
312
	 * @param \EE_Config     $EE_Config
313
	 * @return \stdClass
314
	 */
315
	public static function migrate_old_config_data( $settings = array(), $config = '', EE_Config $EE_Config ) {
316
		$convert_from_array = array( 'addons' );
317
		// in case old settings were saved as an array
318
		if ( is_array( $settings ) && in_array( $config, $convert_from_array )) {
319
			// convert existing settings to an object
320
			$config_array = $settings;
321
			$settings = new stdClass();
322
			foreach ( $config_array as $key => $value ){
323
				if ( $key === 'calendar' && class_exists( 'EE_Calendar_Config' )) {
324
					$EE_Config->set_config( 'addons', 'EE_Calendar', 'EE_Calendar_Config', $value );
325
				} else {
326
					$settings->{$key} = $value;
327
				}
328
			}
329
			add_filter( 'FHEE__EE_Config___load_core_config__update_espresso_config', '__return_true' );
330
		}
331
		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...
332
	}
333
334
335
336
	/**
337
	 * deactivate_event_espresso
338
	 *
339
	 * 	@access public
340
	 * 	@static
341
	 * 	@return void
342
	 */
343
	public static function deactivate_event_espresso() {
344
		// check permissions
345
		if ( current_user_can( 'activate_plugins' )) {
346
			deactivate_plugins( EE_PLUGIN_BASENAME, TRUE );
347
		}
348
	}
349
350
351
352
353
354
	/**
355
	 * verify_default_pages_exist
356
	 *
357
	 * 	@access public
358
	 * 	@static
359
	 * 	@return void
360
	 */
361
	public static function verify_default_pages_exist() {
362
363
		$critical_page_problem = FALSE;
364
365
		$critical_pages = array(
366
			array(
367
				'id' =>'reg_page_id',
368
				'name' => __( 'Registration Checkout', 'event_espresso' ),
369
				'post' => NULL,
370
				'code' => 'ESPRESSO_CHECKOUT'
371
			),
372
			array(
373
				'id' => 'txn_page_id',
374
				'name' => __( 'Transactions', 'event_espresso' ),
375
				'post' => NULL,
376
				'code' => 'ESPRESSO_TXN_PAGE'
377
			),
378
			array(
379
				'id' => 'thank_you_page_id',
380
				'name' => __( 'Thank You', 'event_espresso' ),
381
				'post' => NULL,
382
				'code' => 'ESPRESSO_THANK_YOU'
383
			),
384
			array(
385
				'id' => 'cancel_page_id',
386
				'name' => __( 'Registration Cancelled', 'event_espresso' ),
387
				'post' => NULL,
388
				'code' => 'ESPRESSO_CANCELLED'
389
			),
390
		);
391
392
		$EE_Core_Config = EE_Registry::instance()->CFG->core;
393
394
		foreach ( $critical_pages as $critical_page ) {
395
			// is critical page ID set in config ?
396
			if ( $EE_Core_Config->{$critical_page[ 'id' ]} !== FALSE ) {
397
				// attempt to find post by ID
398
				$critical_page['post'] = get_post( $EE_Core_Config->{$critical_page[ 'id' ]} );
399
			}
400
			// no dice?
401
			if ( $critical_page['post'] === null ) {
402
				// attempt to find post by title
403
				$critical_page['post'] = self::get_page_by_ee_shortcode( $critical_page['code'] );
404
				// still nothing?
405
				if ( $critical_page['post'] === null ) {
406
					$critical_page = EEH_Activation::create_critical_page( $critical_page );
407
					// REALLY? Still nothing ??!?!?
408
					if ( $critical_page['post'] === null ) {
409
						$msg = __( 'The Event Espresso critical page configuration settings could not be updated.', 'event_espresso' );
410
						EE_Error::add_error( $msg, __FILE__, __FUNCTION__, __LINE__ );
411
						break;
412
					}
413
				}
414
			}
415
			// track post_shortcodes
416
			if ( $critical_page['post'] ) {
417
				EEH_Activation::_track_critical_page_post_shortcodes( $critical_page );
418
			}
419
			// check that Post ID matches critical page ID in config
420
			if (
421
				isset( $critical_page['post']->ID )
422
				&& $critical_page['post']->ID !== $EE_Core_Config->{$critical_page[ 'id' ]}
423
			) {
424
				//update Config with post ID
425
				$EE_Core_Config->{$critical_page[ 'id' ]} = $critical_page['post']->ID;
426 View Code Duplication
				if ( ! EE_Config::instance()->update_espresso_config( FALSE, FALSE ) ) {
427
					$msg = __( 'The Event Espresso critical page configuration settings could not be updated.', 'event_espresso' );
428
					EE_Error::add_error( $msg, __FILE__, __FUNCTION__, __LINE__ );
429
				}
430
			}
431
432
			$critical_page_problem =
433
				! isset( $critical_page['post']->post_status )
434
				|| $critical_page['post']->post_status !== 'publish'
435
				|| strpos( $critical_page['post']->post_content, $critical_page['code'] ) === FALSE
436
					? TRUE
437
					: $critical_page_problem;
438
439
		}
440
441
		if ( $critical_page_problem ) {
442
			$msg = sprintf(
443
				__('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' ),
444
				'<a href="' . admin_url('admin.php?page=espresso_general_settings&action=critical_pages') . '">' . __('Event Espresso Critical Pages Settings', 'event_espresso') . '</a>'
445
			);
446
			EE_Error::add_persistent_admin_notice( 'critical_page_problem', $msg );
447
		}
448
		if ( EE_Error::has_notices() ) {
449
			EE_Error::get_notices( FALSE, TRUE, TRUE );
450
		}
451
	}
452
453
	/**
454
	 * Returns the first post which uses the specified shortcode
455
	 * @param string $ee_shortcode usually one of the critical pages shortcodes, eg
456
	 * ESPRESSO_THANK_YOU. So we will search fora post with the content "[ESPRESSO_THANK_YOU"
457
	 * (we don't search for the closing shortcode bracket because they might have added
458
	 * parameter to the shortcode
459
	 * @return WP_Post or NULl
460
	 */
461
	public static function get_page_by_ee_shortcode($ee_shortcode){
462
		global $wpdb;
463
		$shortcode_and_opening_bracket = '['.$ee_shortcode;
464
		$post_id = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_content LIKE '%$shortcode_and_opening_bracket%' LIMIT 1");
465
		if($post_id){
466
			return get_post($post_id);
467
		}else{
468
			return NULL;
469
		}
470
471
//		return $post_id;
472
	}
473
474
475
476
	/**
477
	 *    This function generates a post for critical espresso pages
478
	 *
479
	 * @access public
480
	 * @static
481
	 * @param array $critical_page
482
	 * @return array
483
	 */
484
	public static function create_critical_page( $critical_page ) {
485
486
		$post_args = array(
487
			'post_title' => $critical_page['name'],
488
			'post_status' => 'publish',
489
			'post_type' => 'page',
490
			'comment_status' => 'closed',
491
			'post_content' => '[' . $critical_page['code'] . ']'
492
		);
493
494
		$post_id = wp_insert_post( $post_args );
495
		if ( ! $post_id ) {
496
			$msg = sprintf(
497
				__( 'The Event Espresso  critical page entitled "%s" could not be created.', 'event_espresso' ),
498
				$critical_page['name']
499
			);
500
			EE_Error::add_error( $msg, __FILE__, __FUNCTION__, __LINE__ );
501
			return $critical_page;
502
		}
503
		// get newly created post's details
504
		if ( ! $critical_page['post'] = get_post( $post_id )) {
505
			$msg = sprintf(
506
				__( 'The Event Espresso critical page entitled "%s" could not be retrieved.', 'event_espresso' ),
507
				$critical_page['name']
508
			);
509
			EE_Error::add_error( $msg, __FILE__, __FUNCTION__, __LINE__ );
510
		}
511
512
		return $critical_page;
513
514
	}
515
516
517
518
519
520
	/**
521
	 *    This function adds a critical page's shortcode to the post_shortcodes array
522
	 *
523
	 * @access private
524
	 * @static
525
	 * @param array $critical_page
526
	 * @return void
527
	 */
528
	private static function _track_critical_page_post_shortcodes( $critical_page = array() ) {
529
		// check the goods
530 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...
531
			$msg = sprintf(
532
				__( 'The Event Espresso critical page shortcode for the page %s can not be tracked because it is not a WP_Post object.', 'event_espresso' ),
533
				$critical_page['name']
534
			);
535
			EE_Error::add_error( $msg, __FILE__, __FUNCTION__, __LINE__ );
536
			return;
537
		}
538
		$EE_Core_Config = EE_Registry::instance()->CFG->core;
539
		// map shortcode to post
540
		$EE_Core_Config->post_shortcodes[ $critical_page['post']->post_name ][ $critical_page['code'] ] = $critical_page['post']->ID;
541
		// and make sure it's NOT added to the WP "Posts Page"
542
		// name of the WP Posts Page
543
		$posts_page = EE_Config::get_page_for_posts();
544
		if ( isset( $EE_Core_Config->post_shortcodes[ $posts_page ] )) {
545
			unset( $EE_Core_Config->post_shortcodes[ $posts_page ][ $critical_page['code'] ] );
546
		}
547
		if ( $posts_page !== 'posts' && isset( $EE_Core_Config->post_shortcodes['posts'] )) {
548
			unset( $EE_Core_Config->post_shortcodes['posts'][ $critical_page['code'] ] );
549
		}
550
		// update post_shortcode CFG
551
		if ( ! EE_Config::instance()->update_espresso_config( FALSE, FALSE )) {
552
			$msg = sprintf(
553
				__( 'The Event Espresso critical page shortcode for the %s page could not be configured properly.', 'event_espresso' ),
554
				$critical_page['name']
555
			);
556
			EE_Error::add_error( $msg, __FILE__, __FUNCTION__, __LINE__ );
557
		}
558
	}
559
560
561
562
	/**
563
	 * Tries to find the oldest admin for this site.  If there are no admins for this site then return NULL.
564
	 * The role being used to check is filterable.
565
	 *
566
	 * @since  4.6.0
567
	 * @global WPDB $wpdb
568
	 *
569
	 * @return mixed null|int WP_user ID or NULL
570
	 */
571
	public static function get_default_creator_id() {
572
		global $wpdb;
573
574
		if ( ! empty( self::$_default_creator_id ) ) {
575
			return self::$_default_creator_id;
576
		}/**/
577
578
		$role_to_check = apply_filters( 'FHEE__EEH_Activation__get_default_creator_id__role_to_check', 'administrator' );
579
580
		//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.
581
		$pre_filtered_id = apply_filters( 'FHEE__EEH_Activation__get_default_creator_id__pre_filtered_id', false, $role_to_check );
582
		if ( $pre_filtered_id !== false ) {
583
			return (int) $pre_filtered_id;
584
		}
585
586
		$capabilities_key = EEH_Activation::ensure_table_name_has_prefix( 'capabilities' );
587
		$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 . '%' );
588
		$user_id = $wpdb->get_var( $query );
589
		 $user_id = apply_filters( 'FHEE__EEH_Activation_Helper__get_default_creator_id__user_id', $user_id );
590
		 if ( $user_id && (int)$user_id ) {
591
		 	self::$_default_creator_id = (int)$user_id;
592
		 	return self::$_default_creator_id;
593
		 } else {
594
		 	return NULL;
595
		 }
596
	}
597
598
599
600
601
602
	/**
603
	 * 	used by EE and EE addons during plugin activation
604
	 *
605
	 * 	@access public
606
	 * 	@static
607
	 * @param string $table_name without the $wpdb->prefix
608
	 * @param string $sql SQL for creating the table (contents between brackets in an SQL create table query)
609
	 * @param string $engine like 'ENGINE=MyISAM' or 'ENGINE=InnoDB'
610
	 * @param boolean $drop_pre_existing_table set to TRUE when you want to make SURE the table is completely empty
611
	 * and new once this function is done (ie, you really do want to CREATE a table, and
612
	 * expect it to be empty once you're done)
613
	 * leave as FALSE when you just want to verify the table exists and matches this definition (and if it
614
	 * HAS data in it you want to leave it be)
615
	 * 	@return void
616
	 * @throws EE_Error if there are database errors
617
	 */
618
	public static function create_table( $table_name, $sql, $engine = 'ENGINE=MyISAM ', $drop_pre_existing_table = false ) {
619
		if( apply_filters( 'FHEE__EEH_Activation__create_table__short_circuit', FALSE, $table_name, $sql ) ){
620
			return;
621
		}
622
		do_action( 'AHEE_log', __FILE__, __FUNCTION__, '' );
623
		if ( ! function_exists( 'dbDelta' )) {
624
			require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
625
		}
626
		/** @var WPDB $wpdb */
627
		global $wpdb;
628
		$wp_table_name = EEH_Activation::ensure_table_name_has_prefix( $table_name );
629
		// do we need to first delete an existing version of this table ?
630
		if ( $drop_pre_existing_table && EEH_Activation::table_exists( $wp_table_name ) ){
631
			// ok, delete the table... but ONLY if it's empty
632
			$deleted_safely = EEH_Activation::delete_db_table_if_empty( $wp_table_name );
633
			// table is NOT empty, are you SURE you want to delete this table ???
634
			if ( ! $deleted_safely && defined( 'EE_DROP_BAD_TABLES' ) && EE_DROP_BAD_TABLES ){
635
				EEH_Activation::delete_unused_db_table( $wp_table_name );
636
			} else if ( ! $deleted_safely ) {
637
				// so we should be more cautious rather than just dropping tables so easily
638
				EE_Error::add_persistent_admin_notice(
639
						'bad_table_' . $wp_table_name . '_detected',
640
						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' ),
641
								$wp_table_name,
642
								"<pre>define( 'EE_DROP_BAD_TABLES', TRUE );</pre>",
643
								'<b>wp-config.php</b>',
644
								'<br/>'),
645
								TRUE );
646
			}
647
		}
648
		// does $sql contain valid column information? ( LPT: https://regex101.com/ is great for working out regex patterns )
649
		if ( preg_match( '((((.*?))(,\s))+)', $sql, $valid_column_data ) ) {
650
			$SQL = "CREATE TABLE $wp_table_name ( $sql ) $engine DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;";
651
			//get $wpdb to echo errors, but buffer them. This way at least WE know an error
652
			//happened. And then we can choose to tell the end user
653
			$old_show_errors_policy = $wpdb->show_errors( TRUE );
654
			$old_error_suppression_policy = $wpdb->suppress_errors( FALSE );
655
			ob_start();
656
			dbDelta( $SQL );
657
			$output = ob_get_contents();
658
			ob_end_clean();
659
			$wpdb->show_errors( $old_show_errors_policy );
660
			$wpdb->suppress_errors( $old_error_suppression_policy );
661
			if( ! empty( $output ) ){
662
				throw new EE_Error( $output	);
663
			}
664
		} else {
665
			throw new EE_Error(
666
				sprintf(
667
					__( 'The following table creation SQL does not contain valid information about the table columns: %1$s %2$s', 'event_espresso' ),
668
					'<br />',
669
					$sql
670
				)
671
			);
672
		}
673
674
	}
675
676
677
678
	/**
679
	 *    add_column_if_it_doesn't_exist
680
	 *    Checks if this column already exists on the specified table. Handy for addons which want to add a column
681
	 *
682
	 * @access public
683
	 * @static
684
	 * @param string $table_name  (without "wp_", eg "esp_attendee"
685
	 * @param string $column_name
686
	 * @param string $column_info if your SQL were 'ALTER TABLE table_name ADD price VARCHAR(10)', this would be 'VARCHAR(10)'
687
	 * @return bool|int
688
	 */
689
	public static function add_column_if_it_doesnt_exist($table_name,$column_name,$column_info='INT UNSIGNED NOT NULL'){
690
		if( apply_filters( 'FHEE__EEH_Activation__add_column_if_it_doesnt_exist__short_circuit', FALSE ) ){
691
			return FALSE;
692
		}
693
		global $wpdb;
694
		$full_table_name= EEH_Activation::ensure_table_name_has_prefix( $table_name );
695
		$fields = self::get_fields_on_table($table_name);
696
		if (!in_array($column_name, $fields)){
697
			$alter_query="ALTER TABLE $full_table_name ADD $column_name $column_info";
698
			//echo "alter query:$alter_query";
699
			return $wpdb->query($alter_query);
700
		}
701
		return TRUE;
702
	}
703
704
705
706
707
	/**
708
	 * get_fields_on_table
709
	 * Gets all the fields on the database table.
710
	 *
711
	 * 	@access public
712
	 * 	@static
713
	 * 	@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...
714
	 * 	@return array of database column names
715
	 */
716
	public static function get_fields_on_table( $table_name = NULL ) {
717
		global $wpdb;
718
		$table_name= EEH_Activation::ensure_table_name_has_prefix( $table_name );
719
		if ( ! empty( $table_name )) {
720
			$columns = $wpdb->get_results("SHOW COLUMNS FROM $table_name ");
721
			if ($columns !== FALSE) {
722
				$field_array = array();
723
				foreach($columns as $column ){
724
					$field_array[] = $column->Field;
725
				}
726
				return $field_array;
727
			}
728
		}
729
		return FALSE;
730
	}
731
732
733
734
	/**
735
	 * db_table_is_empty
736
	 *
737
	 * @access public
738
	 * @static
739
	 * @param string $table_name
740
	 * @return bool
741
	 */
742
	public static function db_table_is_empty( $table_name ) {
743
		global $wpdb;
744
		$table_name = EEH_Activation::ensure_table_name_has_prefix( $table_name );
745
		if ( EEH_Activation::table_exists( $table_name ) ) {
746
			$count = $wpdb->get_var( "SELECT COUNT(*) FROM $table_name" );
747
			return absint( $count ) === 0 ? true : false;
748
		}
749
		return false;
750
	}
751
752
753
754
	/**
755
	 * delete_db_table_if_empty
756
	 *
757
	 * @access public
758
	 * @static
759
	 * @param string $table_name
760
	 * @return bool | int
761
	 */
762
	public static function delete_db_table_if_empty( $table_name ) {
763
		if ( EEH_Activation::db_table_is_empty( $table_name ) ) {
764
			return EEH_Activation::delete_unused_db_table( $table_name );
765
		}
766
		return false;
767
	}
768
769
770
771
	/**
772
	 * delete_unused_db_table
773
	 *
774
	 * @access public
775
	 * @static
776
	 * @param string $table_name
777
	 * @return bool | int
778
	 */
779
	public static function delete_unused_db_table( $table_name ) {
780
		global $wpdb;
781
		if ( EEH_Activation::table_exists( $table_name ) ) {
782
			$table_name = EEH_Activation::ensure_table_name_has_prefix( $table_name );
783
			return $wpdb->query( "DROP TABLE IF EXISTS $table_name" );
784
		}
785
		return false;
786
	}
787
788
789
790
	/**
791
	 * drop_index
792
	 *
793
	 * @access public
794
	 * @static
795
	 * @param string $table_name
796
	 * @param string $index_name
797
	 * @return bool | int
798
	 */
799
	public static function drop_index( $table_name, $index_name ) {
800
		if( apply_filters( 'FHEE__EEH_Activation__drop_index__short_circuit', FALSE ) ){
801
			return FALSE;
802
		}
803
		global $wpdb;
804
		$table_name = EEH_Activation::ensure_table_name_has_prefix( $table_name );
805
		$index_exists_query = "SHOW INDEX FROM $table_name WHERE Key_name = '$index_name'";
806
		if (
807
			$wpdb->get_var( "SHOW TABLES LIKE '$table_name'" ) === $table_name
808
			&& $wpdb->get_var( $index_exists_query ) === $table_name //using get_var with the $index_exists_query returns the table's name
809
		) {
810
			return $wpdb->query( "ALTER TABLE $table_name DROP INDEX $index_name" );
811
		}
812
		return TRUE;
813
	}
814
815
816
817
	/**
818
	 * create_database_tables
819
	 *
820
	 * @access public
821
	 * @static
822
	 * @throws EE_Error
823
	 * @return boolean success (whether database is setup properly or not)
824
	 */
825
	public static function create_database_tables() {
826
		EE_Registry::instance()->load_core( 'Data_Migration_Manager' );
827
		//find the migration script that sets the database to be compatible with the code
828
		$dms_name = EE_Data_Migration_Manager::instance()->get_most_up_to_date_dms();
829
		if( $dms_name ){
830
			$current_data_migration_script = EE_Registry::instance()->load_dms( $dms_name );
831
			$current_data_migration_script->set_migrating( false );
0 ignored issues
show
Bug introduced by
The method set_migrating cannot be called on $current_data_migration_script (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
832
			$current_data_migration_script->schema_changes_before_migration();
0 ignored issues
show
Bug introduced by
The method schema_changes_before_migration cannot be called on $current_data_migration_script (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
833
			$current_data_migration_script->schema_changes_after_migration();
0 ignored issues
show
Bug introduced by
The method schema_changes_after_migration cannot be called on $current_data_migration_script (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
834 View Code Duplication
			if( $current_data_migration_script->get_errors() ){
0 ignored issues
show
Bug introduced by
The method get_errors cannot be called on $current_data_migration_script (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
835
				if( WP_DEBUG ){
836
					foreach( $current_data_migration_script->get_errors() as $error ){
0 ignored issues
show
Bug introduced by
The method get_errors cannot be called on $current_data_migration_script (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
837
						EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__ );
838
					}
839
				}else{
840
					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' ) );
841
				}
842
				return false;
843
			}
844
			EE_Data_Migration_Manager::instance()->update_current_database_state_to();
845
		}else{
846
			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__);
847
			return false;
848
		}
849
		return true;
850
	}
851
852
853
854
855
856
	/**
857
	 * initialize_system_questions
858
	 *
859
	 * 	@access public
860
	 * 	@static
861
	 * 	@return void
862
	 */
863
	public static function initialize_system_questions() {
864
		// QUESTION GROUPS
865
		global $wpdb;
866
		$table_name = EEH_Activation::ensure_table_name_has_prefix( 'esp_question_group' );
867
		$SQL = "SELECT QSG_system FROM $table_name WHERE QSG_system != 0";
868
		// what we have
869
		$question_groups = $wpdb->get_col( $SQL );
870
		// check the response
871
		$question_groups = is_array( $question_groups ) ? $question_groups : array();
872
		// what we should have
873
		$QSG_systems = array( 1, 2 );
874
		// loop thru what we should have and compare to what we have
875
		foreach ( $QSG_systems as $QSG_system ) {
876
			// reset values array
877
			$QSG_values = array();
878
			// 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)
879
			if ( ! in_array( "$QSG_system", $question_groups )) {
880
				// add it
881
				switch ( $QSG_system ) {
882
883 View Code Duplication
					case 1:
884
							$QSG_values = array(
885
									'QSG_name' => __( 'Personal Information', 'event_espresso' ),
886
									'QSG_identifier' => 'personal-information-' . time(),
887
									'QSG_desc' => '',
888
									'QSG_order' => 1,
889
									'QSG_show_group_name' => 1,
890
									'QSG_show_group_desc' => 1,
891
									'QSG_system' => EEM_Question_Group::system_personal,
892
									'QSG_deleted' => 0
893
								);
894
						break;
895
896 View Code Duplication
					case 2:
897
							$QSG_values = array(
898
									'QSG_name' => __( 'Address Information','event_espresso' ),
899
									'QSG_identifier' => 'address-information-' . time(),
900
									'QSG_desc' => '',
901
									'QSG_order' => 2,
902
									'QSG_show_group_name' => 1,
903
									'QSG_show_group_desc' => 1,
904
									'QSG_system' => EEM_Question_Group::system_address,
905
									'QSG_deleted' => 0
906
								);
907
						break;
908
909
				}
910
				// make sure we have some values before inserting them
911
				if ( ! empty( $QSG_values )) {
912
					// insert system question
913
					$wpdb->insert(
914
						$table_name,
915
						$QSG_values,
916
						array('%s', '%s', '%s', '%d', '%d', '%d', '%d', '%d' )
917
					);
918
					$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...
919
				}
920
			}
921
		}
922
923
924
925
		// QUESTIONS
926
		global $wpdb;
927
		$table_name = EEH_Activation::ensure_table_name_has_prefix( 'esp_question' );
928
		$SQL = "SELECT QST_system FROM $table_name WHERE QST_system != ''";
929
		// what we have
930
		$questions = $wpdb->get_col( $SQL );
931
		// what we should have
932
		$QST_systems = array(
933
			'fname',
934
			'lname',
935
			'email',
936
			'address',
937
			'address2',
938
			'city',
939
			'state',
940
			'country',
941
			'zip',
942
			'phone'
943
		);
944
		$order_for_group_1 = 1;
945
		$order_for_group_2 = 1;
946
		// loop thru what we should have and compare to what we have
947
		foreach ( $QST_systems as $QST_system ) {
948
			// reset values array
949
			$QST_values = array();
950
			// if we don't have what we should have
951
			if ( ! in_array( $QST_system, $questions )) {
952
				// add it
953
				switch ( $QST_system ) {
954
955 View Code Duplication
					case 'fname':
956
							$QST_values = array(
957
									'QST_display_text' => __( 'First Name', 'event_espresso' ),
958
									'QST_admin_label' => __( 'First Name - System Question', 'event_espresso' ),
959
									'QST_system' => 'fname',
960
									'QST_type' => 'TEXT',
961
									'QST_required' => 1,
962
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
963
									'QST_order' => 1,
964
									'QST_admin_only' => 0,
965
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
966
									'QST_wp_user' => self::get_default_creator_id(),
967
									'QST_deleted' => 0
968
								);
969
						break;
970
971 View Code Duplication
					case 'lname':
972
							$QST_values = array(
973
									'QST_display_text' => __( 'Last Name', 'event_espresso' ),
974
									'QST_admin_label' => __( 'Last Name - System Question', 'event_espresso' ),
975
									'QST_system' => 'lname',
976
									'QST_type' => 'TEXT',
977
									'QST_required' => 1,
978
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
979
									'QST_order' => 2,
980
									'QST_admin_only' => 0,
981
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
982
									'QST_wp_user' => self::get_default_creator_id(),
983
									'QST_deleted' => 0
984
								);
985
						break;
986
987 View Code Duplication
					case 'email':
988
							$QST_values = array(
989
									'QST_display_text' => __( 'Email Address', 'event_espresso' ),
990
									'QST_admin_label' => __( 'Email Address - System Question', 'event_espresso' ),
991
									'QST_system' => 'email',
992
									'QST_type' => 'TEXT',
993
									'QST_required' => 1,
994
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
995
									'QST_order' => 3,
996
									'QST_admin_only' => 0,
997
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
998
									'QST_wp_user' => self::get_default_creator_id(),
999
									'QST_deleted' => 0
1000
								);
1001
						break;
1002
1003 View Code Duplication
					case 'address':
1004
							$QST_values = array(
1005
									'QST_display_text' => __( 'Address', 'event_espresso' ),
1006
									'QST_admin_label' => __( 'Address - System Question', 'event_espresso' ),
1007
									'QST_system' => 'address',
1008
									'QST_type' => 'TEXT',
1009
									'QST_required' => 0,
1010
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
1011
									'QST_order' => 4,
1012
									'QST_admin_only' => 0,
1013
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
1014
									'QST_wp_user' => self::get_default_creator_id(),
1015
									'QST_deleted' => 0
1016
								);
1017
						break;
1018
1019 View Code Duplication
					case 'address2':
1020
							$QST_values = array(
1021
									'QST_display_text' => __( 'Address2', 'event_espresso' ),
1022
									'QST_admin_label' => __( 'Address2 - System Question', 'event_espresso' ),
1023
									'QST_system' => 'address2',
1024
									'QST_type' => 'TEXT',
1025
									'QST_required' => 0,
1026
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
1027
									'QST_order' => 5,
1028
									'QST_admin_only' => 0,
1029
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
1030
									'QST_wp_user' => self::get_default_creator_id(),
1031
									'QST_deleted' => 0
1032
								);
1033
						break;
1034
1035 View Code Duplication
					case 'city':
1036
							$QST_values = array(
1037
									'QST_display_text' => __( 'City', 'event_espresso' ),
1038
									'QST_admin_label' => __( 'City - System Question', 'event_espresso' ),
1039
									'QST_system' => 'city',
1040
									'QST_type' => 'TEXT',
1041
									'QST_required' => 0,
1042
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
1043
									'QST_order' => 6,
1044
									'QST_admin_only' => 0,
1045
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
1046
									'QST_wp_user' => self::get_default_creator_id(),
1047
									'QST_deleted' => 0
1048
								);
1049
						break;
1050
1051 View Code Duplication
					case 'state':
1052
							$QST_values = array(
1053
									'QST_display_text' => __( 'State/Province', 'event_espresso' ),
1054
									'QST_admin_label' => __( 'State/Province - System Question', 'event_espresso' ),
1055
									'QST_system' => 'state',
1056
									'QST_type' => 'STATE',
1057
									'QST_required' => 0,
1058
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
1059
									'QST_order' => 7,
1060
									'QST_admin_only' => 0,
1061
									'QST_wp_user' => self::get_default_creator_id(),
1062
									'QST_deleted' => 0
1063
								);
1064
						break;
1065
1066 View Code Duplication
					case 'country' :
1067
							$QST_values = array(
1068
									'QST_display_text' => __( 'Country', 'event_espresso' ),
1069
									'QST_admin_label' => __( 'Country - System Question', 'event_espresso' ),
1070
									'QST_system' => 'country',
1071
									'QST_type' => 'COUNTRY',
1072
									'QST_required' => 0,
1073
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
1074
									'QST_order' => 8,
1075
									'QST_admin_only' => 0,
1076
									'QST_wp_user' => self::get_default_creator_id(),
1077
									'QST_deleted' => 0
1078
								);
1079
						break;
1080
1081 View Code Duplication
					case 'zip':
1082
							$QST_values = array(
1083
									'QST_display_text' => __( 'Zip/Postal Code', 'event_espresso' ),
1084
									'QST_admin_label' => __( 'Zip/Postal Code - System Question', 'event_espresso' ),
1085
									'QST_system' => 'zip',
1086
									'QST_type' => 'TEXT',
1087
									'QST_required' => 0,
1088
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
1089
									'QST_order' => 9,
1090
									'QST_admin_only' => 0,
1091
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
1092
									'QST_wp_user' => self::get_default_creator_id(),
1093
									'QST_deleted' => 0
1094
								);
1095
						break;
1096
1097 View Code Duplication
					case 'phone':
1098
							$QST_values = array(
1099
									'QST_display_text' => __( 'Phone Number', 'event_espresso' ),
1100
									'QST_admin_label' => __( 'Phone Number - System Question', 'event_espresso' ),
1101
									'QST_system' => 'phone',
1102
									'QST_type' => 'TEXT',
1103
									'QST_required' => 0,
1104
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
1105
									'QST_order' => 10,
1106
									'QST_admin_only' => 0,
1107
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
1108
									'QST_wp_user' => self::get_default_creator_id(),
1109
									'QST_deleted' => 0
1110
								);
1111
						break;
1112
1113
				}
1114
				if ( ! empty( $QST_values )) {
1115
					// insert system question
1116
					$wpdb->insert(
1117
						$table_name,
1118
						$QST_values,
1119
						array( '%s', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%d', '%d' )
1120
					);
1121
					$QST_ID = $wpdb->insert_id;
1122
1123
					// QUESTION GROUP QUESTIONS
1124
					if(  in_array( $QST_system, array( 'fname', 'lname', 'email' ) ) ) {
1125
						$system_question_we_want = EEM_Question_Group::system_personal;
1126
					} else {
1127
						$system_question_we_want = EEM_Question_Group::system_address;
1128
					}
1129
					if( isset( $QSG_IDs[ $system_question_we_want ] ) ) {
1130
						$QSG_ID = $QSG_IDs[ $system_question_we_want ];
1131
					} else {
1132
						$id_col = EEM_Question_Group::instance()->get_col( array( array( 'QSG_system' => $system_question_we_want ) ) );
1133
						if( is_array( $id_col ) ) {
1134
							$QSG_ID = reset( $id_col );
1135
						} else {
1136
							//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
1137
                                                        EE_Log::instance()->log(
1138
                                                                __FILE__,
1139
                                                                __FUNCTION__,
1140
                                                                sprintf(
1141
                                                                        __( 'Could not associate question %1$s to a question group because no system question group existed', 'event_espresso'),
1142
                                                                        $QST_ID ),
1143
                                                                'error' );
1144
                                                        continue;
1145
						}
1146
					}
1147
1148
					// add system questions to groups
1149
					$wpdb->insert(
1150
						EEH_Activation::ensure_table_name_has_prefix( 'esp_question_group_question' ),
1151
						array( 'QSG_ID'    => $QSG_ID,
1152
						       'QST_ID'    => $QST_ID,
1153
						       'QGQ_order' => ( $QSG_ID === 1 ) ? $order_for_group_1++ : $order_for_group_2++
1154
						),
1155
						array( '%d', '%d', '%d' )
1156
					);
1157
				}
1158
			}
1159
		}
1160
1161
	}
1162
1163
1164
1165
	/**
1166
	 * Makes sure the default payment method (Invoice) is active.
1167
	 * This used to be done automatically as part of constructing the old gateways config
1168
	 *
1169
	 * @throws \EE_Error
1170
	 */
1171
	public static function insert_default_payment_methods(){
1172
		if( ! EEM_Payment_Method::instance()->count_active( EEM_Payment_Method::scope_cart ) ){
1173
			EE_Registry::instance()->load_lib( 'Payment_Method_Manager' );
1174
			EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type( 'Invoice' );
1175
		}else{
1176
			EEM_Payment_Method::instance()->verify_button_urls();
1177
		}
1178
	}
1179
1180
	/**
1181
	 * insert_default_status_codes
1182
	 *
1183
	 * 	@access public
1184
	 * 	@static
1185
	 * 	@return void
1186
	 */
1187
	public static function insert_default_status_codes() {
1188
1189
		global $wpdb;
1190
1191
		if ( EEH_Activation::table_exists( EEM_Status::instance()->table() ) ) {
1192
1193
			$table_name = EEM_Status::instance()->table();
1194
1195
			$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' );";
1196
			$wpdb->query($SQL);
1197
1198
			$SQL = "INSERT INTO $table_name
1199
					(STS_ID, STS_code, STS_type, STS_can_edit, STS_desc, STS_open) VALUES
1200
					('ACT', 'ACTIVE', 'event', 0, NULL, 1),
1201
					('NAC', 'NOT_ACTIVE', 'event', 0, NULL, 0),
1202
					('NOP', 'REGISTRATION_NOT_OPEN', 'event', 0, NULL, 1),
1203
					('OPN', 'REGISTRATION_OPEN', 'event', 0, NULL, 1),
1204
					('CLS', 'REGISTRATION_CLOSED', 'event', 0, NULL, 0),
1205
					('PND', 'PENDING', 'event', 0, NULL, 1),
1206
					('ONG', 'ONGOING', 'event', 0, NULL, 1),
1207
					('SEC', 'SECONDARY', 'event', 0, NULL, 1),
1208
					('DRF', 'DRAFT', 'event', 0, NULL, 0),
1209
					('DEL', 'DELETED', 'event', 0, NULL, 0),
1210
					('DEN', 'DENIED', 'event', 0, NULL, 0),
1211
					('EXP', 'EXPIRED', 'event', 0, NULL, 0),
1212
					('RPP', 'PENDING_PAYMENT', 'registration', 0, NULL, 1),
1213
					('RAP', 'APPROVED', 'registration', 0, NULL, 1),
1214
					('RCN', 'CANCELLED', 'registration', 0, NULL, 0),
1215
					('RDC', 'DECLINED', 'registration', 0, NULL, 0),
1216
					('RNA', 'NOT_APPROVED', 'registration', 0, NULL, 1),
1217
					('RIC', 'INCOMPLETE', 'registration', 0, NULL, 1),
1218
					('TFL', 'FAILED', 'transaction', 0, NULL, 0),
1219
					('TAB', 'ABANDONED', 'transaction', 0, NULL, 0),
1220
					('TIN', 'INCOMPLETE', 'transaction', 0, NULL, 1),
1221
					('TCM', 'COMPLETE', 'transaction', 0, NULL, 1),
1222
					('TOP',	'OVERPAID', 'transaction', 0, NULL, 1),
1223
					('PAP', 'APPROVED', 'payment', 0, NULL, 1),
1224
					('PPN', 'PENDING', 'payment', 0, NULL, 1),
1225
					('PCN', 'CANCELLED', 'payment', 0, NULL, 0),
1226
					('PFL', 'FAILED', 'payment', 0, NULL, 0),
1227
					('PDC', 'DECLINED', 'payment', 0, NULL, 0),
1228
					('EDR', 'DRAFT', 'email', 0, NULL, 0),
1229
					('ESN', 'SENT', 'email', 0, NULL, 1);";
1230
			$wpdb->query($SQL);
1231
1232
		}
1233
1234
	}
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
	/**
1249
	 * create_upload_directories
1250
	 * Creates folders in the uploads directory to facilitate addons and templates
1251
	 *
1252
	 * 	@access public
1253
	 * 	@static
1254
	 * 	@return boolean success of verifying upload directories exist
1255
	 */
1256
	public static function create_upload_directories() {
1257
		EE_Registry::instance()->load_helper( 'File' );
1258
		// Create the required folders
1259
		$folders = array(
1260
				EVENT_ESPRESSO_TEMPLATE_DIR,
1261
				EVENT_ESPRESSO_GATEWAY_DIR,
1262
				EVENT_ESPRESSO_UPLOAD_DIR . 'logs/',
1263
				EVENT_ESPRESSO_UPLOAD_DIR . 'css/',
1264
				EVENT_ESPRESSO_UPLOAD_DIR . 'tickets/'
1265
		);
1266
		foreach ( $folders as $folder ) {
1267
			try {
1268
				EEH_File::ensure_folder_exists_and_is_writable( $folder );
1269
				@ 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...
1270
			} catch( EE_Error $e ){
1271
				EE_Error::add_error(
1272
					sprintf(
1273
						__(  'Could not create the folder at "%1$s" because: %2$s', 'event_espresso' ),
1274
						$folder,
1275
						'<br />' . $e->getMessage()
1276
					),
1277
					__FILE__, __FUNCTION__, __LINE__
1278
				);
1279
				//indicate we'll need to fix this later
1280
				update_option( EEH_Activation::upload_directories_incomplete_option_name, true );
1281
				return FALSE;
1282
			}
1283
		}
1284
		//just add the .htaccess file to the logs directory to begin with. Even if logging
1285
		//is disabled, there might be activation errors recorded in there
1286
		EEH_File::add_htaccess_deny_from_all( EVENT_ESPRESSO_UPLOAD_DIR . 'logs/' );
1287
		//remember EE's folders are all good
1288
		delete_option( EEH_Activation::upload_directories_incomplete_option_name );
1289
		return TRUE;
1290
	}
1291
1292
	/**
1293
	 * Whether the upload directories need to be fixed or not.
1294
	 * If EE is installed but filesystem access isn't initially available,
1295
	 * we need to get the user's filesystem credentials and THEN create them,
1296
	 * so there might be period of time when EE is installed but its
1297
	 * upload directories aren't available. This indicates such a state
1298
	 * @return boolean
1299
	 */
1300
	public static function upload_directories_incomplete() {
1301
		return get_option( EEH_Activation::upload_directories_incomplete_option_name, false );
1302
	}
1303
1304
1305
1306
	/**
1307
	 * generate_default_message_templates
1308
	 *
1309
	 * @access public
1310
	 * @static
1311
	 * @return bool | array
1312
	 * @throws \EE_Error
1313
	 */
1314
	public static function generate_default_message_templates() {
1315
1316
		$success = FALSE;
1317
		$installed_messengers = $default_messengers = array();
1318
1319
		//include our helper
1320
		EE_Registry::instance()->load_helper( 'MSG_Template' );
1321
1322
		//get all installed messenger objects
1323
		$installed = EEH_MSG_Template::get_installed_message_objects();
1324
1325
		//let's setup the $installed messengers in an array AND the messengers that are set to be activated on install.
1326
		foreach ( $installed['messengers'] as $msgr ) {
1327
			if ( $msgr instanceof EE_messenger ) {
1328
				$installed_messengers[$msgr->name] = $msgr;
1329
				if ( $msgr->activate_on_install ) {
1330
					$default_messengers[] = $msgr->name;
1331
				}
1332
			}
1333
		}
1334
1335
		//let's determine if we've already got an active messengers option
1336
		$active_messengers = EEH_MSG_Template::get_active_messengers_in_db();
1337
1338
		//things that have already been activated before
1339
		$has_activated = get_option( 'ee_has_activated_messenger' );
1340
1341
		//do an initial loop to determine if we need to continue
1342
		$def_ms = array();
1343
		foreach ( $default_messengers as $msgr ) {
1344
			if ( isset($active_messengers[$msgr] ) || isset( $has_activated[$msgr] ) ) {
1345
				continue;
1346
			}
1347
			$def_ms[] = $msgr;
1348
		}
1349
1350
		//setup the $installed_mts in an array
1351
		foreach ( $installed['message_types'] as $imt ) {
1352
			if ( $imt instanceof EE_message_type ) {
1353
				$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...
1354
			}
1355
		}
1356
1357
		//loop through default array for default messengers (if present)
1358
		if ( ! empty( $def_ms ) ) {
1359
			foreach ( $def_ms as $messenger ) {
1360
				//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.
1361
				if ( ! isset( $installed_messengers[$messenger] )) {
1362
					continue;
1363
				}
1364
				/** @var EE_messenger[] $installed_messengers  */
1365
				$default_mts = $installed_messengers[$messenger]->get_default_message_types();
1366
				$active_messengers[$messenger]['obj'] = $installed_messengers[$messenger];
1367
				foreach ( $default_mts as $index => $mt ) {
1368
					//is there an installed_mt matching the default string?  If not then nothing to do here.
1369
					if ( ! isset( $installed_mts[$mt] ) ) {
1370
						unset( $default_mts[$index] );
1371
						continue;
1372
					}
1373
1374
1375
					//we need to setup any initial settings for message types
1376
					/** @var EE_message_type[] $installed_mts */
1377
					$settings_fields = $installed_mts[$mt]->get_admin_settings_fields();
1378
					$settings = array();
1379 View Code Duplication
					if ( is_array( $settings_fields ) ) {
1380
						foreach ( $settings_fields as $field => $values ) {
1381
							if ( isset( $values['default'] ) ) {
1382
								$settings[$field] = $values['default'];
1383
							}
1384
						}
1385
					}
1386
1387
					$active_messengers[$messenger]['settings'][$messenger . '-message_types'][$mt]['settings'] = $settings;
1388
					$has_activated[$messenger][] = $mt;
1389
				}
1390
1391
				//setup any initial settings for the messenger
1392
				$msgr_settings = $installed_messengers[$messenger]->get_admin_settings_fields();
1393
1394 View Code Duplication
				if ( !empty( $msgr_settings ) ) {
1395
					foreach ( $msgr_settings as $field => $value ) {
1396
						$active_messengers[$messenger]['settings'][$field] = $value;
1397
					}
1398
				}
1399
1400
				//now let's save the settings for this messenger! Must do now because the validator checks the db for active messengers to validate.
1401
				EEH_MSG_Template::update_active_messengers_in_db( $active_messengers );
1402
1403
				//let's generate all the templates but only if the messenger has default_mts (otherwise its just activated).
1404
				if ( !empty( $default_mts ) ) {
1405
					$success = EEH_MSG_Template::generate_new_templates( $messenger, $default_mts, '', TRUE );
1406
				}
1407
			}
1408
		} //end check for empty( $def_ms )
1409
1410
		//still need to see if there are any message types to activate for active messengers
1411
		foreach ( $active_messengers as $messenger => $settings ) {
1412
			$msg_obj = $settings['obj'];
1413
			if ( ! $msg_obj instanceof EE_messenger ) {
1414
				continue;
1415
			}
1416
1417
			$all_default_mts = $msg_obj->get_default_message_types();
1418
			$new_default_mts = array();
1419
1420
			//loop through each default mt reported by the messenger and make sure its set in its active db entry.
1421
			foreach( $all_default_mts as $index => $mt ) {
1422
				//already active? already has generated templates? || has already been activated before (we dont' want to reactivate things users intentionally deactivated).
1423
				if (
1424
					isset( $active_messengers[ $messenger ]['settings'][ $messenger . '-message_types' ][ $mt ] )
1425
					|| ( isset( $has_activated[ $messenger ] ) && in_array( $mt, $has_activated[ $messenger ] ) )
1426
					||  EEH_MSG_Template::already_generated( $messenger, $mt, 0, FALSE )
1427
				) {
1428
					continue;
1429
				}
1430
1431
				//is there an installed_mt matching the default string?  If not then nothing to do here.
1432
				if ( ! isset( $installed_mts[$mt] ) ) {
1433
					unset( $all_default_mts[$mt] );
1434
					continue;
1435
				}
1436
1437
				$settings_fields = $installed_mts[$mt]->get_admin_settings_fields();
1438
				$settings = array();
1439 View Code Duplication
				if ( is_array( $settings_fields ) ) {
1440
					foreach ( $settings_fields as $field => $values ) {
1441
						if ( isset( $values['default'] ) ) {
1442
							$settings[$field] = $values['default'];
1443
						}
1444
					}
1445
				}
1446
1447
				$active_messengers[$messenger]['settings'][$messenger . '-message_types'][$mt]['settings'] = $settings;
1448
				$new_default_mts[] = $mt;
1449
				$has_activated[$messenger][] = $mt;
1450
			}
1451
1452
1453
			if ( ! empty( $new_default_mts ) ) {
1454
				$success = EEH_MSG_Template::generate_new_templates( $messenger, $new_default_mts, '', TRUE );
1455
			}
1456
1457
		}
1458
1459
		//now let's save the settings for this messenger!
1460
		EEH_MSG_Template::update_active_messengers_in_db( $active_messengers );
1461
1462
		//update $has_activated record
1463
		update_option( 'ee_has_activated_messenger', $has_activated );
1464
1465
		//that's it!
1466
		return $success;
1467
	}
1468
1469
1470
1471
1472
1473
1474
	/**
1475
	 * 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.
1476
	 *
1477
	 * @since 4.3.1
1478
	 *
1479
	 * @return void
1480
	 */
1481
	public static function validate_messages_system() {
1482
		//include our helper
1483
		EE_Registry::instance()->load_helper( 'MSG_Template' );
1484
1485
		//get active and installed  messengers/message types.
1486
		$active_messengers = EEH_MSG_Template::get_active_messengers_in_db();
1487
		$installed = EEH_MSG_Template::get_installed_message_objects();
1488
		$installed_messengers = $installed_mts = array();
1489
		//set up the arrays so they can be handled easier.
1490
		foreach( $installed['messengers'] as $im ) {
1491
			if ( $im instanceof EE_messenger ) {
1492
				$installed_messengers[$im->name] = $im;
1493
			}
1494
		}
1495
		foreach( $installed['message_types'] as $imt ) {
1496
			if ( $imt instanceof EE_message_type ) {
1497
				$installed_mts[$imt->name] = $imt;
1498
			}
1499
		}
1500
1501
		//now let's loop through the active array and validate
1502
		foreach( $active_messengers as $messenger => $active_details ) {
1503
			//first let's see if this messenger is installed.
1504
			if ( ! isset( $installed_messengers[$messenger] ) ) {
1505
				//not set so let's just remove from actives and make sure templates are inactive.
1506
				unset( $active_messengers[$messenger] );
1507
				EEH_MSG_Template::update_to_inactive( $messenger );
1508
				continue;
1509
			}
1510
1511
			//messenger is active, so let's just make sure that any active message types not installed are deactivated.
1512
			$mts = ! empty( $active_details['settings'][$messenger . '-message_types'] ) ? $active_details['settings'][$messenger . '-message_types'] : array();
1513
			foreach ( $mts as $mt_name => $mt ) {
1514
				if ( ! isset( $installed_mts[$mt_name] )  ) {
1515
					unset( $active_messengers[$messenger]['settings'][$messenger . '-message_types'][$mt_name] );
1516
					EEH_MSG_Template::update_to_inactive( $messenger, $mt_name );
1517
				}
1518
			}
1519
		}
1520
1521
		//all done! let's update the active_messengers.
1522
		EEH_MSG_Template::update_active_messengers_in_db( $active_messengers );
1523
		do_action( 'AHEE__EEH_Activation__validate_messages_system' );
1524
	}
1525
1526
1527
1528
1529
	/**
1530
	 * create_no_ticket_prices_array
1531
	 *
1532
	 * 	@access public
1533
	 * 	@static
1534
	 * 	@return void
1535
	 */
1536
	public static function create_no_ticket_prices_array(){
1537
		// this creates an array for tracking events that have no active ticket prices created
1538
		// this allows us to warn admins of the situation so that it can be corrected
1539
		$espresso_no_ticket_prices = get_option( 'ee_no_ticket_prices', FALSE );
1540
		if ( ! $espresso_no_ticket_prices ) {
1541
			add_option( 'ee_no_ticket_prices', array(), '', FALSE );
1542
		}
1543
	}
1544
1545
1546
1547
	/**
1548
	 * plugin_deactivation
1549
	 *
1550
	 * 	@access public
1551
	 * 	@static
1552
	 * 	@return void
1553
	 */
1554
	public static function plugin_deactivation() {
1555
	}
1556
1557
1558
1559
	/**
1560
	 * Finds all our EE4 custom post types, and deletes them and their associated data (like post meta or term relations)/
1561
	 *
1562
	 * @global wpdb $wpdb
1563
	 * @throws \EE_Error
1564
	 */
1565
	public static function delete_all_espresso_cpt_data(){
1566
		global $wpdb;
1567
		//get all the CPT post_types
1568
		$ee_post_types = array();
1569
		foreach(EE_Registry::instance()->non_abstract_db_models as $model_name){
1570
			if ( method_exists( $model_name, 'instance' )) {
1571
				$model_obj = call_user_func( array( $model_name, 'instance' ));
1572
				if ( $model_obj instanceof EEM_CPT_Base ) {
1573
					$ee_post_types[] = $wpdb->prepare("%s",$model_obj->post_type());
1574
				}
1575
			}
1576
		}
1577
		//get all our CPTs
1578
		$query = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (".implode(",",$ee_post_types).")";
1579
		$cpt_ids = $wpdb->get_col($query);
1580
		//delete each post meta and term relations too
1581
		foreach($cpt_ids as $post_id){
1582
			wp_delete_post($post_id,true);
1583
		}
1584
	}
1585
1586
1587
1588
	/**
1589
	 * plugin_uninstall
1590
	 *
1591
	 * @access public
1592
	 * @static
1593
	 * @param bool $remove_all
1594
	 * @return void
1595
	 */
1596
	public static function delete_all_espresso_tables_and_data( $remove_all = true ) {
1597
		global $wpdb;
1598
		$undeleted_tables = array();
1599
1600
		// load registry
1601
		foreach( EE_Registry::instance()->non_abstract_db_models as $model_name ){
1602
			if ( method_exists( $model_name, 'instance' )) {
1603
				$model_obj = call_user_func( array( $model_name, 'instance' ));
1604
				if ( $model_obj instanceof EEM_Base ) {
1605
					foreach ( $model_obj->get_tables() as $table ) {
1606
						if ( strpos( $table->get_table_name(), 'esp_' )) {
1607
							switch ( EEH_Activation::delete_unused_db_table( $table->get_table_name() )) {
1608
								case false :
1609
									$undeleted_tables[] = $table->get_table_name();
1610
								break;
1611
								case 0 :
1612
									// echo '<h4 style="color:red;">the table : ' . $table->get_table_name() . ' was not deleted  <br /></h4>';
1613
								break;
1614
								default:
1615
									// echo '<h4>the table : ' . $table->get_table_name() . ' was deleted successfully <br /></h4>';
1616
							}
1617
						}
1618
					}
1619
				}
1620
			}
1621
		}
1622
1623
		//there are some tables whose models were removed.
1624
		//they should be removed when removing all EE core's data
1625
		$tables_without_models = array(
1626
			'esp_promotion',
1627
			'esp_promotion_applied',
1628
			'esp_promotion_object',
1629
			'esp_promotion_rule',
1630
			'esp_rule'
1631
		);
1632
		foreach( $tables_without_models as $table ){
1633
			EEH_Activation::delete_db_table_if_empty( $table );
1634
		}
1635
1636
1637
		$wp_options_to_delete = array(
1638
			'ee_no_ticket_prices' => true,
1639
			'ee_active_messengers' => true,
1640
			'ee_has_activated_messenger' => true,
1641
			'ee_flush_rewrite_rules' => true,
1642
			'ee_config' => false,
1643
			'ee_data_migration_current_db_state' => true,
1644
			'ee_data_migration_mapping_' => false,
1645
			'ee_data_migration_script_' => false,
1646
			'ee_data_migrations' => true,
1647
			'ee_dms_map' => false,
1648
			'ee_notices' => true,
1649
			'lang_file_check_' => false,
1650
			'ee_maintenance_mode' => true,
1651
			'ee_ueip_optin' => true,
1652
			'ee_ueip_has_notified' => true,
1653
			'ee_plugin_activation_errors' => true,
1654
			'ee_id_mapping_from' => false,
1655
			'espresso_persistent_admin_notices' => true,
1656
			'ee_encryption_key' => true,
1657
			'pue_force_upgrade_' => false,
1658
			'pue_json_error_' => false,
1659
			'pue_install_key_' => false,
1660
			'pue_verification_error_' => false,
1661
			'pu_dismissed_upgrade_' => false,
1662
			'external_updates-' => false,
1663
			'ee_extra_data' => true,
1664
			'ee_ssn_' => false,
1665
			'ee_rss_' => false,
1666
			'ee_rte_n_tx_' => false,
1667
			'ee_pers_admin_notices' => true,
1668
			'ee_job_parameters_' => false,
1669
			'ee_upload_directories_incomplete' => true,
1670
		);
1671
		if( is_main_site() ) {
1672
			$wp_options_to_delete[ 'ee_network_config' ] = true;
1673
		}
1674
1675
		$undeleted_options = array();
1676
		foreach ( $wp_options_to_delete as $option_name => $no_wildcard ) {
1677
1678
			if( $no_wildcard ){
1679
				if( ! delete_option( $option_name ) ){
1680
					$undeleted_options[] = $option_name;
1681
				}
1682
			}else{
1683
				$option_names_to_delete_from_wildcard = $wpdb->get_col( "SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%$option_name%'" );
1684
				foreach($option_names_to_delete_from_wildcard as $option_name_from_wildcard ){
1685
					if( ! delete_option( $option_name_from_wildcard ) ){
1686
						$undeleted_options[] = $option_name_from_wildcard;
1687
					}
1688
				}
1689
			}
1690
		}
1691
                //also, let's make sure the "ee_config_option_names" wp option stays out by removing the action that adds it
1692
                remove_action( 'shutdown', array( EE_Config::instance(), 'shutdown' ), 10 );
1693
1694
		if ( $remove_all && $espresso_db_update = get_option( 'espresso_db_update' )) {
1695
			$db_update_sans_ee4 = array();
1696
			foreach($espresso_db_update as $version => $times_activated){
1697
				if( (string)$version[0] === '3'){//if its NON EE4
1698
					$db_update_sans_ee4[$version] = $times_activated;
1699
				}
1700
			}
1701
			update_option( 'espresso_db_update', $db_update_sans_ee4 );
1702
		}
1703
1704
		$errors = '';
1705
		if ( ! empty( $undeleted_tables )) {
1706
			$errors .= sprintf(
1707
				__( 'The following tables could not be deleted: %s%s', 'event_espresso' ),
1708
				'<br/>',
1709
				implode( ',<br/>', $undeleted_tables )
1710
			);
1711
		}
1712
		if ( ! empty( $undeleted_options )) {
1713
			$errors .= ! empty( $undeleted_tables ) ? '<br/>' : '';
1714
			$errors .= sprintf(
1715
				__( 'The following wp-options could not be deleted: %s%s', 'event_espresso' ),
1716
				'<br/>',
1717
				implode( ',<br/>', $undeleted_options )
1718
			);
1719
1720
		}
1721
		if ( ! empty( $errors ) ) {
1722
			EE_Error::add_attention( $errors, __FILE__, __FUNCTION__, __LINE__ );
1723
		}
1724
	}
1725
1726
	/**
1727
	 * Checks that the database table exists. Also works on temporary tables (for unit tests mostly).
1728
	 * @global wpdb $wpdb
1729
	 * @param string $table_name with or without $wpdb->prefix
1730
	 * @return boolean
1731
	 */
1732
	public static function table_exists( $table_name ){
1733
		global $wpdb, $EZSQL_ERROR;
1734
		$table_name = EEH_Activation::ensure_table_name_has_prefix( $table_name );
1735
		//ignore if this causes an sql error
1736
		$old_error = $wpdb->last_error;
1737
		$old_suppress_errors = $wpdb->suppress_errors();
1738
		$old_show_errors_value = $wpdb->show_errors( FALSE );
1739
		$ezsql_error_cache = $EZSQL_ERROR;
1740
		$wpdb->get_results( "SELECT * from $table_name LIMIT 1");
1741
		$wpdb->show_errors( $old_show_errors_value );
1742
		$wpdb->suppress_errors( $old_suppress_errors );
1743
		$new_error = $wpdb->last_error;
1744
		$wpdb->last_error = $old_error;
1745
		$EZSQL_ERROR = $ezsql_error_cache;
1746
		if( empty( $new_error ) ){
1747
			return TRUE;
1748
		}else{
1749
			return FALSE;
1750
		}
1751
	}
1752
1753
	/**
1754
	 * Resets the cache on EEH_Activation
1755
	 */
1756
	public static function reset(){
1757
		self::$_default_creator_id = NULL;
1758
		self::$_initialized_db_content_already_in_this_request = false;
1759
	}
1760
}
1761
// End of file EEH_Activation.helper.php
1762
// Location: /helpers/EEH_Activation.core.php
1763