Passed
Push — master ( dbd34e...7fc9f5 )
by Brian
04:27
created

GetPaid_Installer   A

Complexity

Total Complexity 38

Size/Duplication

Total Lines 528
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 198
dl 0
loc 528
rs 9.36
c 0
b 0
f 0
wmc 38

13 Methods

Rating   Name   Duplication   Size   Complexity  
A upgrade_db() 0 31 3
A rename_gateways_label() 0 11 2
A upgrade_from_0() 0 4 1
A upgrade_from_118() 0 2 1
C migrate_old_invoices() 0 124 12
A create_db_tables() 0 12 1
A maybe_create_db_tables() 0 3 2
A get_pages() 0 60 1
A upgrade_from_004() 0 25 5
A is_db_schema_up_to_date() 0 2 1
B get_db_schema() 0 154 6
A add_capabilities() 0 2 1
A create_pages() 0 4 2
1
<?php
2
/**
3
 * Contains the main installer class.
4
 *
5
 * @package GetPaid
6
 * @subpackage Admin
7
 * @version 2.0.2
8
 * @since   2.0.2
9
 */
10
11
defined( 'ABSPATH' ) || exit;
12
13
/**
14
 * The main installer/updater class.
15
 *
16
 * @package GetPaid
17
 * @subpackage Admin
18
 * @version 2.0.2
19
 * @since   2.0.2
20
 */
