Completed
Pull Request — master (#10196)
by Shiva
19:21
created

WC_Install::cron_schedules()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 7
rs 9.4285
cc 1
eloc 5
nc 1
nop 1
1
<?php
1 ignored issue
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 18 and the first side effect is on line 12.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * Installation related functions and actions
4
 *
5
 * @author   WooThemes
6
 * @category Admin
7
 * @package  WooCommerce/Classes
8
 * @version  2.4.1
9
 */
10
11
if ( ! defined( 'ABSPATH' ) ) {
12
	exit;
13
}
14
15
/**
16
 * WC_Install Class.
17
 */
18
class WC_Install {
19
20
	/** @var array DB updates that need to be run */
21
	private static $db_updates = array(
22
		'2.0.0' => 'updates/woocommerce-update-2.0.php',
23
		'2.0.9' => 'updates/woocommerce-update-2.0.9.php',
24
		'2.1.0' => 'updates/woocommerce-update-2.1.php',
25
		'2.2.0' => 'updates/woocommerce-update-2.2.php',
26
		'2.3.0' => 'updates/woocommerce-update-2.3.php',
27
		'2.4.0' => 'updates/woocommerce-update-2.4.php',
28
		'2.4.1' => 'updates/woocommerce-update-2.4.1.php',
29
		'2.5.0' => 'updates/woocommerce-update-2.5.php',
30
	);
31
32
	/**
33
	 * Hook in tabs.
34
	 */
35
	public static function init() {
36
		add_action( 'init', array( __CLASS__, 'check_version' ), 5 );
37
		add_action( 'admin_init', array( __CLASS__, 'install_actions' ) );
38
		add_action( 'in_plugin_update_message-woocommerce/woocommerce.php', array( __CLASS__, 'in_plugin_update_message' ) );
39
		add_filter( 'plugin_action_links_' . WC_PLUGIN_BASENAME, array( __CLASS__, 'plugin_action_links' ) );
40
		add_filter( 'plugin_row_meta', array( __CLASS__, 'plugin_row_meta' ), 10, 2 );
41
		add_filter( 'wpmu_drop_tables', array( __CLASS__, 'wpmu_drop_tables' ) );
42
		add_filter( 'cron_schedules', array( __CLASS__, 'cron_schedules' ) );
43
	}
44
45
	/**
46
	 * Check WooCommerce version and run the updater is required.
47
	 *
48
	 * This check is done on all requests and runs if he versions do not match.
49
	 */
50
	public static function check_version() {
51
		if ( ! defined( 'IFRAME_REQUEST' ) && get_option( 'woocommerce_version' ) !== WC()->version ) {
52
			self::install();
53
			do_action( 'woocommerce_updated' );
54
		}
55
	}
56
57
	/**
58
	 * Install actions when a update button is clicked within the admin area.
59
	 *
60
	 * This function is hooked into admin_init to affect admin only.
61
	 */
62
	public static function install_actions() {
63
		if ( ! empty( $_GET['do_update_woocommerce'] ) ) {
64
			self::update();
65
			WC_Admin_Notices::remove_notice( 'update' );
66
			add_action( 'admin_notices', array( __CLASS__, 'updated_notice' ) );
67
		}
68
	}
69
70
	/**
71
	 * Show notice stating update was successful.
72
	 */
73
	public static function updated_notice() {
74
		?>
75
		<div id="message" class="updated woocommerce-message wc-connect">
76
			<p><?php _e( 'WooCommerce data update complete. Thank you for updating to the latest version!', 'woocommerce' ); ?></p>
77
		</div>
78
		<?php
79
	}
80
81
	/**
82
	 * Install WC.
83
	 */
84
	public static function install() {
85
		global $wpdb;
86
87
		if ( ! defined( 'WC_INSTALLING' ) ) {
88
			define( 'WC_INSTALLING', true );
89
		}
90
91
		// Ensure needed classes are loaded
92
		include_once( 'admin/class-wc-admin-notices.php' );
93
94
		self::create_options();
95
		self::create_tables();
96
		self::create_roles();
97
98
		// Register post types
99
		WC_Post_types::register_post_types();
100
		WC_Post_types::register_taxonomies();
101
102
		// Also register endpoints - this needs to be done prior to rewrite rule flush
103
		WC()->query->init_query_vars();
104
		WC()->query->add_endpoints();
105
		WC_API::add_endpoint();
106
		WC_Auth::add_endpoint();
107
108
		self::create_terms();
109
		self::create_cron_jobs();
110
		self::create_files();
111
112
		// Queue upgrades/setup wizard
113
		$current_wc_version    = get_option( 'woocommerce_version', null );
114
		$current_db_version    = get_option( 'woocommerce_db_version', null );
115
		$major_wc_version      = substr( WC()->version, 0, strrpos( WC()->version, '.' ) );
0 ignored issues
show
Unused Code introduced by
$major_wc_version is not used, you could remove the assignment.

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

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

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

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

Loading history...
116
117
		WC_Admin_Notices::remove_all_notices();
118
119
		// No versions? This is a new install :)
120
		if ( is_null( $current_wc_version ) && is_null( $current_db_version ) && apply_filters( 'woocommerce_enable_setup_wizard', true ) ) {
121
			WC_Admin_Notices::add_notice( 'install' );
122
			set_transient( '_wc_activation_redirect', 1, 30 );
123
124
		// No page? Let user run wizard again..
125
		} elseif ( ! get_option( 'woocommerce_cart_page_id' ) ) {
126
			WC_Admin_Notices::add_notice( 'install' );
127
		}
128
129
		if ( ! is_null( $current_db_version ) && version_compare( $current_db_version, max( array_keys( self::$db_updates ) ), '<' ) ) {
130
			WC_Admin_Notices::add_notice( 'update' );
131
		} else {
132
			self::update_db_version();
133
		}
134
135
		self::update_wc_version();
136
137
		// Flush rules after install
138
		flush_rewrite_rules();
139
		delete_transient( 'wc_attribute_taxonomies' );
140
141
		/*
142
		 * Deletes all expired transients. The multi-table delete syntax is used.
143
		 * to delete the transient record from table a, and the corresponding.
144
		 * transient_timeout record from table b.
145
		 *
146
		 * Based on code inside core's upgrade_network() function.
147
		 */
148
		$sql = "DELETE a, b FROM $wpdb->options a, $wpdb->options b
149
			WHERE a.option_name LIKE %s
150
			AND a.option_name NOT LIKE %s
151
			AND b.option_name = CONCAT( '_transient_timeout_', SUBSTRING( a.option_name, 12 ) )
152
			AND b.option_value < %d";
153
		$wpdb->query( $wpdb->prepare( $sql, $wpdb->esc_like( '_transient_' ) . '%', $wpdb->esc_like( '_transient_timeout_' ) . '%', time() ) );
154
155
		// Trigger action
156
		do_action( 'woocommerce_installed' );
157
	}
158
159
	/**
160
	 * Update WC version to current.
161
	 */
162
	private static function update_wc_version() {
163
		delete_option( 'woocommerce_version' );
164
		add_option( 'woocommerce_version', WC()->version );
165
	}
166
167
	/**
168
	 * Update DB version to current.
169
	 */
170
	private static function update_db_version( $version = null ) {
171
		delete_option( 'woocommerce_db_version' );
172
		add_option( 'woocommerce_db_version', is_null( $version ) ? WC()->version : $version );
173
	}
174
175
	/**
176
	 * Handle updates.
177
	 */
178
	private static function update() {
179
		$current_db_version = get_option( 'woocommerce_db_version' );
180
181
		foreach ( self::$db_updates as $version => $updater ) {
182
			if ( version_compare( $current_db_version, $version, '<' ) ) {
183
				include( $updater );
184
				self::update_db_version( $version );
185
			}
186
		}
187
188
		self::update_db_version();
189
	}
190
191
	/**
192
	 * Add more cron schedules.
193
	 * @param  array $schedules
194
	 * @return array
195
	 */
196
	public static function cron_schedules( $schedules ) {
197
		$schedules['monthly'] = array(
198
			'interval' => 2635200,
199
			'display'  => __( 'Monthly', 'woocommerce' )
200
		);
201
		return $schedules;
202
	}
203
204
	/**
205
	 * Create cron jobs (clear them first).
206
	 */
207
	private static function create_cron_jobs() {
208
		wp_clear_scheduled_hook( 'woocommerce_scheduled_sales' );
209
		wp_clear_scheduled_hook( 'woocommerce_cancel_unpaid_orders' );
210
		wp_clear_scheduled_hook( 'woocommerce_cleanup_sessions' );
211
		wp_clear_scheduled_hook( 'woocommerce_geoip_updater' );
212
		wp_clear_scheduled_hook( 'woocommerce_tracker_send_event' );
213
214
		$ve = get_option( 'gmt_offset' ) > 0 ? '+' : '-';
215
216
		wp_schedule_event( strtotime( '00:00 tomorrow ' . $ve . get_option( 'gmt_offset' ) . ' HOURS' ), 'daily', 'woocommerce_scheduled_sales' );
217
218
		$held_duration = get_option( 'woocommerce_hold_stock_minutes', '60' );
219
220
		if ( $held_duration != '' ) {
221
			wp_schedule_single_event( time() + ( absint( $held_duration ) * 60 ), 'woocommerce_cancel_unpaid_orders' );
222
		}
223
224
		wp_schedule_event( time(), 'twicedaily', 'woocommerce_cleanup_sessions' );
225
		wp_schedule_event( strtotime( 'first tuesday of next month' ), 'monthly', 'woocommerce_geoip_updater' );
226
		wp_schedule_event( time(), apply_filters( 'woocommerce_tracker_event_recurrence', 'daily' ), 'woocommerce_tracker_send_event' );
227
	}
228
229
	/**
230
	 * Create pages that the plugin relies on, storing page id's in variables.
231
	 */
232
	public static function create_pages() {
233
		include_once( 'admin/wc-admin-functions.php' );
234
235
		$pages = apply_filters( 'woocommerce_create_pages', array(
236
			'shop' => array(
237
				'name'    => _x( 'shop', 'Page slug', 'woocommerce' ),
238
				'title'   => _x( 'Shop', 'Page title', 'woocommerce' ),
239
				'content' => ''
240
			),
241
			'cart' => array(
242
				'name'    => _x( 'cart', 'Page slug', 'woocommerce' ),
243
				'title'   => _x( 'Cart', 'Page title', 'woocommerce' ),
244
				'content' => '[' . apply_filters( 'woocommerce_cart_shortcode_tag', 'woocommerce_cart' ) . ']'
245
			),
246
			'checkout' => array(
247
				'name'    => _x( 'checkout', 'Page slug', 'woocommerce' ),
248
				'title'   => _x( 'Checkout', 'Page title', 'woocommerce' ),
249
				'content' => '[' . apply_filters( 'woocommerce_checkout_shortcode_tag', 'woocommerce_checkout' ) . ']'
250
			),
251
			'myaccount' => array(
252
				'name'    => _x( 'my-account', 'Page slug', 'woocommerce' ),
253
				'title'   => _x( 'My Account', 'Page title', 'woocommerce' ),
254
				'content' => '[' . apply_filters( 'woocommerce_my_account_shortcode_tag', 'woocommerce_my_account' ) . ']'
255
			)
256
		) );
257
258
		foreach ( $pages as $key => $page ) {
259
			wc_create_page( esc_sql( $page['name'] ), 'woocommerce_' . $key . '_page_id', $page['title'], $page['content'], ! empty( $page['parent'] ) ? wc_get_page_id( $page['parent'] ) : '' );
260
		}
261
262
		delete_transient( 'woocommerce_cache_excluded_uris' );
263
	}
264
265
	/**
266
	 * Default options.
267
	 *
268
	 * Sets up the default options used on the settings page.
269
	 */
270
	private static function create_options() {
271
		// Include settings so that we can run through defaults
272
		include_once( 'admin/class-wc-admin-settings.php' );
273
274
		$settings = WC_Admin_Settings::get_settings_pages();
275
276
		foreach ( $settings as $section ) {
277
			if ( ! method_exists( $section, 'get_settings' ) ) {
278
				continue;
279
			}
280
			$subsections = array_unique( array_merge( array( '' ), array_keys( $section->get_sections() ) ) );
281
282
			foreach ( $subsections as $subsection ) {
283
				foreach ( $section->get_settings( $subsection ) as $value ) {
284
					if ( isset( $value['default'] ) && isset( $value['id'] ) ) {
285
						$autoload = isset( $value['autoload'] ) ? (bool) $value['autoload'] : true;
286
						add_option( $value['id'], $value['default'], '', ( $autoload ? 'yes' : 'no' ) );
287
					}
288
				}
289
			}
290
		}
291
	}
292
293
	/**
294
	 * Add the default terms for WC taxonomies - product types and order statuses. Modify this at your own risk.
295
	 */
296
	private static function create_terms() {
297
		$taxonomies = array(
298
			'product_type' => array(
299
				'simple',
300
				'grouped',
301
				'variable',
302
				'external'
303
			)
304
		);
305
306
		foreach ( $taxonomies as $taxonomy => $terms ) {
307
			foreach ( $terms as $term ) {
308
				if ( ! get_term_by( 'slug', sanitize_title( $term ), $taxonomy ) ) {
309
					wp_insert_term( $term, $taxonomy );
310
				}
311
			}
312
		}
313
	}
314
315
	/**
316
	 * Set up the database tables which the plugin needs to function.
317
	 *
318
	 * Tables:
319
	 *		woocommerce_attribute_taxonomies - Table for storing attribute taxonomies - these are user defined
320
	 *		woocommerce_termmeta - Term meta table - sadly WordPress does not have termmeta so we need our own
321
	 *		woocommerce_downloadable_product_permissions - Table for storing user and guest download permissions.
322
	 *			KEY(order_id, product_id, download_id) used for organizing downloads on the My Account page
323
	 *		woocommerce_order_items - Order line items are stored in a table to make them easily queryable for reports
324
	 *		woocommerce_order_itemmeta - Order line item meta is stored in a table for storing extra data.
325
	 *		woocommerce_tax_rates - Tax Rates are stored inside 2 tables making tax queries simple and efficient.
326
	 *		woocommerce_tax_rate_locations - Each rate can be applied to more than one postcode/city hence the second table.
327
	 */
328
	private static function create_tables() {
329
		global $wpdb;
330
331
		$wpdb->hide_errors();
332
333
		require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
334
335
		/**
336
		 * Before updating with DBDELTA, remove any primary keys which could be modified due to schema updates.
337
		 */
338 View Code Duplication
		if ( $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->prefix}woocommerce_downloadable_product_permissions';" ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
339
			if ( ! $wpdb->get_var( "SHOW COLUMNS FROM `{$wpdb->prefix}woocommerce_downloadable_product_permissions` LIKE 'permission_id';" ) ) {
340
				$wpdb->query( "ALTER TABLE {$wpdb->prefix}woocommerce_downloadable_product_permissions DROP PRIMARY KEY, ADD `permission_id` bigint(20) NOT NULL PRIMARY KEY AUTO_INCREMENT;" );
341
			}
342
		}
343
344 View Code Duplication
		if ( $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->prefix}woocommerce_tax_rate_locations';" ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
345
			if ( $wpdb->get_var( "SHOW INDEX FROM `{$wpdb->prefix}woocommerce_tax_rate_locations` WHERE Key_name LIKE 'location_type_code';" ) ) {
346
				$wpdb->query( "DROP INDEX `location_type_code` ON {$wpdb->prefix}woocommerce_tax_rate_locations;" );
347
			}
348
		}
349
350
		dbDelta( self::get_schema() );
351
	}
