Passed
Push — master ( ad1bda...a722cd )
by Chris
02:54
created

MonsterInsights_Install::v700_upgrades()   B

Complexity

Conditions 9
Paths 54

Size

Total Lines 30
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 12
nc 54
nop 0
dl 0
loc 30
rs 8.0555
c 0
b 0
f 0
1
<?php
2
/**
3
 * MonsterInsights Installation and Automatic Upgrades.
4
 *
5
 * This file handles setting up new
6
 * MonsterInsights installs as well as performing
7
 * behind the scene upgrades between
8
 * MonsterInsights versions.
9
 *
10
 * @package MonsterInsights
11
 * @subpackage Install/Upgrade
12
 * @since 6.0.0
13
 */
14
15
// Exit if accessed directly
16
if ( ! defined( 'ABSPATH' ) ) {
17
	exit;
18
}
19
20
/**
21
 * MonsterInsights Install.
22
 *
23
 * This class handles a new MI install
24
 * as well as automatic (non-user initiated)
25
 * upgrade routines.
26
 *
27
 * @since 6.0.0
28
 * @access public
29
 */
30
class MonsterInsights_Install {
31
32
	/**
33
	 * MI Settings.
34
	 *
35
	 * @since 6.0.0
36
	 * @access public
37
	 * @var array $new_settings When the init() function starts, initially
38
	 *      					contains the original settings. At the end
39
	 *      				 	of init() contains the settings to save.
40
	 */
41
	public $new_settings = array();
42
43
	/**
44
	 * Install/Upgrade routine.
45
	 *
46
	 * This function is what is called to actually install MI data on new installs and to do
47
	 * behind the scenes upgrades on MI upgrades. If this function contains a bug, the results
48
	 * can be catastrophic. This function gets the highest priority in all of MI for unit tests.
49
	 *
50
	 * @since 6.0.0
51
	 * @access public
52
	 *
53
	 * @return void
54
	 */
55
	public function init() {
56
57
		// Get a copy of the current MI settings.
58
		$this->new_settings = get_option( monsterinsights_get_option_name() );
0 ignored issues
show
Documentation Bug introduced by
It seems like get_option(monsterinsights_get_option_name()) can also be of type false. However, the property $new_settings is declared as type array. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
59
60
61
		$version = get_option( 'monsterinsights_current_version', false );
62
		$cachec  = false; // have we forced an object cache to be cleared already (so we don't clear it unnecessarily)
63
64
		// if new install or Yoast Era instal
65
		if ( ! $version ) {
66
			// See if from Yoast
67
			$yoast   = get_option( 'yst_ga', false );
68
69
			// In case from Yoast, start from scratch
70
			delete_option( 'yoast-ga-access_token' );
71
			delete_option( 'yoast-ga-refresh_token' );
72
			delete_option( 'yst_ga' );
73
			delete_option( 'yst_ga_api' );
74
75
			$this->new_install();
76
77
			// set db version (Do not increment! See below large comment)
78
			update_option( 'monsterinsights_db_version', '7.4.0' );
79
80
			// Remove Yoast hook if present
81
			if ( wp_next_scheduled( 'yst_ga_aggregate_data' ) ) {
82
				wp_clear_scheduled_hook( 'yst_ga_aggregate_data' );
83
			}
84
85
			// Clear cache since coming from Yoast
86
			if ( ! $cachec && ! empty( $yoast ) ) {
0 ignored issues
show
introduced by
The condition $cachec is always false.
Loading history...
87
				wp_cache_flush();
88
				$cachec = true;
0 ignored issues
show
Unused Code introduced by
The assignment to $cachec is dead and can be removed.
Loading history...
89
			}
90
		} else { // if existing install
91
			if ( version_compare( $version, '6.0.11', '<' ) ) {
92
				if ( ! $cachec ) {
0 ignored issues
show
introduced by
The condition $cachec is always false.
Loading history...
93
					wp_cache_flush();
94
					$cachec = true;
95
				}
96
			}
97
98
			if ( version_compare( $version, '7.0.0', '<' ) ) {
99
				$this->v700_upgrades();
100
			}
101
102
			if ( version_compare( $version, '7.4.0', '<' ) ) {
103
				$this->v740_upgrades();
104
				// Do not increment! See below large comment
105
				update_option( 'monsterinsights_db_version', '7.4.0' );
106
			}
107
108
			// Do not use. See monsterinsights_after_install_routine comment below.
109
			do_action( 'monsterinsights_after_existing_upgrade_routine', $version );
110
			$version = get_option( 'monsterinsights_current_version', $version );
111
			update_option( 'monsterinsights_version_upgraded_from', $version );
112
		}
113
114
		// This hook is used primarily by the Pro version to run some Pro
115
		// specific install stuff. Please do not use this hook. It is not
116
		// considered a public hook by MI's dev team and can/will be removed,
117
		// relocated, and/or altered without warning at any time. You've been warned.
118
		// As this hook is not for public use, we've intentionally not docbloc'd this
119
		// hook to avoid developers seeing it future public dev docs.
120
		do_action( 'monsterinsights_after_install_routine', $version );
121
122
		// This is the version of MI installed
123
		update_option( 'monsterinsights_current_version', MONSTERINSIGHTS_VERSION );
124
125
		// This is where we save MI settings
126
		update_option( monsterinsights_get_option_name(), $this->new_settings );
127
128
		// There's no code for this function below this. Just an explanation
129
		// of the MI core options.
130
131
		/**
132
		 * Explanation of MonsterInsights core options
133
		 *
134
		 * By now your head is probably spinning trying to figure
135
		 * out what all of these version options are for. Note, I've abbreviated
136
		 * "monsterinsights" to "mi" in the options names to make this table easier
137
		 * to read.
138
		 *
139
		 * Here's a basic rundown:
140
		 *
141
		 * mi_current_version:  This starts with the actual version MI was
142
		 * 						installed on. We use this version to
143
		 * 						determine whether or not a site needs
144
		 * 						to run one of the behind the scenes
145
		 * 						MI upgrade routines. This version is updated
146
		 * 						every time a minor or major background upgrade
147
		 * 						routine is run. Generally lags behind the
148
		 * 						MONSTERINSIGHTS_VERSION constant by at most a couple minor
149
		 * 						versions. Never lags behind by 1 major version
150
		 * 						or more generally.
151
		 *
152
		 * mi_db_version: 		This is different from mi_current_version.
153
		 * 						Unlike the former, this is used to determine
154
		 * 						if a site needs to run a *user* initiated
155
		 * 						upgrade routine (incremented in MI_Upgrade class). This
156
		 * 						value is only update when a user initiated
157
		 * 						upgrade routine is done. Because we do very
158
		 * 						few user initiated upgrades compared to
159
		 * 						automatic ones, this version can lag behind by
160
		 * 						2 or even 3 major versions. Generally contains
161
		 * 						the current major version.
162
		 *
163
		 * mi_settings:		    Returned by monsterinsights_get_option_name(), this
164
		 * 						is actually "monsterinsights_settings" for both pro
165
		 * 						and lite version. However we use a helper function to
166
		 * 						retrieve the option name in case we ever decide down the
167
		 * 						road to maintain seperate options for the Lite and Pro versions.
168
		 * 					 	If you need to access MI's settings directly, (as opposed to our
169
		 * 					 	monsterinsights_get_option helper which uses the option name helper
170
		 * 					 	automatically), you should use this function to get the
171
		 * 					 	name of the option to retrieve.
172
		 *
173
		 * Therefore you should never increment mi_db_version in this file and always increment mi_current_version.
174
		 */
175
	}
176
177
178
	/**
179
	 * New MonsterInsights Install routine.
180
	 *
181
	 * This function installs all of the default
182
	 * things on new MI installs. Flight 5476 with
183
	 * non-stop service to a whole world of
184
	 * possibilities is now boarding.
185
	 *
186
	 * @since 6.0.0
187
	 * @access public
188
	 *
189
	 * @return void
190
	 */
191
	public function new_install() {
192
193
		// Add default settings values
194
		$this->new_settings = $this->get_monsterinsights_default_values();
195
196
		$data = array(
197
			'installed_version' => MONSTERINSIGHTS_VERSION,
198
			'installed_date'    => time(),
199
			'installed_pro'     => monsterinsights_is_pro_version(),
200
		);
201
202
		update_option( 'monsterinsights_over_time', $data );
203
204
		// Let addons + MI Pro/Lite hook in here. @todo: doc as nonpublic
205
		do_action( 'monsterinsights_after_new_install_routine', MONSTERINSIGHTS_VERSION );
206
	}
207
208
	public function get_monsterinsights_default_values() {
209
		return array(
210
			'enable_affiliate_links'    => true,
211
			'affiliate_links'           => array(
212
				array(
213
					'path'  => '/go/',
214
					'label' => 'affiliate',
215
				),
216
				array(
217
					'path'  => '/recommend/',
218
					'label' => 'affiliate',
219
				)
220
			),
221
			'demographics'              => 1,
222
			'ignore_users'              => array( 'administrator' ),
223
			'dashboards_disabled'       => 0,
224
			'anonymize_ips'             => 0,
225
			'extensions_of_files'       => 'doc,exe,js,pdf,ppt,tgz,zip,xls',
226
			'subdomain_tracking'        => '',
227
			'tag_links_in_rss'          => 0,
228
			'allow_anchor'              => 0,
229
			'add_allow_linker'          => 0,
230
			'custom_code'               => '',
231
			'save_settings'             => array( 'administrator' ),
232
			'view_reports'              => array( 'administrator', 'editor' ),
233
		);
234
	}
235
236
	/**
237
	 * MonsterInsights Version 7.0 upgrades.
238
	 *
239
	 * This function does the
240
	 * upgrade routine from MonsterInsights 6.2->7.0.
241
	 *
242
	 * @since 7.0.0
243
	 * @access public
244
	 *
245
	 * @return void
246
	 */
247
	public function v700_upgrades() {
248
		// 1. Default all event tracking and tracking to GA + JS respectively
249
			// 3a Set tracking_mode to use analytics.js
250
			$this->new_settings['tracking_mode' ] = 'analytics';
251
252
253
			// 3b Set events mode to use JS if the events mode is not set explicitly to none
254
			if ( empty( $this->new_settings['events_mode' ] ) || $this->new_settings['events_mode' ] !== 'none' ) {
255
				$this->new_settings['events_mode' ] = 'js';
256
			}
257
258
		// 2. Migrate manual UA codes
259
			// 2a Manual UA has the lowest priority
260
			if ( ! empty( $this->new_settings['manual_ua_code' ] ) ) {
261
				// Set as manual UA code
262
				is_network_admin() ? update_site_option( 'monsterinsights_network_profile', array( 'manual' => $this->new_settings['manual_ua_code' ] ) ) : update_option( 'monsterinsights_site_profile', array( 'manual' => $this->new_settings['manual_ua_code' ] ) );
263
			}
264
265
			// 2b Then try the oAuth UA code
266
			if ( ! empty( $this->new_settings['analytics_profile_code' ] ) ) {
267
				// Set as manual UA code
268
				is_network_admin() ? update_site_option( 'monsterinsights_network_profile', array( 'manual' => $this->new_settings['analytics_profile_code' ] ) ) : update_option( 'monsterinsights_site_profile', array( 'manual' => $this->new_settings['analytics_profile_code' ] ) );
269
			}
270
271
		// 3. Migrate License keys
272
		if ( is_multisite() ) {
273
			$ms_license = get_site_option( 'monsterinsights_license', '' );
274
			if ( $ms_license ) {
275
				update_site_option( 'monsterinsights_network_license_updates', get_site_option( 'monsterinsights_license_updates', '' ) );
276
				update_site_option( 'monsterinsights_network_license', $ms_license );
277
			}
278
		}
279
	}
280
281
	/**
282
	 * Upgrade routine for the new settings panel, onboarding wizard, and the internal-as-outbound v2 settings system.
283
	 */
284
	public function v740_upgrades() {
285
286
		// 1. Settings Conversions:
287
			// Convert affiliate field to repeater format
288
			if ( ! empty( $this->new_settings['track_internal_as_outbound'] ) ) {
289
				$affiliate_old_paths = $this->new_settings['track_internal_as_outbound'];
290
				$affiliate_old_label = isset( $this->new_settings['track_internal_as_label'] ) ? $this->new_settings['track_internal_as_label'] : '';
291
292
				$new_paths = explode( ',', $affiliate_old_paths );
293
294
				$this->new_settings['affiliate_links'] = array();
295
				if ( ! empty( $new_paths ) ) {
296
					$this->new_settings['enable_affiliate_links'] = true;
297
					foreach ( $new_paths as $new_path ) {
298
						$this->new_settings['affiliate_links'][] = array(
299
							'path'  => $new_path,
300
							'label' => $affiliate_old_label,
301
						);
302
					}
303
				}
304
305
				$settings = array(
306
					'track_internal_as_outbound',
307
					'track_internal_as_label',
308
				);
309
				foreach ( $settings as $setting ) {
310
					if ( ! empty( $this->new_settings[ $setting ] ) ) {
311
						unset( $this->new_settings[ $setting ] );
312
					}
313
				}
314
			}
315
316
			// Update option to disable just reports or also the dashboard widget.
317
			if ( isset( $this->new_settings['dashboards_disabled'] ) && $this->new_settings['dashboards_disabled'] ) {
318
				$this->new_settings['dashboards_disabled'] = 'disabled';
319
			}
320
321
			$this->new_settings['tracking_mode'] = 'analytics';
322
			$this->new_settings['events_mode']   = 'js';
323
324
			// If opted in during allow_tracking era, move that over
325
			if ( ! empty( $this->new_settings['allow_tracking'] ) ) {
326
				$this->new_settings['anonymous_data'] = 1;
327
			}
328
329
		// 2. Remove Yoast stuff
330
			delete_option( 'yoast-ga-access_token' );
331
			delete_option( 'yoast-ga-refresh_token' );
332
			delete_option( 'yst_ga' );
333
			delete_option( 'yst_ga_api' );
334
335
336
		// 3. Remove fake settings from other plugins using our key for some reason and old settings of ours
337
			$settings = array(
338
				'debug_mode',
339
				'track_download_as',
340
				'analytics_profile',
341
				'analytics_profile_code',
342
				'analytics_profile_name',
343
				'manual_ua_code',
344
				'track_outbound',
345
				'track_download_as',
346
				'enhanced_link_attribution',
347
				'oauth_version',
348
				'monsterinsights_oauth_status',
349
				'firebug_lite',
350
				'google_auth_code',
351
				'allow_tracking',
352
			);
353
354
			foreach ( $settings as $setting ) {
355
				if ( ! empty( $this->new_settings[ $setting ] ) ) {
356
					unset( $this->new_settings[ $setting ] );
357
				}
358
			}
359
360
			$settings = array(
361
				'_repeated',
362
				'ajax',
363
				'asmselect0',
364
				'bawac_force_nonce',
365
				'icl_post_language',
366
				'saved_values',
367
				'mlcf_email',
368
				'mlcf_name',
369
				'cron_failed',
370
				'undefined',
371
				'cf_email',
372
				'cf_message',
373
				'cf_name',
374
				'cf_number',
375
				'cf_phone',
376
				'cf_subject',
377
				'content',
378
				'credentials',
379
				'cron_failed',
380
				'cron_last_run',
381
				'global-css',
382
				'grids',
383
				'page',
384
				'punch-fonts',
385
				'return_tab',
386
				'skins',
387
				'navigation-skins',
388
				'title',
389
				'type',
390
				'wpcf_email',
391
				'wpcf_your_name',
392
			);
393
394
			foreach ( $settings as $setting ) {
395
				if ( ! empty( $this->new_settings[ $setting ] ) ) {
396
					unset( $this->new_settings[ $setting ] );
397
				}
398
			}
399
400
		// 4. Remove old crons
401
			if ( wp_next_scheduled( 'monsterinsights_daily_cron' ) ) {
402
				wp_clear_scheduled_hook( 'monsterinsights_daily_cron' );
403
			}
404
			if ( wp_next_scheduled( 'monsterinsights_send_tracking_data' ) ) {
405
				wp_clear_scheduled_hook( 'monsterinsights_send_tracking_data' );
406
			}
407
408
			if ( wp_next_scheduled( 'monsterinsights_send_tracking_checkin' ) ) {
409
				wp_clear_scheduled_hook( 'monsterinsights_send_tracking_checkin' );
410
			}
411
412
			if ( wp_next_scheduled( 'monsterinsights_weekly_cron' ) ) {
413
				wp_clear_scheduled_hook( 'monsterinsights_weekly_cron' );
414
			}
415
416
			if ( wp_next_scheduled( 'yst_ga_aggregate_data' ) ) {
417
				wp_clear_scheduled_hook( 'yst_ga_aggregate_data' );
418
			}
419
420
			delete_option( 'monsterinsights_tracking_last_send' );
421
			delete_option( 'mi_tracking_last_send' );
422
423
		// 5. Remove old option
424
			delete_option( 'monsterinsights_settings_version' );
425
	}
426
427
428
	/**
429
	 * Upgrade routine
430
	 */
431
	public function v750_upgrades() {
432
		// 1. One time re-prompt for anonymous data (due to migration bug now fixed)
433
		// if ( ! monsterinsights_is_pro_version() ) {
434
		// 	if ( empty( $this->new_settings[ 'anonymous_data' ] ) ) {
435
		// 		update_option( 'monsterinsights_tracking_notice', 0 );
436
		// 	}
437
		// }
438
		//
439
		// 2. Clear old settings ( 	'tracking_mode','events_mode',)
440
	}
441
}
442