21
class GetPaid_Installer {
22
23
	/**
24
	 * Upgrades the install.
25
	 *
26
	 * @param string $upgrade_from The current invoicing version.
27
	 */
28
	public function upgrade_db( $upgrade_from ) {
29
30
		// Save the current invoicing version.
31
		update_option( 'wpinv_version', WPINV_VERSION );
32
33
		// Setup the invoice Custom Post Type.
34
		GetPaid_Post_Types::register_post_types();
35
36
		// Clear the permalinks
37
		flush_rewrite_rules();
38
39
		// Maybe create new/missing pages.
40
		$this->create_pages();
41
42
		// Maybe re(add) admin capabilities.
43
		$this->add_capabilities();
44
45
		// Maybe create the default payment form.
46
		wpinv_get_default_payment_form();
47
48
		// Create any missing database tables.
49
		$method = "upgrade_from_$upgrade_from";
50
51
		$installed = get_option( 'gepaid_installed_on' );
52
53
		if ( empty( $installed ) ) {
54
			update_option( 'gepaid_installed_on', time() );
55
		}
56
57
		if ( method_exists( $this, $method ) ) {
58
			$this->$method();
59
		}
60
61
	}
62
63
	/**
64
	 * Do a fresh install.
65
	 *
66
	 */
67
	public function upgrade_from_0() {
68
69
		// Save default tax rates.
70
		update_option( 'wpinv_tax_rates', wpinv_get_data( 'tax-rates' ) );
71
	}
72
73
	/**
74
	 * Upgrade to 0.0.5
75
	 *
76
	 */
77
	public function upgrade_from_004() {
78
		global $wpdb;
79
80
		// Invoices.
81
		$results = $wpdb->get_results( "SELECT ID FROM {$wpdb->posts} WHERE post_type = 'wpi_invoice' AND post_status IN( 'pending', 'processing', 'onhold', 'refunded', 'cancelled', 'failed', 'renewal' )" );
82
		if ( ! empty( $results ) ) {
83
			$wpdb->query( "UPDATE {$wpdb->posts} SET post_status = CONCAT( 'wpi-', post_status ) WHERE post_type = 'wpi_invoice' AND post_status IN( 'pending', 'processing', 'onhold', 'refunded', 'cancelled', 'failed', 'renewal' )" );
84
85
			// Clean post cache
86
			foreach ( $results as $row ) {
87
				clean_post_cache( $row->ID );
88
			}
89
		}
90
91
		// Item meta key changes
92
		$query = 'SELECT DISTINCT post_id FROM ' . $wpdb->postmeta . " WHERE meta_key IN( '_wpinv_item_id', '_wpinv_package_id', '_wpinv_post_id', '_wpinv_cpt_name', '_wpinv_cpt_singular_name' )";
93
		$results = $wpdb->get_results( $query );
94
95
		if ( ! empty( $results ) ) {
96
			$wpdb->query( 'UPDATE ' . $wpdb->postmeta . " SET meta_key = '_wpinv_custom_id' WHERE meta_key IN( '_wpinv_item_id', '_wpinv_package_id', '_wpinv_post_id' )" );
97
			$wpdb->query( 'UPDATE ' . $wpdb->postmeta . " SET meta_key = '_wpinv_custom_name' WHERE meta_key = '_wpinv_cpt_name'" );
98
			$wpdb->query( 'UPDATE ' . $wpdb->postmeta . " SET meta_key = '_wpinv_custom_singular_name' WHERE meta_key = '_wpinv_cpt_singular_name'" );
99
100
			foreach ( $results as $row ) {
101
				clean_post_cache( $row->post_id );
102
			}
103
		}
104
105
	}
106
107
	/**
108
	 * Upgrade to version 2.0.0.
109
	 *
110
	 */
111
	public function upgrade_from_118() {
112
		$this->migrate_old_invoices();
113
	}
114
115
	/**
116
	 * Give administrators the capability to manage GetPaid.
117
	 *
118
	 */
119
	public function add_capabilities() {
120
		$GLOBALS['wp_roles']->add_cap( 'administrator', 'manage_invoicing' );
121
	}
122
123
	/**
124
	 * Retreives GetPaid pages.
125
	 *
126
	 */
127
	public static function get_pages() {
128
129
		return apply_filters(
130
			'wpinv_create_pages',
131
			array(
132
133
				// Checkout page.
134
				'checkout_page'             => array(
135
					'name'    => _x( 'gp-checkout', 'Page slug', 'invoicing' ),
136
					'title'   => _x( 'Checkout', 'Page title', 'invoicing' ),
137
					'content' => '
138
						<!-- wp:shortcode -->
139
						[wpinv_checkout]
140
						<!-- /wp:shortcode -->
141
					',
142
					'parent'  => '',
143
				),
144
145
				// Invoice history page.
146
				'invoice_history_page'      => array(
147
					'name'    => _x( 'gp-invoices', 'Page slug', 'invoicing' ),
148
					'title'   => _x( 'My Invoices', 'Page title', 'invoicing' ),
149
					'content' => '
150
					<!-- wp:shortcode -->
151
					[wpinv_history]
152
					<!-- /wp:shortcode -->
153
				',
154
					'parent'  => '',
155
				),
156
157
				// Success page content.
158
				'success_page'              => array(
159
					'name'    => _x( 'gp-receipt', 'Page slug', 'invoicing' ),
160
					'title'   => _x( 'Payment Confirmation', 'Page title', 'invoicing' ),
161
					'content' => '
162
					<!-- wp:shortcode -->
163
					[wpinv_receipt]
164
					<!-- /wp:shortcode -->
165
				',
166
					'parent'  => 'gp-checkout',
167
				),
168
169
				// Failure page content.
170
				'failure_page'              => array(
171
					'name'    => _x( 'gp-transaction-failed', 'Page slug', 'invoicing' ),
172
					'title'   => _x( 'Transaction Failed', 'Page title', 'invoicing' ),
173
					'content' => __( 'Your transaction failed, please try again or contact site support.', 'invoicing' ),
174
					'parent'  => 'gp-checkout',
175
				),
176
177
				// Subscriptions history page.
178
				'invoice_subscription_page' => array(
179
					'name'    => _x( 'gp-subscriptions', 'Page slug', 'invoicing' ),
180
					'title'   => _x( 'My Subscriptions', 'Page title', 'invoicing' ),
181
					'content' => '
182
					<!-- wp:shortcode -->
183
					[wpinv_subscriptions]
184
					<!-- /wp:shortcode -->
185
				',
186
					'parent'  => '',
187
				),
188
189
			)
190
		);
191
192
	}
193
194
	/**
195
	 * Re-create GetPaid pages.
196
	 *
197
	 */
198
	public function create_pages() {
199
200
		foreach ( self::get_pages() as $key => $page ) {
201
			wpinv_create_page( esc_sql( $page['name'] ), $key, $page['title'], $page['content'], $page['parent'] );
202
		}
203
204
	}
205
206
	/**
207
	 * Migrates old invoices to new invoices.
208
	 *
209
	 */
210
	public function migrate_old_invoices() {
211
		global $wpdb;
212
213
		$invoices_table      = $wpdb->prefix . 'getpaid_invoices';
214
		$invoice_items_table = $wpdb->prefix . 'getpaid_invoice_items';
215
		$migrated            = $wpdb->get_col( "SELECT post_id FROM $invoices_table" );
216
		$invoices            = array_unique(
217
			get_posts(
218
				array(
219
					'post_type'      => array( 'wpi_invoice', 'wpi_quote' ),
220
					'posts_per_page' => -1,
221
					'fields'         => 'ids',
222
					'post_status'    => array_keys( get_post_stati() ),
223
					'exclude'        => (array) $migrated,
224
				)
225
			)
226
		);
227
228
		// Abort if we do not have any invoices.
229
		if ( empty( $invoices ) ) {
230
			return;
231
		}
232
233
		require_once WPINV_PLUGIN_DIR . 'includes/class-wpinv-legacy-invoice.php';
234
235
		$invoice_rows = array();
236
		foreach ( $invoices as $invoice ) {
237
238
			$invoice = new WPInv_Legacy_Invoice( $invoice );
239
240
			if ( empty( $invoice->ID ) ) {
241
				return;
242
			}
243
244
			$fields = array(
245
				'post_id'            => $invoice->ID,
246
				'number'             => $invoice->get_number(),
247
				'key'                => $invoice->get_key(),
248
				'type'               => str_replace( 'wpi_', '', $invoice->post_type ),
249
				'mode'               => $invoice->mode,
250
				'user_ip'            => $invoice->get_ip(),
251
				'first_name'         => $invoice->get_first_name(),
252
				'last_name'          => $invoice->get_last_name(),
253
				'address'            => $invoice->get_address(),
254
				'city'               => $invoice->city,
255
				'state'              => $invoice->state,
256
				'country'            => $invoice->country,
257
				'zip'                => $invoice->zip,
258
				'adddress_confirmed' => (int) $invoice->adddress_confirmed,
259
				'gateway'            => $invoice->get_gateway(),
260
				'transaction_id'     => $invoice->get_transaction_id(),
261
				'currency'           => $invoice->get_currency(),
262
				'subtotal'           => $invoice->get_subtotal(),
263
				'tax'                => $invoice->get_tax(),
264
				'fees_total'         => $invoice->get_fees_total(),
265
				'total'              => $invoice->get_total(),
266
				'discount'           => $invoice->get_discount(),
267
				'discount_code'      => $invoice->get_discount_code(),
268
				'disable_taxes'      => $invoice->disable_taxes,
269
				'due_date'           => $invoice->get_due_date(),
270
				'completed_date'     => $invoice->get_completed_date(),
271
				'company'            => $invoice->company,
272
				'vat_number'         => $invoice->vat_number,
273
				'vat_rate'           => $invoice->vat_rate,
274
				'custom_meta'        => $invoice->payment_meta,
275
			);
276
277
			foreach ( $fields as $key => $val ) {
278
				if ( is_null( $val ) ) {
279
					$val = '';
280
				}
281
				$val = maybe_serialize( $val );
282
				$fields[ $key ] = $wpdb->prepare( '%s', $val );
283
			}
284
285
			$fields = implode( ', ', $fields );
286
			$invoice_rows[] = "($fields)";
287
288
			$item_rows    = array();
289
			$item_columns = array();
290
			foreach ( $invoice->get_cart_details() as $details ) {
291
				$fields = array(
292
					'post_id'          => $invoice->ID,
293
					'item_id'          => $details['id'],
294
					'item_name'        => $details['name'],
295
					'item_description' => empty( $details['meta']['description'] ) ? '' : $details['meta']['description'],
296
					'vat_rate'         => $details['vat_rate'],
297
					'vat_class'        => empty( $details['vat_class'] ) ? '_standard' : $details['vat_class'],
298
					'tax'              => $details['tax'],
299
					'item_price'       => $details['item_price'],
300
					'custom_price'     => $details['custom_price'],
301
					'quantity'         => $details['quantity'],
302
					'discount'         => $details['discount'],
303
					'subtotal'         => $details['subtotal'],
304
					'price'            => $details['price'],
305
					'meta'             => $details['meta'],
306
					'fees'             => $details['fees'],
307
				);
308
309
				$item_columns = array_keys( $fields );
310
311
				foreach ( $fields as $key => $val ) {
312
					if ( is_null( $val ) ) {
313
						$val = '';
314
					}
315
					$val = maybe_serialize( $val );
316
					$fields[ $key ] = $wpdb->prepare( '%s', $val );
317
				}
318
319
				$fields = implode( ', ', $fields );
320
				$item_rows[] = "($fields)";
321
			}
322
323
			$item_rows    = implode( ', ', $item_rows );
324
			$item_columns = implode( ', ', $item_columns );
325
			$wpdb->query( "INSERT INTO $invoice_items_table ($item_columns) VALUES $item_rows" );
326
		}
327
328
		if ( empty( $invoice_rows ) ) {
329
			return;
330
		}
331
332
		$invoice_rows = implode( ', ', $invoice_rows );
333
		$wpdb->query( "INSERT INTO $invoices_table VALUES $invoice_rows" );
334
335
	}
336
337
	/**
338
	 * Migrates old invoices to new invoices.
339
	 *
340
	 */
341
	public static function rename_gateways_label() {
342
		global $wpdb;
343
344
		foreach ( array_keys( wpinv_get_payment_gateways() ) as $gateway ) {
345
346
			$wpdb->update(
347
				$wpdb->prefix . 'getpaid_invoices',
348
				array( 'gateway' => $gateway ),
349
				array( 'gateway' => wpinv_get_gateway_admin_label( $gateway ) ),
350
				'%s',
351
				'%s'
352
			);
353
354
		}
355
	}
356
357
	/**
358
	 * Returns the DB schema.
359
	 *
360
	 */
361
	public static function get_db_schema() {
362
		global $wpdb;
363
364
		require_once ABSPATH . 'wp-admin/includes/upgrade.php';
365
366
		$charset_collate = $wpdb->get_charset_collate();
367
368
		// Subscriptions.
369
		$schema = "CREATE TABLE {$wpdb->prefix}wpinv_subscriptions (
370
			id bigint(20) unsigned NOT NULL auto_increment,
371
			customer_id bigint(20) NOT NULL,
372
			frequency int(11) NOT NULL DEFAULT '1',
373
			period varchar(20) NOT NULL,
374
			initial_amount DECIMAL(16,4) NOT NULL,
375
			recurring_amount DECIMAL(16,4) NOT NULL,
376
			bill_times bigint(20) NOT NULL,
377
			transaction_id varchar(60) NOT NULL,
378
			parent_payment_id bigint(20) NOT NULL,
379
			product_id bigint(20) NOT NULL,
380
			created datetime NOT NULL,
381
			expiration datetime NOT NULL,
382
			trial_period varchar(20) NOT NULL,
383
			profile_id varchar(60) NOT NULL,
384
			status varchar(20) NOT NULL,
385
			PRIMARY KEY  (id),
386
			KEY profile_id (profile_id),
387
			KEY customer (customer_id),
388
			KEY transaction (transaction_id),
389
			KEY customer_and_status (customer_id, status)
390
		  ) $charset_collate;";
391
392
		// Invoices.
393
		$schema .= "CREATE TABLE {$wpdb->prefix}getpaid_invoices (
394
			post_id BIGINT(20) NOT NULL,
395
            `number` VARCHAR(100),
396
            `key` VARCHAR(100),
397
            `type` VARCHAR(100) NOT NULL DEFAULT 'invoice',
398
            mode VARCHAR(100) NOT NULL DEFAULT 'live',
399
            user_ip VARCHAR(100),
400
            first_name VARCHAR(100),
401
            last_name VARCHAR(100),
402
            `address` VARCHAR(100),
403
            city VARCHAR(100),
404
            `state` VARCHAR(100),
405
            country VARCHAR(100),
406
            zip VARCHAR(100),
407
            adddress_confirmed INT(10),
408
            gateway VARCHAR(100),
409
            transaction_id VARCHAR(100),
410
            currency VARCHAR(10),
411
            subtotal DECIMAL(16,4) NOT NULL DEFAULT 0,
412
            tax DECIMAL(16,4) NOT NULL DEFAULT 0,
413
            fees_total DECIMAL(16,4) NOT NULL DEFAULT 0,
414
            total DECIMAL(16,4) NOT NULL DEFAULT 0,
415
            discount DECIMAL(16,4) NOT NULL DEFAULT 0,
416
            discount_code VARCHAR(100),
417
            disable_taxes INT(2) NOT NULL DEFAULT 0,
418
            due_date DATETIME,
419
            completed_date DATETIME,
420
            company VARCHAR(100),
421
            vat_number VARCHAR(100),
422
            vat_rate VARCHAR(100),
423
            custom_meta TEXT,
424
			PRIMARY KEY  (post_id),
425
			KEY number (number),
426
			KEY `key` (`key`)
427
		  ) $charset_collate;";