352
353
	/**
354
	 * Get Table schema.
355
	 * @return string
356
	 */
357
	private static function get_schema() {
358
		global $wpdb;
359
360
		$collate = '';
361
362
		if ( $wpdb->has_cap( 'collation' ) ) {
363
			$collate = $wpdb->get_charset_collate();
364
		}
365
366
		return "
367
CREATE TABLE {$wpdb->prefix}woocommerce_sessions (
368
  session_id bigint(20) NOT NULL AUTO_INCREMENT,
369
  session_key char(32) NOT NULL,
370
  session_value longtext NOT NULL,
371
  session_expiry bigint(20) NOT NULL,
372
  UNIQUE KEY session_id (session_id),
373
  PRIMARY KEY  (session_key)
374
) $collate;
375
CREATE TABLE {$wpdb->prefix}woocommerce_api_keys (
376
  key_id bigint(20) NOT NULL auto_increment,
377
  user_id bigint(20) NOT NULL,
378
  description longtext NULL,
379
  permissions varchar(10) NOT NULL,
380
  consumer_key char(64) NOT NULL,
381
  consumer_secret char(43) NOT NULL,
382
  nonces longtext NULL,
383
  truncated_key char(7) NOT NULL,
384
  last_access datetime NULL default null,
385
  PRIMARY KEY  (key_id),
386
  KEY consumer_key (consumer_key),
387
  KEY consumer_secret (consumer_secret)
388
) $collate;
389
CREATE TABLE {$wpdb->prefix}woocommerce_attribute_taxonomies (
390
  attribute_id bigint(20) NOT NULL auto_increment,
391
  attribute_name varchar(200) NOT NULL,
392
  attribute_label longtext NULL,
393
  attribute_type varchar(200) NOT NULL,
394
  attribute_orderby varchar(200) NOT NULL,
395
  attribute_public int(1) NOT NULL DEFAULT 1,
396
  PRIMARY KEY  (attribute_id),
397
  KEY attribute_name (attribute_name)
398
) $collate;
399
CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
400
  meta_id bigint(20) NOT NULL auto_increment,
401
  woocommerce_term_id bigint(20) NOT NULL,
402
  meta_key varchar(255) NULL,
403
  meta_value longtext NULL,
404
  PRIMARY KEY  (meta_id),
405
  KEY woocommerce_term_id (woocommerce_term_id),
406
  KEY meta_key (meta_key)
407
) $collate;
408
CREATE TABLE {$wpdb->prefix}woocommerce_downloadable_product_permissions (
409
  permission_id bigint(20) NOT NULL auto_increment,
410
  download_id varchar(32) NOT NULL,
411
  product_id bigint(20) NOT NULL,
412
  order_id bigint(20) NOT NULL DEFAULT 0,
413
  order_key varchar(200) NOT NULL,
414
  user_email varchar(200) NOT NULL,
415
  user_id bigint(20) NULL,
416
  downloads_remaining varchar(9) NULL,
417
  access_granted datetime NOT NULL default '0000-00-00 00:00:00',
418
  access_expires datetime NULL default null,
419
  download_count bigint(20) NOT NULL DEFAULT 0,
420
  PRIMARY KEY  (permission_id),
421
  KEY download_order_key_product (product_id,order_id,order_key,download_id),
422
  KEY download_order_product (download_id,order_id,product_id)
423
) $collate;
424
CREATE TABLE {$wpdb->prefix}woocommerce_order_items (
425
  order_item_id bigint(20) NOT NULL auto_increment,
426
  order_item_name longtext NOT NULL,
427
  order_item_type varchar(200) NOT NULL DEFAULT '',
428
  order_id bigint(20) NOT NULL,
429
  PRIMARY KEY  (order_item_id),
430
  KEY order_id (order_id)
431
) $collate;
432
CREATE TABLE {$wpdb->prefix}woocommerce_order_itemmeta (
433
  meta_id bigint(20) NOT NULL auto_increment,
434
  order_item_id bigint(20) NOT NULL,
435
  meta_key varchar(255) NULL,
436
  meta_value longtext NULL,
437
  PRIMARY KEY  (meta_id),
438
  KEY order_item_id (order_item_id),
439
  KEY meta_key (meta_key)
440
) $collate;
441
CREATE TABLE {$wpdb->prefix}woocommerce_tax_rates (
442
  tax_rate_id bigint(20) NOT NULL auto_increment,
443
  tax_rate_country varchar(200) NOT NULL DEFAULT '',
444
  tax_rate_state varchar(200) NOT NULL DEFAULT '',
445
  tax_rate varchar(200) NOT NULL DEFAULT '',
446
  tax_rate_name varchar(200) NOT NULL DEFAULT '',
447
  tax_rate_priority bigint(20) NOT NULL,
448
  tax_rate_compound int(1) NOT NULL DEFAULT 0,
449
  tax_rate_shipping int(1) NOT NULL DEFAULT 1,
450
  tax_rate_order bigint(20) NOT NULL,
451
  tax_rate_class varchar(200) NOT NULL DEFAULT '',
452
  PRIMARY KEY  (tax_rate_id),
453
  KEY tax_rate_country (tax_rate_country),
454
  KEY tax_rate_state (tax_rate_state),
455
  KEY tax_rate_class (tax_rate_class),
456
  KEY tax_rate_priority (tax_rate_priority)
457
) $collate;
458
CREATE TABLE {$wpdb->prefix}woocommerce_tax_rate_locations (
459
  location_id bigint(20) NOT NULL auto_increment,
460
  location_code varchar(255) NOT NULL,
461
  tax_rate_id bigint(20) NOT NULL,
462
  location_type varchar(40) NOT NULL,
463
  PRIMARY KEY  (location_id),
464
  KEY tax_rate_id (tax_rate_id),
465
  KEY location_type (location_type),
466
  KEY location_type_code (location_type(40),location_code(90))
467
) $collate;
468
		";
