Completed
Branch BUG-8957-add-countries (d46858)
by
unknown
31:05 queued 15:34
created

EEH_Activation::system_initialization()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
670
				\EEH_Activation::getTableManager()->dropTable( $wp_table_name );
671
			} else if ( ! $deleted_safely ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $deleted_safely of type integer|false is loosely compared to false; this is ambiguous if the integer can be zero. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
672
				// so we should be more cautious rather than just dropping tables so easily
673
				EE_Error::add_persistent_admin_notice(
674
						'bad_table_' . $wp_table_name . '_detected',
675
						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' ),
676
								$wp_table_name,
677
								"<pre>define( 'EE_DROP_BAD_TABLES', TRUE );</pre>",
678
								'<b>wp-config.php</b>',
679
								'<br/>'),
680
								TRUE );
681
			}
682
		}
683
		$engine = str_replace( 'ENGINE=', '', $engine );
684
		\EEH_Activation::getTableManager()->createTable( $table_name, $sql, $engine );
685
	}
686
687
688
689
	/**
690
	 *    add_column_if_it_doesn't_exist
691
	 *    Checks if this column already exists on the specified table. Handy for addons which want to add a column
692
	 *
693
	 * @access public
694
	 * @static
695
	 * @deprecated instead use TableManager::addColumn()
696
	 * @param string $table_name  (without "wp_", eg "esp_attendee"
697
	 * @param string $column_name
698
	 * @param string $column_info if your SQL were 'ALTER TABLE table_name ADD price VARCHAR(10)', this would be
699
	 *                            'VARCHAR(10)'
700
	 * @return bool|int
701
	 */
702
	public static function add_column_if_it_doesnt_exist($table_name,$column_name,$column_info='INT UNSIGNED NOT NULL'){
703
		return \EEH_Activation::getTableManager()->addColumn( $table_name, $column_name, $column_info );
704
	}
705
706
707
708
709
	/**
710
	 * get_fields_on_table
711
	 * Gets all the fields on the database table.
712
	 *
713
	 * @access public
714
	 * @deprecated instead use TableManager::getTableColumns()
715
	 * @static
716
	 * @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...
717
	 * @return array of database column names
718
	 */
719
	public static function get_fields_on_table( $table_name = NULL ) {
720
		return \EEH_Activation::getTableManager()->getTableColumns( $table_name );
721
	}
722
723
724
725
	/**
726
	 * db_table_is_empty
727
	 *
728
	 * @access public\
729
	 * @deprecated instead use TableAnalysis::tableIsEmpty()
730
	 * @static
731
	 * @param string $table_name
732
	 * @return bool
733
	 */
734
	public static function db_table_is_empty( $table_name ) {
735
		return \EEH_Activation::getTableAnalysis()->tableIsEmpty( $table_name );
736
}
737
738
739
740
/**
741
	 * delete_db_table_if_empty
742
	 *
743
	 * @access public
744
	 * @static
745
	 * @param string $table_name
746
	 * @return bool | int
747
	 */
748
	public static function delete_db_table_if_empty( $table_name ) {
749
		if ( \EEH_Activation::getTableAnalysis()->tableIsEmpty( $table_name ) ) {
750
			return \EEH_Activation::getTableManager()->dropTable( $table_name );
751
		}
752
		return false;
753
	}
754
755
756
757
	/**
758
	 * delete_unused_db_table
759
	 *
760
	 * @access public
761
	 * @static
762
	 * @deprecated instead use TableManager::dropTable()
763
	 * @param string $table_name
764
	 * @return bool | int
765
	 */
766
	public static function delete_unused_db_table( $table_name ) {
767
		return \EEH_Activation::getTableManager()->dropTable( $table_name );
768
	}
769
770
771
772
	/**
773
	 * drop_index
774
	 *
775
	 * @access public
776
	 * @static
777
	 * @deprecated instead use TableManager::dropIndex()
778
	 * @param string $table_name
779
	 * @param string $index_name
780
	 * @return bool | int
781
	 */
782
	public static function drop_index( $table_name, $index_name ) {
783
		return \EEH_Activation::getTableManager()->dropIndex( $table_name, $index_name );
784
	}
785
786
787
788
	/**
789
	 * create_database_tables
790
	 *
791
	 * @access public
792
	 * @static
793
	 * @throws EE_Error
794
	 * @return boolean success (whether database is setup properly or not)
795
	 */
796
	public static function create_database_tables() {
797
		EE_Registry::instance()->load_core( 'Data_Migration_Manager' );
798
		//find the migration script that sets the database to be compatible with the code
799
		$dms_name = EE_Data_Migration_Manager::instance()->get_most_up_to_date_dms();
800
		if( $dms_name ){
801
			$current_data_migration_script = EE_Registry::instance()->load_dms( $dms_name );
802
			$current_data_migration_script->set_migrating( false );
803
			$current_data_migration_script->schema_changes_before_migration();
804
			$current_data_migration_script->schema_changes_after_migration();
805 View Code Duplication
			if( $current_data_migration_script->get_errors() ){
806
				if( WP_DEBUG ){
807
					foreach( $current_data_migration_script->get_errors() as $error ){
808
						EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__ );
809
					}
810
				}else{
811
					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' ) );
812
				}
813
				return false;
814
			}
815
			EE_Data_Migration_Manager::instance()->update_current_database_state_to();
816
		}else{
817
			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__);
818
			return false;
819
		}