428
429
		// Invoice items.
430
		$schema .= "CREATE TABLE {$wpdb->prefix}getpaid_invoice_items (
431
			ID BIGINT(20) NOT NULL AUTO_INCREMENT,
432
            post_id BIGINT(20) NOT NULL,
433
            item_id BIGINT(20) NOT NULL,
434
            item_name TEXT NOT NULL,
435
            item_description TEXT NOT NULL,
436
            vat_rate FLOAT NOT NULL DEFAULT 0,
437
            vat_class VARCHAR(100),
438
            tax DECIMAL(16,4) NOT NULL DEFAULT 0,
439
            item_price DECIMAL(16,4) NOT NULL DEFAULT 0,
440
            custom_price DECIMAL(16,4) NOT NULL DEFAULT 0,
441
            quantity FLOAT(20) NOT NULL DEFAULT 1,
442
            discount DECIMAL(16,4) NOT NULL DEFAULT 0,
443
            subtotal DECIMAL(16,4) NOT NULL DEFAULT 0,
444
            price DECIMAL(16,4) NOT NULL DEFAULT 0,
445
            meta TEXT,
446
            fees TEXT,
447
			PRIMARY KEY  (ID),
448
			KEY item_id (item_id),
449
			KEY post_id (post_id)
450
		  ) $charset_collate;";