469
	}
470
471
	/**
472
	 * Create roles and capabilities.
473
	 */
474
	public static function create_roles() {
475
		global $wp_roles;
476
477
		if ( ! class_exists( 'WP_Roles' ) ) {
478
			return;
479
		}
480
481
		if ( ! isset( $wp_roles ) ) {
482
			$wp_roles = new WP_Roles();
483
		}
484
485
		// Customer role
486
		add_role( 'customer', __( 'Customer', 'woocommerce' ), array(
487
			'read' 					=> true
488
		) );
489
490
		// Shop manager role
491
		add_role( 'shop_manager', __( 'Shop Manager', 'woocommerce' ), array(
492
			'level_9'                => true,
493
			'level_8'                => true,
494
			'level_7'                => true,
495
			'level_6'                => true,
496
			'level_5'                => true,
497
			'level_4'                => true,
498
			'level_3'                => true,
499
			'level_2'                => true,
500
			'level_1'                => true,
501
			'level_0'                => true,
502
			'read'                   => true,
503
			'read_private_pages'     => true,
504
			'read_private_posts'     => true,
505
			'edit_users'             => true,
506
			'edit_posts'             => true,
507
			'edit_pages'             => true,
508
			'edit_published_posts'   => true,
509
			'edit_published_pages'   => true,
510
			'edit_private_pages'     => true,
511
			'edit_private_posts'     => true,
512
			'edit_others_posts'      => true,
513
			'edit_others_pages'      => true,
514
			'publish_posts'          => true,
515
			'publish_pages'          => true,
516
			'delete_posts'           => true,
517
			'delete_pages'           => true,
518
			'delete_private_pages'   => true,
519
			'delete_private_posts'   => true,
520
			'delete_published_pages' => true,
521
			'delete_published_posts' => true,
522
			'delete_others_posts'    => true,
523
			'delete_others_pages'    => true,
524
			'manage_categories'      => true,
525
			'manage_links'           => true,
526
			'moderate_comments'      => true,
527
			'unfiltered_html'        => true,
528
			'upload_files'           => true,
529
			'export'                 => true,
530
			'import'                 => true,
531
			'list_users'             => true
532
		) );
533
534
		$capabilities = self::get_core_capabilities();
535
536
		foreach ( $capabilities as $cap_group ) {
537
			foreach ( $cap_group as $cap ) {
538
				$wp_roles->add_cap( 'shop_manager', $cap );
539
				$wp_roles->add_cap( 'administrator', $cap );
540
			}
541
		}
542
	}