820
		return true;
821
	}
822
823
824
825
826
827
	/**
828
	 * initialize_system_questions
829
	 *
830
	 * 	@access public
831
	 * 	@static
832
	 * 	@return void
833
	 */
834
	public static function initialize_system_questions() {
835
		// QUESTION GROUPS
836
		global $wpdb;
837
		$table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix( 'esp_question_group' );
838
		$SQL = "SELECT QSG_system FROM $table_name WHERE QSG_system != 0";
839
		// what we have
840
		$question_groups = $wpdb->get_col( $SQL );
841
		// check the response
842
		$question_groups = is_array( $question_groups ) ? $question_groups : array();
843
		// what we should have
844
		$QSG_systems = array( 1, 2 );
845
		// loop thru what we should have and compare to what we have
846
		foreach ( $QSG_systems as $QSG_system ) {
847
			// reset values array
848
			$QSG_values = array();
849
			// 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)
850
			if ( ! in_array( "$QSG_system", $question_groups )) {
851
				// add it
852
				switch ( $QSG_system ) {
853
854 View Code Duplication
					case 1:
855
							$QSG_values = array(
856
									'QSG_name' => __( 'Personal Information', 'event_espresso' ),
857
									'QSG_identifier' => 'personal-information-' . time(),
858
									'QSG_desc' => '',
859
									'QSG_order' => 1,
860
									'QSG_show_group_name' => 1,
861
									'QSG_show_group_desc' => 1,
862
									'QSG_system' => EEM_Question_Group::system_personal,
863
									'QSG_deleted' => 0
864
								);
865
						break;
866
867 View Code Duplication
					case 2:
868
							$QSG_values = array(
869
									'QSG_name' => __( 'Address Information','event_espresso' ),
870
									'QSG_identifier' => 'address-information-' . time(),
871
									'QSG_desc' => '',
872
									'QSG_order' => 2,
873
									'QSG_show_group_name' => 1,
874
									'QSG_show_group_desc' => 1,
875
									'QSG_system' => EEM_Question_Group::system_address,
876
									'QSG_deleted' => 0
877
								);
878
						break;
879
880
				}
881
				// make sure we have some values before inserting them
882
				if ( ! empty( $QSG_values )) {
883
					// insert system question
884
					$wpdb->insert(
885
						$table_name,
886
						$QSG_values,
887
						array('%s', '%s', '%s', '%d', '%d', '%d', '%d', '%d' )
888
					);
889
					$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...
890
				}
891
			}
892
		}
893
894
895
896
		// QUESTIONS
897
		global $wpdb;
898
		$table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix( 'esp_question' );
899
		$SQL = "SELECT QST_system FROM $table_name WHERE QST_system != ''";
900
		// what we have
901
		$questions = $wpdb->get_col( $SQL );
902
		// what we should have
903
		$QST_systems = array(
904
			'fname',
905
			'lname',
906
			'email',
907
			'address',
908
			'address2',
909
			'city',
910
			'state',
911
			'country',
912
			'zip',
913
			'phone'
914
		);
915
		$order_for_group_1 = 1;
916
		$order_for_group_2 = 1;
917
		// loop thru what we should have and compare to what we have
918
		foreach ( $QST_systems as $QST_system ) {
919
			// reset values array
920
			$QST_values = array();
921
			// if we don't have what we should have
922
			if ( ! in_array( $QST_system, $questions )) {
923
				// add it
924
				switch ( $QST_system ) {
925
926 View Code Duplication
					case 'fname':
927
							$QST_values = array(
928
									'QST_display_text' => __( 'First Name', 'event_espresso' ),
929
									'QST_admin_label' => __( 'First Name - System Question', 'event_espresso' ),
930
									'QST_system' => 'fname',
931
									'QST_type' => 'TEXT',
932
									'QST_required' => 1,
933
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
934
									'QST_order' => 1,
935
									'QST_admin_only' => 0,
936
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
937
									'QST_wp_user' => self::get_default_creator_id(),
938
									'QST_deleted' => 0
939
								);
940
						break;
941
942 View Code Duplication
					case 'lname':
943
							$QST_values = array(
944
									'QST_display_text' => __( 'Last Name', 'event_espresso' ),
945
									'QST_admin_label' => __( 'Last Name - System Question', 'event_espresso' ),
946
									'QST_system' => 'lname',
947
									'QST_type' => 'TEXT',
948
									'QST_required' => 1,
949
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
950
									'QST_order' => 2,
951
									'QST_admin_only' => 0,
952
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
953
									'QST_wp_user' => self::get_default_creator_id(),
954
									'QST_deleted' => 0
955
								);
956
						break;
957
958 View Code Duplication
					case 'email':
959
							$QST_values = array(
960
									'QST_display_text' => __( 'Email Address', 'event_espresso' ),
961
									'QST_admin_label' => __( 'Email Address - System Question', 'event_espresso' ),
962
									'QST_system' => 'email',
963
									'QST_type' => 'EMAIL',
964
									'QST_required' => 1,
965
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
966
									'QST_order' => 3,
967
									'QST_admin_only' => 0,
968
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
969
									'QST_wp_user' => self::get_default_creator_id(),
970
									'QST_deleted' => 0
971
								);
972
						break;
973
974 View Code Duplication
					case 'address':
975
							$QST_values = array(
976
									'QST_display_text' => __( 'Address', 'event_espresso' ),
977
									'QST_admin_label' => __( 'Address - System Question', 'event_espresso' ),
978
									'QST_system' => 'address',
979
									'QST_type' => 'TEXT',
980
									'QST_required' => 0,
981
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
982
									'QST_order' => 4,
983
									'QST_admin_only' => 0,
984
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
985
									'QST_wp_user' => self::get_default_creator_id(),
986
									'QST_deleted' => 0
987
								);
988
						break;
989
990 View Code Duplication
					case 'address2':
991
							$QST_values = array(
992
									'QST_display_text' => __( 'Address2', 'event_espresso' ),
993
									'QST_admin_label' => __( 'Address2 - System Question', 'event_espresso' ),
994
									'QST_system' => 'address2',
995
									'QST_type' => 'TEXT',
996
									'QST_required' => 0,
997
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
998
									'QST_order' => 5,
999
									'QST_admin_only' => 0,
1000
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
1001
									'QST_wp_user' => self::get_default_creator_id(),
1002
									'QST_deleted' => 0
1003
								);
1004
						break;
1005
1006 View Code Duplication
					case 'city':
1007
							$QST_values = array(
1008
									'QST_display_text' => __( 'City', 'event_espresso' ),
1009
									'QST_admin_label' => __( 'City - System Question', 'event_espresso' ),
1010
									'QST_system' => 'city',
1011
									'QST_type' => 'TEXT',
1012
									'QST_required' => 0,
1013
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
1014
									'QST_order' => 6,
1015
									'QST_admin_only' => 0,
1016
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
1017
									'QST_wp_user' => self::get_default_creator_id(),
1018
									'QST_deleted' => 0
1019
								);
1020
						break;
1021
1022 View Code Duplication
					case 'state':
1023
							$QST_values = array(
1024
									'QST_display_text' => __( 'State/Province', 'event_espresso' ),
1025
									'QST_admin_label' => __( 'State/Province - System Question', 'event_espresso' ),
1026
									'QST_system' => 'state',
1027
									'QST_type' => 'STATE',
1028
									'QST_required' => 0,
1029
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
1030
									'QST_order' => 7,
1031
									'QST_admin_only' => 0,
1032
									'QST_wp_user' => self::get_default_creator_id(),
1033
									'QST_deleted' => 0
1034
								);
1035
						break;
1036
1037 View Code Duplication
					case 'country' :
1038
							$QST_values = array(
1039
									'QST_display_text' => __( 'Country', 'event_espresso' ),
1040
									'QST_admin_label' => __( 'Country - System Question', 'event_espresso' ),
1041
									'QST_system' => 'country',
1042
									'QST_type' => 'COUNTRY',
1043
									'QST_required' => 0,
1044
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
1045
									'QST_order' => 8,
1046
									'QST_admin_only' => 0,
1047
									'QST_wp_user' => self::get_default_creator_id(),
1048
									'QST_deleted' => 0
1049
								);
1050
						break;
1051
1052 View Code Duplication
					case 'zip':
1053
							$QST_values = array(
1054
									'QST_display_text' => __( 'Zip/Postal Code', 'event_espresso' ),
1055
									'QST_admin_label' => __( 'Zip/Postal Code - System Question', 'event_espresso' ),
1056
									'QST_system' => 'zip',
1057
									'QST_type' => 'TEXT',
1058
									'QST_required' => 0,
1059
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
1060
									'QST_order' => 9,
1061
									'QST_admin_only' => 0,
1062
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
1063
									'QST_wp_user' => self::get_default_creator_id(),
1064
									'QST_deleted' => 0
1065
								);
1066
						break;
1067
1068 View Code Duplication
					case 'phone':
1069
							$QST_values = array(
1070
									'QST_display_text' => __( 'Phone Number', 'event_espresso' ),
1071
									'QST_admin_label' => __( 'Phone Number - System Question', 'event_espresso' ),
1072
									'QST_system' => 'phone',
1073
									'QST_type' => 'TEXT',
1074
									'QST_required' => 0,
1075
									'QST_required_text' => __( 'This field is required', 'event_espresso' ),
1076
									'QST_order' => 10,
1077
									'QST_admin_only' => 0,
1078
									'QST_max' => EEM_Question::instance()->absolute_max_for_system_question( $QST_system ),
1079
									'QST_wp_user' => self::get_default_creator_id(),
1080
									'QST_deleted' => 0
1081
								);
1082
						break;
1083
1084
				}
1085
				if ( ! empty( $QST_values )) {
1086
					// insert system question
1087
					$wpdb->insert(
1088
						$table_name,
1089
						$QST_values,
1090
						array( '%s', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%d', '%d' )
1091
					);
1092
					$QST_ID = $wpdb->insert_id;
1093
1094
					// QUESTION GROUP QUESTIONS
1095
					if(  in_array( $QST_system, array( 'fname', 'lname', 'email' ) ) ) {
1096
						$system_question_we_want = EEM_Question_Group::system_personal;
1097
					} else {
1098
						$system_question_we_want = EEM_Question_Group::system_address;
1099
					}
1100
					if( isset( $QSG_IDs[ $system_question_we_want ] ) ) {
1101
						$QSG_ID = $QSG_IDs[ $system_question_we_want ];
1102
					} else {
1103
						$id_col = EEM_Question_Group::instance()->get_col( array( array( 'QSG_system' => $system_question_we_want ) ) );
1104
						if( is_array( $id_col ) ) {
1105
							$QSG_ID = reset( $id_col );
1106
						} else {
1107
							//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
1108
                                                        EE_Log::instance()->log(
1109
                                                                __FILE__,
1110
                                                                __FUNCTION__,
1111
                                                                sprintf(
1112
                                                                        __( 'Could not associate question %1$s to a question group because no system question group existed', 'event_espresso'),
1113
                                                                        $QST_ID ),
1114
                                                                'error' );
1115
                                                        continue;
1116
						}
1117
					}
1118
1119
					// add system questions to groups
1120
					$wpdb->insert(
1121
						\EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix( 'esp_question_group_question' ),
1122
						array( 'QSG_ID'    => $QSG_ID,
1123
						       'QST_ID'    => $QST_ID,
1124
						       'QGQ_order' => ( $QSG_ID === 1 ) ? $order_for_group_1++ : $order_for_group_2++
1125
						),
1126
						array( '%d', '%d', '%d' )
1127
					);
1128
				}
1129
			}
1130
		}
1131
1132
	}
1133
1134
1135
1136
	/**
1137
	 * Makes sure the default payment method (Invoice) is active.
1138
	 * This used to be done automatically as part of constructing the old gateways config
1139
	 *
1140
	 * @throws \EE_Error
1141
	 */
1142
	public static function insert_default_payment_methods(){
1143
		if( ! EEM_Payment_Method::instance()->count_active( EEM_Payment_Method::scope_cart ) ){
1144
			EE_Registry::instance()->load_lib( 'Payment_Method_Manager' );
1145
			EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type( 'Invoice' );
1146
		}else{
1147
			EEM_Payment_Method::instance()->verify_button_urls();
1148
		}
1149
	}
1150
1151
	/**
1152
	 * insert_default_status_codes
1153
	 *
1154
	 * 	@access public
1155
	 * 	@static
1156
	 * 	@return void
1157
	 */
1158
	public static function insert_default_status_codes() {
1159
1160
		global $wpdb;
1161
1162
		if ( \EEH_Activation::getTableAnalysis()->tableExists( EEM_Status::instance()->table() ) ) {
1163
1164
			$table_name = EEM_Status::instance()->table();
1165
1166
			$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', 'RWL', 'TAB', 'TIN', 'TFL', 'TCM', 'TOP', 'PAP', 'PCN', 'PFL', 'PDC', 'EDR', 'ESN', 'PPN', 'RIC', 'MSN', 'MFL', 'MID', 'MRS', 'MIC' );";
1167
			$wpdb->query($SQL);
1168
1169
			$SQL = "INSERT INTO $table_name
1170
					(STS_ID, STS_code, STS_type, STS_can_edit, STS_desc, STS_open) VALUES
1171
					('ACT', 'ACTIVE', 'event', 0, NULL, 1),
1172
					('NAC', 'NOT_ACTIVE', 'event', 0, NULL, 0),
1173
					('NOP', 'REGISTRATION_NOT_OPEN', 'event', 0, NULL, 1),
1174
					('OPN', 'REGISTRATION_OPEN', 'event', 0, NULL, 1),
1175
					('CLS', 'REGISTRATION_CLOSED', 'event', 0, NULL, 0),
1176
					('PND', 'PENDING', 'event', 0, NULL, 1),
1177
					('ONG', 'ONGOING', 'event', 0, NULL, 1),
1178
					('SEC', 'SECONDARY', 'event', 0, NULL, 1),
1179
					('DRF', 'DRAFT', 'event', 0, NULL, 0),
1180
					('DEL', 'DELETED', 'event', 0, NULL, 0),
1181
					('DEN', 'DENIED', 'event', 0, NULL, 0),
1182
					('EXP', 'EXPIRED', 'event', 0, NULL, 0),
1183
					('RPP', 'PENDING_PAYMENT', 'registration', 0, NULL, 1),
1184
					('RAP', 'APPROVED', 'registration', 0, NULL, 1),
1185
					('RCN', 'CANCELLED', 'registration', 0, NULL, 0),
1186
					('RDC', 'DECLINED', 'registration', 0, NULL, 0),
1187
					('RNA', 'NOT_APPROVED', 'registration', 0, NULL, 1),
1188
					('RIC', 'INCOMPLETE', 'registration', 0, NULL, 1),
1189
					('RWL', 'WAIT_LIST', 'registration', 0, NULL, 1),
1190
					('TFL', 'FAILED', 'transaction', 0, NULL, 0),
1191
					('TAB', 'ABANDONED', 'transaction', 0, NULL, 0),
1192
					('TIN', 'INCOMPLETE', 'transaction', 0, NULL, 1),
1193
					('TCM', 'COMPLETE', 'transaction', 0, NULL, 1),
1194
					('TOP',	'OVERPAID', 'transaction', 0, NULL, 1),
1195
					('PAP', 'APPROVED', 'payment', 0, NULL, 1),
1196
					('PPN', 'PENDING', 'payment', 0, NULL, 1),
1197
					('PCN', 'CANCELLED', 'payment', 0, NULL, 0),
1198
					('PFL', 'FAILED', 'payment', 0, NULL, 0),
1199
					('PDC', 'DECLINED', 'payment', 0, NULL, 0),
1200
					('EDR', 'DRAFT', 'email', 0, NULL, 0),
1201
					('ESN', 'SENT', 'email', 0, NULL, 1),
1202
					('MSN', 'SENT', 'message', 0, NULL, 0),
1203
					('MFL', 'FAIL', 'message', 0, NULL, 0),
1204
					('MID', 'IDLE', 'message', 0, NULL, 1),
1205
					('MRS', 'RESEND', 'message', 0, NULL, 1),
1206
					('MIC', 'INCOMPLETE', 'message', 0, NULL, 0);";
1207
			$wpdb->query($SQL);
1208
1209
		}
1210
1211
	}
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
	/**
1226
	 * create_upload_directories
1227
	 * Creates folders in the uploads directory to facilitate addons and templates
1228
	 *
1229
	 * 	@access public
1230
	 * 	@static
1231
	 * 	@return boolean success of verifying upload directories exist
1232
	 */
1233
	public static function create_upload_directories() {
1234
		// Create the required folders
1235
		$folders = array(
1236
				EVENT_ESPRESSO_TEMPLATE_DIR,
1237
				EVENT_ESPRESSO_GATEWAY_DIR,
1238
				EVENT_ESPRESSO_UPLOAD_DIR . 'logs/',
1239
				EVENT_ESPRESSO_UPLOAD_DIR . 'css/',
1240
				EVENT_ESPRESSO_UPLOAD_DIR . 'tickets/'
1241
		);
1242
		foreach ( $folders as $folder ) {
1243
			try {
1244
				EEH_File::ensure_folder_exists_and_is_writable( $folder );
1245
				@ 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...
1246
			} catch( EE_Error $e ){
1247
				EE_Error::add_error(
1248
					sprintf(
1249
						__(  'Could not create the folder at "%1$s" because: %2$s', 'event_espresso' ),
1250
						$folder,
1251
						'<br />' . $e->getMessage()
1252
					),
1253
					__FILE__, __FUNCTION__, __LINE__
1254
				);
1255
				//indicate we'll need to fix this later
1256
				update_option( EEH_Activation::upload_directories_incomplete_option_name, true );
1257
				return FALSE;
1258
			}
1259
		}
1260
		//just add the .htaccess file to the logs directory to begin with. Even if logging
1261
		//is disabled, there might be activation errors recorded in there
1262
		EEH_File::add_htaccess_deny_from_all( EVENT_ESPRESSO_UPLOAD_DIR . 'logs/' );
1263
		//remember EE's folders are all good
1264
		delete_option( EEH_Activation::upload_directories_incomplete_option_name );
1265
		return TRUE;
1266
	}
1267
1268
	/**
1269
	 * Whether the upload directories need to be fixed or not.
1270
	 * If EE is installed but filesystem access isn't initially available,
1271
	 * we need to get the user's filesystem credentials and THEN create them,
1272
	 * so there might be period of time when EE is installed but its
1273
	 * upload directories aren't available. This indicates such a state
1274
	 * @return boolean
1275
	 */
1276
	public static function upload_directories_incomplete() {
1277
		return get_option( EEH_Activation::upload_directories_incomplete_option_name, false );
1278
	}
1279
1280
1281
1282
	/**
1283
	 * generate_default_message_templates
1284
	 *
1285
	 * @static
1286
	 * @throws EE_Error
1287
	 * @return bool     true means new templates were created.
1288
	 *                  false means no templates were created.
1289
	 *                  This is NOT an error flag. To check for errors you will want
1290
	 *                  to use either EE_Error or a try catch for an EE_Error exception.
1291
	 */
1292
	public static function generate_default_message_templates() {
1293
		/** @type EE_Message_Resource_Manager $message_resource_manager */
1294
		$message_resource_manager = EE_Registry::instance()->load_lib( 'Message_Resource_Manager' );
1295
		/*
1296
		 * This first method is taking care of ensuring any default messengers
1297
		 * that should be made active and have templates generated are done.
1298
		 */
1299
		$new_templates_created_for_messenger = self::_activate_and_generate_default_messengers_and_message_templates(
1300
			$message_resource_manager
1301
		);
1302
		/**
1303
		 * This method is verifying there are no NEW default message types
1304
		 * for ACTIVE messengers that need activated (and corresponding templates setup).
1305
		 */
1306
		$new_templates_created_for_message_type = self::_activate_new_message_types_for_active_messengers_and_generate_default_templates(
1307
			$message_resource_manager
1308
		);
1309
		//after all is done, let's persist these changes to the db.
1310
		$message_resource_manager->update_has_activated_messengers_option();
1311
		$message_resource_manager->update_active_messengers_option();
1312
		// will return true if either of these are true.  Otherwise will return false.
1313
		return $new_templates_created_for_message_type || $new_templates_created_for_messenger;
1314
	}
1315
1316
1317
1318
	/**
1319
	 * @param \EE_Message_Resource_Manager $message_resource_manager
1320
	 * @return array|bool
1321
	 * @throws \EE_Error
1322
	 */
1323
	protected static function _activate_new_message_types_for_active_messengers_and_generate_default_templates(
1324
		EE_Message_Resource_Manager $message_resource_manager
1325
	) {
1326
		/** @type EE_messenger[] $active_messengers */
1327
		$active_messengers = $message_resource_manager->active_messengers();
1328
		$installed_message_types = $message_resource_manager->installed_message_types();
1329
		$templates_created = false;
1330
		foreach ( $active_messengers as $active_messenger ) {
1331
			$default_message_type_names_for_messenger = $active_messenger->get_default_message_types();
1332
			$default_message_type_names_to_activate = array();
1333
			// looping through each default message type reported by the messenger
1334
			// and setup the actual message types to activate.
1335
			foreach ( $default_message_type_names_for_messenger as $default_message_type_name_for_messenger ) {
1336
				// if already active or has already been activated before we skip
1337
				// (otherwise we might reactivate something user's intentionally deactivated.)
1338
				// we also skip if the message type is not installed.
1339
				if (
1340
					$message_resource_manager->has_message_type_been_activated_for_messenger( $default_message_type_name_for_messenger, $active_messenger->name )
1341
					|| $message_resource_manager->is_message_type_active_for_messenger(
1342
						$active_messenger->name,
1343
						$default_message_type_name_for_messenger
1344
					)
1345
					|| ! isset( $installed_message_types[ $default_message_type_name_for_messenger ] )
1346
				) {
1347
					continue;
1348
				}
1349
				$default_message_type_names_to_activate[] = $default_message_type_name_for_messenger;
1350
			}
1351
			//let's activate!
1352
			$message_resource_manager->ensure_message_types_are_active(
1353
				$default_message_type_names_to_activate,
1354
				$active_messenger->name,
1355
				false
1356
			);
1357
			//activate the templates for these message types
1358
			if ( ! empty( $default_message_type_names_to_activate ) ) {
1359
				$templates_created = EEH_MSG_Template::generate_new_templates(
1360
					$active_messenger->name,
1361
					$default_message_type_names_for_messenger,
1362
					'',
1363
					true
1364
				);
1365
			}
1366
		}
1367
		return $templates_created;
1368
	}
1369
1370
1371
1372
	/**
1373
	 * This will activate and generate default messengers and default message types for those messengers.
1374
	 *
1375
	 * @param EE_message_Resource_Manager $message_resource_manager
1376
	 * @return array|bool  True means there were default messengers and message type templates generated.
1377
	 *                     False means that there were no templates generated
1378
	 *                     (which could simply mean there are no default message types for a messenger).
1379
	 * @throws EE_Error
1380
	 */
1381
	protected static function _activate_and_generate_default_messengers_and_message_templates(
1382
		EE_Message_Resource_Manager $message_resource_manager
1383
	) {
1384
		/** @type EE_messenger[] $messengers_to_generate */
1385
		$messengers_to_generate = self::_get_default_messengers_to_generate_on_activation( $message_resource_manager );
1386
		$installed_message_types = $message_resource_manager->installed_message_types();
1387
		$templates_generated = false;
1388
		foreach ( $messengers_to_generate as $messenger_to_generate ) {
1389
			$default_message_type_names_for_messenger = $messenger_to_generate->get_default_message_types();
1390
			//verify the default message types match an installed message type.
1391
			foreach ( $default_message_type_names_for_messenger as $key => $name ) {
1392
				if (
1393
					! isset( $installed_message_types[ $name ] )
1394
					|| $message_resource_manager->has_message_type_been_activated_for_messenger( $name, $messenger_to_generate->name )
1395
				) {
1396
					unset( $default_message_type_names_for_messenger[ $key ] );
1397
				}
1398
			}
1399
			// in previous iterations, the active_messengers option in the db
1400
			// needed updated before calling create templates. however with the changes this may not be necessary.
1401
			// This comment is left here just in case we discover that we _do_ need to update before
1402
			// passing off to create templates (after the refactor is done).
1403
			// @todo remove this comment when determined not necessary.
1404
			$message_resource_manager->activate_messenger(
1405
				$messenger_to_generate->name,
1406
				$default_message_type_names_for_messenger,
1407
				false
1408
			);
1409
			//create any templates needing created (or will reactivate templates already generated as necessary).
1410
			if ( ! empty( $default_message_type_names_for_messenger ) ) {
1411
				$templates_generated = EEH_MSG_Template::generate_new_templates(
1412
					$messenger_to_generate->name,
1413
					$default_message_type_names_for_messenger,
1414
					'',
1415
					true
1416
				);
1417
			}
1418
		}
1419
		return $templates_generated;
1420
	}
1421
1422
1423
1424
	/**
1425
	 * This returns the default messengers to generate templates for on activation of EE.
1426
	 * It considers:
1427
	 * - whether a messenger is already active in the db.
1428
	 * - whether a messenger has been made active at any time in the past.
1429
	 *
1430
	 * @static
1431
	 * @param  EE_Message_Resource_Manager $message_resource_manager
1432
	 * @return EE_messenger[]
1433
	 */
1434
	protected static function _get_default_messengers_to_generate_on_activation(
1435
		EE_Message_Resource_Manager $message_resource_manager
1436
	) {
1437
		$active_messengers = $message_resource_manager->active_messengers();
1438
		$installed_messengers = $message_resource_manager->installed_messengers();
1439
		$has_activated = $message_resource_manager->get_has_activated_messengers_option();
1440
1441
		$messengers_to_generate = array();
1442
		foreach ( $installed_messengers as $installed_messenger ) {
1443
			//if installed messenger is a messenger that should be activated on install
1444
			//and is not already active
1445
			//and has never been activated
1446
			if (
1447
				! $installed_messenger->activate_on_install
1448
				|| isset( $active_messengers[ $installed_messenger->name ] )
1449
				|| isset( $has_activated[ $installed_messenger->name ] )
1450
			) {
1451
				continue;
1452
			}
1453
			$messengers_to_generate[ $installed_messenger->name ] = $installed_messenger;
1454
		}
1455
		return $messengers_to_generate;
1456
	}
1457
1458
1459
1460
1461
1462
1463
	/**
1464
	 * This simply validates active message types to ensure they actually match installed
1465
	 * message types.  If there's a mismatch then we deactivate the message type and ensure all related db
1466
	 * rows are set inactive.
1467
	 *
1468
	 * Note: Messengers are no longer validated here as of 4.9.0 because they get validated automatically whenever
1469
	 * EE_Messenger_Resource_Manager is constructed.  Message Types are a bit more resource heavy for validation so they
1470
	 * are still handled in here.
1471
	 *
1472
	 * @since 4.3.1
1473
	 *
1474
	 * @return void
1475
	 */
1476
	public static function validate_messages_system() {
1477
		/** @type EE_Message_Resource_Manager $message_resource_manager */
1478
		$message_resource_manager = EE_Registry::instance()->load_lib( 'Message_Resource_Manager' );
1479
		$message_resource_manager->validate_active_message_types_are_installed();
1480
		do_action( 'AHEE__EEH_Activation__validate_messages_system' );
1481
	}
1482
1483
1484
1485
1486
	/**
1487
	 * create_no_ticket_prices_array
1488
	 *
1489
	 * 	@access public
1490
	 * 	@static
1491
	 * 	@return void
1492
	 */
1493
	public static function create_no_ticket_prices_array(){
1494
		// this creates an array for tracking events that have no active ticket prices created
1495
		// this allows us to warn admins of the situation so that it can be corrected
1496
		$espresso_no_ticket_prices = get_option( 'ee_no_ticket_prices', FALSE );
1497
		if ( ! $espresso_no_ticket_prices ) {
1498
			add_option( 'ee_no_ticket_prices', array(), '', FALSE );
1499
		}
1500
	}
1501
1502
1503
1504
	/**
1505
	 * plugin_deactivation
1506
	 *
1507
	 * 	@access public
1508
	 * 	@static
1509
	 * 	@return void
1510
	 */
1511
	public static function plugin_deactivation() {
1512
	}
1513
1514
1515
1516
	/**
1517
	 * Finds all our EE4 custom post types, and deletes them and their associated data
1518
	 * (like post meta or term relations)
1519
	 *
1520
	 * @global wpdb $wpdb
1521
	 * @throws \EE_Error
1522
	 */
1523
	public static function delete_all_espresso_cpt_data(){
1524
		global $wpdb;
1525
		//get all the CPT post_types
1526
		$ee_post_types = array();
1527
		foreach(EE_Registry::instance()->non_abstract_db_models as $model_name){
1528
			if ( method_exists( $model_name, 'instance' )) {
1529
				$model_obj = call_user_func( array( $model_name, 'instance' ));
1530
				if ( $model_obj instanceof EEM_CPT_Base ) {
1531
					$ee_post_types[] = $wpdb->prepare("%s",$model_obj->post_type());
1532
				}
1533
			}
1534
		}
1535
		//get all our CPTs
1536
		$query = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (".implode(",",$ee_post_types).")";
1537
		$cpt_ids = $wpdb->get_col($query);
1538
		//delete each post meta and term relations too
1539
		foreach($cpt_ids as $post_id){
1540
			wp_delete_post($post_id,true);
1541
		}
1542
	}
1543
1544
	/**
1545
	 * Deletes all EE custom tables
1546
	 *
1547
	 * @return array
1548
	 */
1549
	public static function drop_espresso_tables() {
1550
		$tables = array();
1551
		// load registry
1552
		foreach( EE_Registry::instance()->non_abstract_db_models as $model_name ){
1553
			if ( method_exists( $model_name, 'instance' )) {
1554
				$model_obj = call_user_func( array( $model_name, 'instance' ));
1555
				if ( $model_obj instanceof EEM_Base ) {
1556
					foreach ( $model_obj->get_tables() as $table ) {
1557
						if ( strpos( $table->get_table_name(), 'esp_' )
1558
							&& 
1559
							( 
1560
								is_main_site()//main site? nuke them all
1561
								|| ! $table->is_global()//not main site,but not global either. nuke it
1562
							)
1563
						) {
1564
							$tables[] = $table->get_table_name();
1565
						}
1566
					}
1567
				}
1568
			}
1569
		}
1570
1571
		//there are some tables whose models were removed.
1572
		//they should be removed when removing all EE core's data
1573
		$tables_without_models = array(
1574
			'esp_promotion',
1575
			'esp_promotion_applied',
1576
			'esp_promotion_object',
1577
			'esp_promotion_rule',
1578
			'esp_rule'
1579
		);
1580
		foreach( $tables_without_models as $table ){
1581
			$tables[] = $table;
1582
		}
1583
		return \EEH_Activation::getTableManager()->dropTables( $tables );
1584
	}
1585
1586
	/**
1587
	 * Drops all the tables mentioned in a single MYSQL query. Double-checks
1588
	 * each table name provided has a wpdb prefix attached, and that it exists.
1589
	 * Returns the list actually deleted
1590
	 * @deprecated in 4.9.13. Instead use TableManager::dropTables()
1591
	 * @global WPDB $wpdb
1592
	 * @param array $table_names
1593
	 * @return array of table names which we deleted
1594
	 */
1595
	public static function drop_tables( $table_names ) {
1596
		return \EEH_Activation::getTableManager()->dropTables( $table_names );
1597
	}
1598
	/**
1599
	 * plugin_uninstall
1600
	 *
1601
	 * @access public
1602
	 * @static
1603
	 * @param bool $remove_all
1604
	 * @return void
1605
	 */
1606
	public static function delete_all_espresso_tables_and_data( $remove_all = true ) {
1607
		global $wpdb;
1608
		self::drop_espresso_tables();
1609
1610
		$wp_options_to_delete = array(
1611
			'ee_no_ticket_prices' => true,
1612
			'ee_active_messengers' => true,
1613
			'ee_has_activated_messenger' => true,
1614
			'ee_flush_rewrite_rules' => true,
1615
			'ee_config' => false,
1616
			'ee_data_migration_current_db_state' => true,
1617
			'ee_data_migration_mapping_' => false,
1618
			'ee_data_migration_script_' => false,
1619
			'ee_data_migrations' => true,
1620
			'ee_dms_map' => false,
1621
			'ee_notices' => true,
1622
			'lang_file_check_' => false,
1623
			'ee_maintenance_mode' => true,
1624
			'ee_ueip_optin' => true,
1625
			'ee_ueip_has_notified' => true,
1626
			'ee_plugin_activation_errors' => true,
1627
			'ee_id_mapping_from' => false,
1628
			'espresso_persistent_admin_notices' => true,
1629
			'ee_encryption_key' => true,
1630
			'pue_force_upgrade_' => false,
1631
			'pue_json_error_' => false,
1632
			'pue_install_key_' => false,
1633
			'pue_verification_error_' => false,
1634
			'pu_dismissed_upgrade_' => false,
1635
			'external_updates-' => false,
1636
			'ee_extra_data' => true,
1637
			'ee_ssn_' => false,
1638
			'ee_rss_' => false,
1639
			'ee_rte_n_tx_' => false,
1640
			'ee_pers_admin_notices' => true,
1641
			'ee_job_parameters_' => false,
1642
			'ee_upload_directories_incomplete' => true,
1643
		);
1644
		if( is_main_site() ) {
1645
			$wp_options_to_delete[ 'ee_network_config' ] = true;
1646
		}
1647
1648
		$undeleted_options = array();
1649
		foreach ( $wp_options_to_delete as $option_name => $no_wildcard ) {
1650
1651
			if( $no_wildcard ){
1652
				if( ! delete_option( $option_name ) ){
1653
					$undeleted_options[] = $option_name;
1654
				}
1655
			}else{
1656
				$option_names_to_delete_from_wildcard = $wpdb->get_col( "SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%$option_name%'" );
1657
				foreach($option_names_to_delete_from_wildcard as $option_name_from_wildcard ){
1658
					if( ! delete_option( $option_name_from_wildcard ) ){
1659
						$undeleted_options[] = $option_name_from_wildcard;
1660
					}
1661
				}
1662
			}
1663
		}
1664
                //also, let's make sure the "ee_config_option_names" wp option stays out by removing the action that adds it
1665
                remove_action( 'shutdown', array( EE_Config::instance(), 'shutdown' ), 10 );
1666
1667
		if ( $remove_all && $espresso_db_update = get_option( 'espresso_db_update' )) {
1668
			$db_update_sans_ee4 = array();
1669
			foreach($espresso_db_update as $version => $times_activated){
1670
				if( (string)$version[0] === '3'){//if its NON EE4
1671
					$db_update_sans_ee4[$version] = $times_activated;
1672
				}
1673
			}
1674
			update_option( 'espresso_db_update', $db_update_sans_ee4 );
1675
		}
1676
1677
		$errors = '';
1678
		if ( ! empty( $undeleted_options )) {
1679
			$errors .= sprintf(
1680
				__( 'The following wp-options could not be deleted: %s%s', 'event_espresso' ),
1681
				'<br/>',
1682
				implode( ',<br/>', $undeleted_options )
1683
			);
1684
1685
		}
1686
		if ( ! empty( $errors ) ) {
1687
			EE_Error::add_attention( $errors, __FILE__, __FUNCTION__, __LINE__ );
1688
		}
1689
	}
1690
1691
	/**
1692
	 * Gets the mysql error code from the last used query by wpdb
1693
	 * @return int mysql error code, see https://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html
1694
	 */
1695
	public static function last_wpdb_error_code() {
1696
		global $wpdb;
1697
		if( $wpdb->use_mysqli ) {
1698
			return mysqli_errno( $wpdb->dbh );
1699
		} else {
1700
			return mysql_errno( $wpdb->dbh );
1701
		}
1702
	}
1703
1704
	/**
1705
	 * Checks that the database table exists. Also works on temporary tables (for unit tests mostly).
1706
	 * @global wpdb $wpdb
1707
	 * @deprecated instead use TableAnalysis::tableExists()
1708
	 * @param string $table_name with or without $wpdb->prefix
1709
	 * @return boolean
1710
	 */
1711
	public static function table_exists( $table_name ){
1712
		return \EEH_Activation::getTableAnalysis()->tableExists( $table_name );
1713
	}
1714
1715
	/**
1716
	 * Resets the cache on EEH_Activation
1717
	 */
1718
	public static function reset(){
1719
		self::$_default_creator_id = NULL;
1720
		self::$_initialized_db_content_already_in_this_request = false;
1721
	}
1722
}
1723
// End of file EEH_Activation.helper.php
1724
// Location: /helpers/EEH_Activation.core.php
1725