451
452
		// Customers.
453
		$schema .= "CREATE TABLE {$wpdb->prefix}getpaid_customers (
454
			id BIGINT(20) NOT NULL AUTO_INCREMENT,
455
			user_id BIGINT(20) NOT NULL,
456
			email VARCHAR(100) NOT NULL,
457
			email_cc TEXT,
458
			status VARCHAR(100) NOT NULL DEFAULT 'active',
459
			purchase_value DECIMAL(18,9) NOT NULL DEFAULT 0,
460
			purchase_count BIGINT(20) NOT NULL DEFAULT 0,
461
			";
462
463
		// Add address fields.
464
		foreach ( array_keys( getpaid_user_address_fields() ) as $field ) {
465
466
			// Skip id, user_id and email.
467
			if ( in_array( $field, array( 'id', 'user_id', 'email', 'purchase_value', 'purchase_count', 'date_created', 'date_modified', 'uuid' ), true ) ) {
468
				continue;
469
			}
470
471
			$field   = sanitize_key( $field );
472
			$length  = 100;
473
			$default = '';
474
475
			// Country.
476
			if ( 'country' === $field ) {
477
				$length  = 2;
478
				$default = wpinv_get_default_country();
479
			}
480
481
			// State.
482
			if ( 'state' === $field ) {
483
				$default = wpinv_get_default_state();
484
			}
485
486
			// Phone, zip.
487
			if ( in_array( $field, array( 'phone', 'zip' ), true ) ) {
488
				$length = 20;
489
			}
490
491
			$schema .= "`$field` VARCHAR($length) NOT NULL DEFAULT '$default',";
492
		}