543
544
	/**
545
	 * Get capabilities for WooCommerce - these are assigned to admin/shop manager during installation or reset.
546
	 *
547
	 * @return array
548
	 */
549
	 private static function get_core_capabilities() {
550
		$capabilities = array();
551
552
		$capabilities['core'] = array(
553
			'manage_woocommerce',
554
			'view_woocommerce_reports'
555
		);
556
557
		$capability_types = array( 'product', 'shop_order', 'shop_coupon', 'shop_webhook' );
558
559
		foreach ( $capability_types as $capability_type ) {
560
561
			$capabilities[ $capability_type ] = array(
562
				// Post type
563
				"edit_{$capability_type}",
564
				"read_{$capability_type}",
565
				"delete_{$capability_type}",
566
				"edit_{$capability_type}s",
567
				"edit_others_{$capability_type}s",
568
				"publish_{$capability_type}s",
569
				"read_private_{$capability_type}s",
570
				"delete_{$capability_type}s",
571
				"delete_private_{$capability_type}s",
572
				"delete_published_{$capability_type}s",
573
				"delete_others_{$capability_type}s",
574
				"edit_private_{$capability_type}s",
575
				"edit_published_{$capability_type}s",
576
577
				// Terms
578
				"manage_{$capability_type}_terms",
579
				"edit_{$capability_type}_terms",
580
				"delete_{$capability_type}_terms",
581
				"assign_{$capability_type}_terms"
582
			);
583
		}
584
585
		return $capabilities;
586
	}