493
494
		$schema .= "
495
			date_created DATETIME NOT NULL,
496
			date_modified DATETIME NOT NULL,
497
			uuid VARCHAR(100) NOT NULL,
498
			PRIMARY KEY  (id),
499
			KEY user_id (user_id),
500
			KEY email (email)
501
		  ) $charset_collate";
502
503
		// Customer meta.
504
		$schema .= "CREATE TABLE {$wpdb->prefix}getpaid_customer_meta (
505
			meta_id BIGINT(20) NOT NULL AUTO_INCREMENT,
506
			customer_id BIGINT(20) NOT NULL,
507
			meta_key VARCHAR(255) NOT NULL,
508
			meta_value LONGTEXT,
509
			PRIMARY KEY  (meta_id),
510
			KEY customer_id (customer_id),
511
			KEY meta_key (meta_key(191))
512
		  ) $charset_collate";
513
514
		return $schema;
515
	}
516
517
	/**
518
	 * Checks if the db schema is up to date.
519
	 *
520
	 * @return bool
521
	 */
522
	public static function is_db_schema_up_to_date() {
523
		return md5( self::get_db_schema() ) === get_option( 'getpaid_db_schema' );
524
	}
525
526
	/**
527
	 * Set up the database tables which the plugin needs to function.
528
	 */
529
	public static function create_db_tables() {
530
		global $wpdb;
531
532
		$wpdb->hide_errors();
533
534
		require_once ABSPATH . 'wp-admin/includes/upgrade.php';
535
536
		$schema = self::get_db_schema();
537
538
		dbDelta( $schema );
539
540
		update_option( 'getpaid_db_schema', md5( self::get_db_schema() ) );
541
	}
542
543
	/**
544
	 * Creates tables if schema is not up to date.
545
	 */
546
	public static function maybe_create_db_tables() {
547
		if ( ! self::is_db_schema_up_to_date() ) {
548
			self::create_db_tables();
549
		}
550
	}
551
}
552