587
588
	/**
589
	 * woocommerce_remove_roles function.
590
	 */
591
	public static function remove_roles() {
592
		global $wp_roles;
593
594
		if ( ! class_exists( 'WP_Roles' ) ) {
595
			return;
596
		}
597
598
		if ( ! isset( $wp_roles ) ) {
599
			$wp_roles = new WP_Roles();
600
		}
601
602
		$capabilities = self::get_core_capabilities();
603
604
		foreach ( $capabilities as $cap_group ) {
605
			foreach ( $cap_group as $cap ) {
606
				$wp_roles->remove_cap( 'shop_manager', $cap );
607
				$wp_roles->remove_cap( 'administrator', $cap );
608
			}
609
		}
610
611
		remove_role( 'customer' );
612
		remove_role( 'shop_manager' );
613
	}
614
615
	/**
616
	 * Create files/directories.
617
	 */
618
	private static function create_files() {
619
		// Install files and folders for uploading files and prevent hotlinking
620
		$upload_dir      = wp_upload_dir();
621
		$download_method = get_option( 'woocommerce_file_download_method', 'force' );
622
623
		$files = array(
624
			array(
625
				'base' 		=> $upload_dir['basedir'] . '/woocommerce_uploads',
626
				'file' 		=> 'index.html',
627
				'content' 	=> ''
628
			),
629
			array(
630
				'base' 		=> WC_LOG_DIR,
631
				'file' 		=> '.htaccess',
632
				'content' 	=> 'deny from all'
633
			),
634
			array(
635
				'base' 		=> WC_LOG_DIR,
636
				'file' 		=> 'index.html',
637
				'content' 	=> ''
638
			)
639
		);
640
641
		if ( 'redirect' !== $download_method ) {
642
			$files[] = array(
643
				'base' 		=> $upload_dir['basedir'] . '/woocommerce_uploads',
644
				'file' 		=> '.htaccess',
645
				'content' 	=> 'deny from all'
646
			);
647
		}
648
649
		foreach ( $files as $file ) {
650
			if ( wp_mkdir_p( $file['base'] ) && ! file_exists( trailingslashit( $file['base'] ) . $file['file'] ) ) {
651
				if ( $file_handle = @fopen( trailingslashit( $file['base'] ) . $file['file'], 'w' ) ) {
652
					fwrite( $file_handle, $file['content'] );
653
					fclose( $file_handle );
654
				}
655
			}
656
		}
657
	}
658
659
	/**
660
	 * Show plugin changes. Code adapted from W3 Total Cache.
661
	 */
662
	public static function in_plugin_update_message( $args ) {
663
		$transient_name = 'wc_upgrade_notice_' . $args['Version'];
664
665
		if ( false === ( $upgrade_notice = get_transient( $transient_name ) ) ) {
666
			$response = wp_safe_remote_get( 'https://plugins.svn.wordpress.org/woocommerce/trunk/readme.txt' );
667
668
			if ( ! is_wp_error( $response ) && ! empty( $response['body'] ) ) {
669
				$upgrade_notice = self::parse_update_notice( $response['body'] );
670
				set_transient( $transient_name, $upgrade_notice, DAY_IN_SECONDS );
671
			}
672
		}
673
674
		echo wp_kses_post( $upgrade_notice );
675
	}
676
677
	/**
678
	 * Parse update notice from readme file.
679
	 * @param  string $content
680
	 * @return string
681
	 */
682
	private static function parse_update_notice( $content ) {
683
		// Output Upgrade Notice
684
		$matches        = null;
685
		$regexp         = '~==\s*Upgrade Notice\s*==\s*=\s*(.*)\s*=(.*)(=\s*' . preg_quote( WC_VERSION ) . '\s*=|$)~Uis';
686
		$upgrade_notice = '';
687
688
		if ( preg_match( $regexp, $content, $matches ) ) {
689
			$version = trim( $matches[1] );
690
			$notices = (array) preg_split('~[\r\n]+~', trim( $matches[2] ) );
691
692
			if ( version_compare( WC_VERSION, $version, '<' ) ) {
693
694
				$upgrade_notice .= '<div class="wc_plugin_upgrade_notice">';
695
696
				foreach ( $notices as $index => $line ) {
697
					$upgrade_notice .= wp_kses_post( preg_replace( '~\[([^\]]*)\]\(([^\)]*)\)~', '<a href="${2}">${1}</a>', $line ) );
698
				}
699
700
				$upgrade_notice .= '</div> ';
701
			}
702
		}
703
704
		return wp_kses_post( $upgrade_notice );
705
	}
706
707
	/**
708
	 * Show action links on the plugin screen.
709
	 *
710
	 * @param	mixed $links Plugin Action links
711
	 * @return	array
712
	 */
713
	public static function plugin_action_links( $links ) {
714
		$action_links = array(
715
			'settings' => '<a href="' . admin_url( 'admin.php?page=wc-settings' ) . '" title="' . esc_attr( __( 'View WooCommerce Settings', 'woocommerce' ) ) . '">' . __( 'Settings', 'woocommerce' ) . '</a>',
716
		);
717
718
		return array_merge( $action_links, $links );
719
	}
720
721
	/**
722
	 * Show row meta on the plugin screen.
723
	 *
724
	 * @param	mixed $links Plugin Row Meta
725
	 * @param	mixed $file  Plugin Base file
726
	 * @return	array
727
	 */
728
	public static function plugin_row_meta( $links, $file ) {
729
		if ( $file == WC_PLUGIN_BASENAME ) {
730
			$row_meta = array(
731
				'docs'    => '<a href="' . esc_url( apply_filters( 'woocommerce_docs_url', 'http://docs.woothemes.com/documentation/plugins/woocommerce/' ) ) . '" title="' . esc_attr( __( 'View WooCommerce Documentation', 'woocommerce' ) ) . '">' . __( 'Docs', 'woocommerce' ) . '</a>',
732
				'apidocs' => '<a href="' . esc_url( apply_filters( 'woocommerce_apidocs_url', 'http://docs.woothemes.com/wc-apidocs/' ) ) . '" title="' . esc_attr( __( 'View WooCommerce API Docs', 'woocommerce' ) ) . '">' . __( 'API Docs', 'woocommerce' ) . '</a>',
733
				'support' => '<a href="' . esc_url( apply_filters( 'woocommerce_support_url', 'http://support.woothemes.com/' ) ) . '" title="' . esc_attr( __( 'Visit Premium Customer Support Forum', 'woocommerce' ) ) . '">' . __( 'Premium Support', 'woocommerce' ) . '</a>',
734
			);
735
736
			return array_merge( $links, $row_meta );
737
		}
738
739
		return (array) $links;
740
	}
741
742
	/**
743
	 * Uninstall tables when MU blog is deleted.
744
	 * @param  array $tables
745
	 * @return string[]
746
	 */
747
	public static function wpmu_drop_tables( $tables ) {
748
		global $wpdb;
749
750
		$tables[] = $wpdb->prefix . 'woocommerce_sessions';
751
		$tables[] = $wpdb->prefix . 'woocommerce_api_keys';
752
		$tables[] = $wpdb->prefix . 'woocommerce_attribute_taxonomies';
753
		$tables[] = $wpdb->prefix . 'woocommerce_downloadable_product_permissions';
754
		$tables[] = $wpdb->prefix . 'woocommerce_termmeta';
755
		$tables[] = $wpdb->prefix . 'woocommerce_tax_rates';
756
		$tables[] = $wpdb->prefix . 'woocommerce_tax_rate_locations';
757
		$tables[] = $wpdb->prefix . 'woocommerce_order_items';
758
		$tables[] = $wpdb->prefix . 'woocommerce_order_itemmeta';
759
760
		return $tables;
761
	}
762
}
763
764
WC_Install::init();
765