Passed
Push — master ( 59650c...0b7aa3 )
by Chris
11:04 queued 06:15
created

MonsterInsights_Rest_Routes   F

Complexity

Total Complexity 129

Size/Duplication

Total Lines 777
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 409
c 1
b 0
f 0
dl 0
loc 777
rs 2
wmc 129

16 Methods

Rating   Name   Duplication   Size   Complexity  
B handle_settings_import() 0 66 11
A get_profile() 0 15 2
F get_report_data() 0 88 29
F get_addons() 0 153 14
A get_notice_status() 0 12 3
A update_settings() 0 21 4
A hide_old_notices() 0 17 5
B install_plugin() 0 85 7
B handle_sanitization() 0 42 9
A dismiss_first_time_notice() 0 5 1
A dismiss_notice() 0 11 3
A get_addon() 0 24 5
A __construct() 0 18 1
A get_license() 0 26 3
C get_settings() 0 53 11
D update_manual_ua() 0 47 21

How to fix   Complexity   

Complex Class

Complex classes like MonsterInsights_Rest_Routes often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use MonsterInsights_Rest_Routes, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Routes for VUE are registered here.
4
 *
5
 * @package monsterinsights
6
 */
7
8
/**
9
 * Class MonsterInsights_Rest_Routes
10
 */
11
class MonsterInsights_Rest_Routes {
12
13
	/**
14
	 * MonsterInsights_Rest_Routes constructor.
15
	 */
16
	public function __construct() {
17
18
		add_action( 'wp_ajax_monsterinsights_vue_get_license', array( $this, 'get_license' ) );
19
		add_action( 'wp_ajax_monsterinsights_vue_get_profile', array( $this, 'get_profile' ) );
20
		add_action( 'wp_ajax_monsterinsights_vue_get_settings', array( $this, 'get_settings' ) );
21
		add_action( 'wp_ajax_monsterinsights_vue_update_settings', array( $this, 'update_settings' ) );
22
		add_action( 'wp_ajax_monsterinsights_vue_get_addons', array( $this, 'get_addons' ) );
23
		add_action( 'wp_ajax_monsterinsights_update_manual_ua', array( $this, 'update_manual_ua' ) );
24
		add_action( 'wp_ajax_monsterinsights_vue_get_report_data', array( $this, 'get_report_data' ) );
25
		add_action( 'wp_ajax_monsterinsights_vue_install_plugin', array( $this, 'install_plugin' ) );
26
		add_action( 'wp_ajax_monsterinsights_vue_notice_status', array( $this, 'get_notice_status' ) );
27
		add_action( 'wp_ajax_monsterinsights_vue_notice_dismiss', array( $this, 'dismiss_notice' ) );
28
29
		add_action( 'wp_ajax_monsterinsights_handle_settings_import', array( $this, 'handle_settings_import' ) );
30
31
		add_action( 'admin_notices', array( $this, 'hide_old_notices' ), 0 );
32
33
		add_action( 'wp_ajax_monsterinsights_vue_dismiss_first_time_notice', array( $this, 'dismiss_first_time_notice' ) );
34
	}
35
36
	/**
37
	 * Ajax handler for grabbing the license
38
	 */
39
	public function get_license() {
40
41
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
42
43
		if ( ! current_user_can( 'monsterinsights_view_dashboard' ) || ! monsterinsights_is_pro_version() ) {
44
			return;
45
		}
46
47
		$site_license    = array(
48
			'key'         => MonsterInsights()->license->get_site_license_key(),
49
			'type'        => MonsterInsights()->license->get_site_license_type(),
50
			'is_disabled' => MonsterInsights()->license->site_license_disabled(),
51
			'is_expired'  => MonsterInsights()->license->site_license_expired(),
52
			'is_invalid'  => MonsterInsights()->license->site_license_invalid(),
53
		);
54
		$network_license = array(
55
			'key'         => MonsterInsights()->license->get_network_license_key(),
56
			'type'        => MonsterInsights()->license->get_network_license_type(),
57
			'is_disabled' => MonsterInsights()->license->network_license_disabled(),
58
			'is_expired'  => MonsterInsights()->license->network_license_expired(),
59
			'is_invalid'  => MonsterInsights()->license->network_license_disabled(),
60
		);
61
62
		wp_send_json( array(
63
			'site'    => $site_license,
64
			'network' => $network_license,
65
		) );
66
67
	}
68
69
	/**
70
	 * Ajax handler for grabbing the current authenticated profile.
71
	 */
72
	public function get_profile() {
73
74
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
75
76
		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
77
			return;
78
		}
79
80
		wp_send_json( array(
81
			'ua'                => MonsterInsights()->auth->get_ua(),
82
			'viewname'          => MonsterInsights()->auth->get_viewname(),
83
			'manual_ua'         => MonsterInsights()->auth->get_manual_ua(),
84
			'network_ua'        => MonsterInsights()->auth->get_network_ua(),
85
			'network_viewname'  => MonsterInsights()->auth->get_network_viewname(),
86
			'network_manual_ua' => MonsterInsights()->auth->get_network_manual_ua(),
87
		) );
88
89
	}
90
91
	/**
92
	 * Ajax handler for grabbing the settings.
93
	 */
94
	public function get_settings() {
95
96
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
97
98
		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
99
			return;
100
		}
101
102
		$options = monsterinsights_get_options();
103
104
		// Array fields are needed even if empty.
105
		$array_fields = array( 'view_reports', 'save_settings', 'ignore_users' );
106
		foreach ( $array_fields as $array_field ) {
107
			if ( ! isset( $options[ $array_field ] ) ) {
108
				$options[ $array_field ] = array();
109
			}
110
		}
111
		if ( isset( $options['custom_code'] ) ) {
112
			$options['custom_code'] = stripslashes( $options['custom_code'] );
113
		}
114
115
		//add email summaries options
116
		if ( monsterinsights_is_pro_version() ) {
117
			$default_email = array(
118
				'email' => get_option( 'admin_email' ),
119
			);
120
121
			if ( ! isset( $options['email_summaries'] ) ) {
122
				$options['email_summaries'] = 'on';
123
			}
124
125
			if ( ! isset( $options['summaries_email_addresses'] ) ) {
126
				$options['summaries_email_addresses'] = array(
127
					$default_email,
128
				);
129
			}
130
131
			if ( ! isset( $options['summaries_html_template'] ) ) {
132
				$options['summaries_html_template'] = 'yes';
133
			}
134
135
136
			if ( ! isset( $options['summaries_carbon_copy'] ) ) {
137
				$options['summaries_carbon_copy'] = 'no';
138
			}
139
140
141
			if ( ! isset( $options['summaries_header_image'] ) ) {
142
				$options['summaries_header_image'] = '';
143
			}
144
		}
145
146
		wp_send_json( $options );
147
148
	}
149
150
	/**
151
	 * Ajax handler for updating the settings.
152
	 */
153
	public function update_settings() {
154
155
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
156
157
		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
158
			return;
159
		}
160
161
		if ( isset( $_POST['setting'] ) ) {
162
			$setting = sanitize_text_field( wp_unslash( $_POST['setting'] ) );
163
			if ( isset( $_POST['value'] ) ) {
164
				$value = $this->handle_sanitization( $setting, $_POST['value'] );
165
				monsterinsights_update_option( $setting, $value );
166
				do_action( 'monsterinsights_after_update_settings', $setting, $value );
167
			} else {
168
				monsterinsights_update_option( $setting, false );
169
				do_action( 'monsterinsights_after_update_settings', $setting, false );
170
			}
171
		}
172
173
		wp_send_json_success();
174
175
	}
176
177
	/**
178
	 * Sanitization specific to each field.
179
	 *
180
	 * @param string $field The key of the field to sanitize.
181
	 * @param string $value The value of the field to sanitize.
182
	 *
183
	 * @return mixed The sanitized input.
184
	 */
185
	private function handle_sanitization( $field, $value ) {
186
187
		$value = wp_unslash( $value );
188
189
		// Textarea fields.
190
		$textarea_fields = array(
191
			'custom_code',
192
		);
193
194
		if ( in_array( $field, $textarea_fields, true ) ) {
195
			if ( function_exists( 'sanitize_textarea_field' ) ) {
196
				return sanitize_textarea_field( $value );
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type string[]; however, parameter $str of sanitize_textarea_field() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

196
				return sanitize_textarea_field( /** @scrutinizer ignore-type */ $value );
Loading history...
197
			} else {
198
				return wp_kses( $value, array() );
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type string[]; however, parameter $string of wp_kses() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

198
				return wp_kses( /** @scrutinizer ignore-type */ $value, array() );
Loading history...
199
			}
200
		}
201
202
		$array_value = json_decode( $value, true );
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type string[]; however, parameter $json of json_decode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

202
		$array_value = json_decode( /** @scrutinizer ignore-type */ $value, true );
Loading history...
203
		if ( is_array( $array_value ) ) {
204
			$value = $array_value;
205
			// Don't save empty values.
206
			foreach ( $value as $key => $item ) {
207
				if ( is_array( $item ) ) {
208
					$empty = true;
209
					foreach ( $item as $item_value ) {
210
						if ( ! empty( $item_value ) ) {
211
							$empty = false;
212
						}
213
					}
214
					if ( $empty ) {
215
						unset( $value[ $key ] );
216
					}
217
				}
218
			}
219
220
			// Reset array keys because JavaScript can't handle arrays with non-sequential keys.
221
			$value = array_values( $value );
222
223
			return $value;
224
		}
225
226
		return sanitize_text_field( $value );
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type string[]; however, parameter $str of sanitize_text_field() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

226
		return sanitize_text_field( /** @scrutinizer ignore-type */ $value );
Loading history...
227
228
	}
229
230
	/**
231
	 * Return the state of the addons ( installed, activated )
232
	 */
233
	public function get_addons() {
234
235
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
236
237
		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
238
			return;
239
		}
240
241
		if ( isset( $_POST['network'] ) && intval( $_POST['network'] ) > 0 ) {
242
			define( 'WP_NETWORK_ADMIN', true );
243
		}
244
245
		$addons_data       = monsterinsights_get_addons();
246
		$parsed_addons     = array();
247
		$installed_plugins = get_plugins();
248
249
		if ( ! is_array( $addons_data ) ) {
250
			$addons_data = array();
251
		}
252
253
		foreach ( $addons_data as $addons_type => $addons ) {
254
			foreach ( $addons as $addon ) {
255
				$slug = 'monsterinsights-' . $addon->slug;
256
				if ( 'monsterinsights-ecommerce' === $slug ) {
257
					$addon = $this->get_addon( $installed_plugins, $addons_type, $addon, $slug );
258
					if ( empty( $addon->installed ) ) {
259
						$slug  = 'ga-ecommerce';
260
						$addon = $this->get_addon( $installed_plugins, $addons_type, $addon, $slug );
261
					}
262
				} else {
263
					$addon = $this->get_addon( $installed_plugins, $addons_type, $addon, $slug );
264
				}
265
				$parsed_addons[ $addon->slug ] = $addon;
266
			}
267
		}
268
269
		// Include data about the plugins needed by some addons ( WooCommerce, EDD, Google AMP, CookieBot, etc ).
270
		// WooCommerce.
271
		$parsed_addons['woocommerce'] = array(
272
			'active' => class_exists( 'WooCommerce' ),
273
		);
274
		// Edd.
275
		$parsed_addons['easy_digital_downloads'] = array(
276
			'active' => class_exists( 'Easy_Digital_Downloads' ),
277
		);
278
		// MemberPress.
279
		$parsed_addons['memberpress'] = array(
280
			'active' => defined( 'MEPR_VERSION' ) && version_compare( MEPR_VERSION, '1.3.43', '>' ),
0 ignored issues
show
Bug introduced by
The constant MEPR_VERSION was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
281
		);
282
		// LifterLMS.
283
		$parsed_addons['lifterlms'] = array(
284
			'active' => function_exists( 'LLMS' ) && version_compare( LLMS()->version, '3.32.0', '>=' ),
285
		);
286
		// Cookiebot.
287
		$parsed_addons['cookiebot'] = array(
288
			'active' => function_exists( 'cookiebot_active' ) && cookiebot_active(),
289
		);
290
		// Cookie Notice.
291
		$parsed_addons['cookie_notice'] = array(
292
			'active' => class_exists( 'Cookie_Notice' ),
293
		);
294
		// Fb Instant Articles.
295
		$parsed_addons['instant_articles'] = array(
296
			'active' => defined( 'IA_PLUGIN_VERSION' ) && version_compare( IA_PLUGIN_VERSION, '3.3.4', '>' ),
0 ignored issues
show
Bug introduced by
The constant IA_PLUGIN_VERSION was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
297
		);
298
		// Google AMP.
299
		$parsed_addons['google_amp'] = array(
300
			'active' => defined( 'AMP__FILE__' ),
301
		);
302
		// WPForms.
303
		$parsed_addons['wpforms-lite'] = array(
304
			'active'    => function_exists( 'wpforms' ),
305
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugin-wpforms.png',
306
			'title'     => 'WPForms',
307
			'excerpt'   => __( 'The most beginner friendly drag & drop WordPress forms plugin allowing you to create beautiful contact forms, subscription forms, payment forms, and more in minutes, not hours!', 'google-analytics-for-wordpress' ),
308
			'installed' => array_key_exists( 'wpforms-lite/wpforms.php', $installed_plugins ),
309
			'basename'  => 'wpforms-lite/wpforms.php',
310
			'slug'      => 'wpforms-lite',
311
		);
312
		// OptinMonster.
313
		$parsed_addons['optinmonster'] = array(
314
			'active'    => class_exists( 'OMAPI' ),
315
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugin-om.png',
316
			'title'     => 'OptinMonster',
317
			'excerpt'   => __( 'Our high-converting optin forms like Exit-Intent® popups, Fullscreen Welcome Mats, and Scroll boxes help you dramatically boost conversions and get more email subscribers.', 'google-analytics-for-wordpress' ),
318
			'installed' => array_key_exists( 'optinmonster/optin-monster-wp-api.php', $installed_plugins ),
319
			'basename'  => 'optinmonster/optin-monster-wp-api.php',
320
			'slug'      => 'optinmonster',
321
		);
322
		// WP Mail Smtp.
323
		$parsed_addons['wp-mail-smtp'] = array(
324
			'active'    => function_exists( 'wp_mail_smtp' ),
325
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugin-smtp.png',
326
			'title'     => 'WP Mail SMTP',
327
			'excerpt'   => __( 'SMTP (Simple Mail Transfer Protocol) is an industry standard for sending emails. SMTP helps increase email deliverability by using proper authentication.', 'google-analytics-for-wordpress' ),
328
			'installed' => array_key_exists( 'wp-mail-smtp/wp_mail_smtp.php', $installed_plugins ),
329
			'basename'  => 'wp-mail-smtp/wp_mail_smtp.php',
330
			'slug'      => 'wp-mail-smtp',
331
		);
332
		// Pretty Links
333
		$parsed_addons['pretty-link'] = array(
334
			'active'    => class_exists( 'PrliBaseController' ),
335
			'icon'      => '',
336
			'title'     => 'Pretty Links',
337
			'excerpt'   => __( 'Pretty Links helps you shrink, beautify, track, manage and share any URL on or off of your WordPress website. Create links that look how you want using your own domain name!', 'google-analytics-for-wordpress' ),
338
			'installed' => array_key_exists( 'pretty-link/pretty-link.php', $installed_plugins ),
339
			'basename'  => 'pretty-link/pretty-link.php',
340
			'slug'      => 'pretty-link',
341
		);
342
		// SeedProd.
343
		$parsed_addons['coming-soon'] = array(
344
			'active'    => function_exists( 'seed_csp4_activation' ),
345
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/seedprod.png',
346
			'title'     => 'SeedProd',
347
			'excerpt'   => __( 'Better Coming Soon & Maintenance Mode Pages', 'google-analytics-for-wordpress' ),
348
			'installed' => array_key_exists( 'coming-soon/coming-soon.php', $installed_plugins ),
349
			'basename'  => 'coming-soon/coming-soon.php',
350
			'slug'      => 'coming-soon',
351
		);
352
		$parsed_addons['rafflepress'] = array(
353
			'active'    => function_exists( 'rafflepress_lite_activation' ),
354
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/rafflepress.png',
355
			'title'     => 'RafflePress',
356
			'excerpt'   => __( 'Get More Traffic with Viral Giveaways', 'google-analytics-for-wordpress' ),
357
			'installed' => array_key_exists( 'rafflepress/rafflepress.php', $installed_plugins ),
358
			'basename'  => 'rafflepress/rafflepress.php',
359
			'slug'      => 'rafflepress',
360
		);
361
		$parsed_addons['trustpulse-api'] = array(
362
			'active'    => class_exists( 'TPAPI' ),
363
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/trustpulse.png',
364
			'title'     => 'TrustPulse',
365
			'excerpt'   => __( 'Social Proof Notifications that Boost Sales', 'google-analytics-for-wordpress' ),
366
			'installed' => array_key_exists( 'trustpulse-api/trustpulse.php', $installed_plugins ),
367
			'basename'  => 'trustpulse-api/trustpulse.php',
368
			'slug'      => 'trustpulse-api',
369
		);
370
		// Gravity Forms.
371
		$parsed_addons['gravity_forms'] = array(
372
			'active' => class_exists( 'GFCommon' ),
373
		);
374
		// Formidable Forms.
375
		$parsed_addons['formidable_forms'] = array(
376
			'active' => class_exists( 'FrmHooksController' ),
377
		);
378
		// Manual UA Addon.
379
		if ( ! isset( $parsed_addons['manual_ua'] ) ) {
380
			$parsed_addons['manual_ua'] = array(
381
				'active' => class_exists( 'MonsterInsights_Manual_UA' ),
382
			);
383
		}
384
385
		wp_send_json( $parsed_addons );
386
	}
387
388
	public function get_addon( $installed_plugins, $addons_type, $addon, $slug ) {
389
		$active          = false;
390
		$installed       = false;
391
		$plugin_basename = monsterinsights_get_plugin_basename_from_slug( $slug );
392
393
		if ( isset( $installed_plugins[ $plugin_basename ] ) ) {
394
			$installed = true;
395
396
			if ( is_multisite() && is_network_admin() ) {
397
				$active = is_plugin_active_for_network( $plugin_basename );
398
			} else {
399
				$active = is_plugin_active( $plugin_basename );
400
			}
401
		}
402
		if ( empty( $addon->url ) ) {
403
			$addon->url = '';
404
		}
405
406
		$addon->type      = $addons_type;
407
		$addon->installed = $installed;
408
		$addon->active    = $active;
409
		$addon->basename  = $plugin_basename;
410
411
		return $addon;
412
	}
413
414
	/**
415
	 * Use custom notices in the Vue app on the Settings screen.
416
	 */
417
	public function hide_old_notices() {
418
419
		global $wp_version;
420
		if ( version_compare( $wp_version, '4.6', '<' ) ) {
421
			// remove_all_actions triggers an infinite loop on older versions.
422
			return;
423
		}
424
425
		$screen = get_current_screen();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $screen is correct as get_current_screen() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
426
		// Bail if we're not on a MonsterInsights screen.
427
		if ( empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) === false ) {
428
			return;
429
		}
430
431
		// Hide admin notices on the settings screen.
432
		if ( monsterinsights_is_settings_page() ) {
433
			remove_all_actions( 'admin_notices' );
434
		}
435
436
	}
437
438
	/**
439
	 * Update manual ua.
440
	 */
441
	public function update_manual_ua() {
442
443
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
444
445
		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
446
			return;
447
		}
448
449
		$manual_ua_code = isset( $_POST['manual_ua_code'] ) ? sanitize_text_field( wp_unslash( $_POST['manual_ua_code'] ) ) : '';
450
		$manual_ua_code = monsterinsights_is_valid_ua( $manual_ua_code ); // Also sanitizes the string.
451
		if ( ! empty( $_REQUEST['isnetwork'] ) && sanitize_text_field( wp_unslash( $_REQUEST['isnetwork'] ) ) ) {
452
			define( 'WP_NETWORK_ADMIN', true );
453
		}
454
		$manual_ua_code_old = is_network_admin() ? MonsterInsights()->auth->get_network_manual_ua() : MonsterInsights()->auth->get_manual_ua();
455
456
		if ( $manual_ua_code && $manual_ua_code_old && $manual_ua_code_old === $manual_ua_code ) {
457
			// Same code we had before
458
			// Do nothing.
459
			wp_send_json_success();
460
		} else if ( $manual_ua_code && $manual_ua_code_old && $manual_ua_code_old !== $manual_ua_code ) {
461
			// Different UA code.
462
			if ( is_network_admin() ) {
463
				MonsterInsights()->auth->set_network_manual_ua( $manual_ua_code );
464
			} else {
465
				MonsterInsights()->auth->set_manual_ua( $manual_ua_code );
466
			}
467
		} else if ( $manual_ua_code && empty( $manual_ua_code_old ) ) {
468
			// Move to manual.
469
			if ( is_network_admin() ) {
470
				MonsterInsights()->auth->set_network_manual_ua( $manual_ua_code );
471
			} else {
472
				MonsterInsights()->auth->set_manual_ua( $manual_ua_code );
473
			}
474
		} else if ( empty( $manual_ua_code ) && $manual_ua_code_old ) {
475
			// Deleted manual.
476
			if ( is_network_admin() ) {
477
				MonsterInsights()->auth->delete_network_manual_ua();
478
			} else {
479
				MonsterInsights()->auth->delete_manual_ua();
480
			}
481
		} else if ( isset( $_POST['manual_ua_code'] ) && empty( $manual_ua_code ) ) {
482
			wp_send_json_error( array(
483
				'error' => __( 'Invalid UA code', 'google-analytics-for-wordpress' ),
484
			) );
485
		}
486
487
		wp_send_json_success();
488
	}
489
490
	/**
491
	 *
492
	 */
493
	public function handle_settings_import() {
494
495
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
496
497
		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
498
			return;
499
		}
500
501
		if ( ! isset( $_FILES['import_file'] ) ) {
502
			return;
503
		}
504
505
		$extension = explode( '.', sanitize_text_field( wp_unslash( $_FILES['import_file']['name'] ) ) );
506
		$extension = end( $extension );
507
508
		if ( 'json' !== $extension ) {
509
			wp_send_json_error( array(
510
				'message' => esc_html__( 'Please upload a valid .json file', 'google-analytics-for-wordpress' ),
511
			) );
512
		}
513
514
		$import_file = sanitize_text_field( wp_unslash( $_FILES['import_file']['tmp_name'] ) );
515
516
		$file = file_get_contents( $import_file );
517
		if ( empty( $file ) ) {
518
			wp_send_json_error( array(
519
				'message' => esc_html__( 'Please upload a file to import', 'google-analytics-for-wordpress' ),
520
			) );
521
		}
522
523
		// Retrieve the settings from the file and convert the json object to an array.
524
		$new_settings = json_decode( wp_json_encode( json_decode( $file ) ), true );
525
		$settings     = monsterinsights_get_options();
526
		$exclude      = array(
527
			'analytics_profile',
528
			'analytics_profile_code',
529
			'analytics_profile_name',
530
			'oauth_version',
531
			'cron_last_run',
532
			'monsterinsights_oauth_status',
533
		);
534
535
		foreach ( $exclude as $e ) {
536
			if ( ! empty( $new_settings[ $e ] ) ) {
537
				unset( $new_settings[ $e ] );
538
			}
539
		}
540
541
		if ( ! is_super_admin() ) {
542
			if ( ! empty( $new_settings['custom_code'] ) ) {
543
				unset( $new_settings['custom_code'] );
544
			}
545
		}
546
547
		foreach ( $exclude as $e ) {
548
			if ( ! empty( $settings[ $e ] ) ) {
549
				$new_settings = $settings[ $e ];
550
			}
551
		}
552
553
		global $monsterinsights_settings;
554
		$monsterinsights_settings = $new_settings;
555
556
		update_option( monsterinsights_get_option_name(), $new_settings );
557
558
		wp_send_json_success( $new_settings );
559
560
	}
561
562
	/**
563
	 * Generic Ajax handler for grabbing report data in JSON.
564
	 */
565
	public function get_report_data() {
566
567
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
568
569
		if ( ! current_user_can( 'monsterinsights_view_dashboard' ) ) {
570
			wp_send_json_error( array( 'message' => __( "You don't have permission to view MonsterInsights reports.", 'google-analytics-for-wordpress' ) ) );
571
		}
572
573
		if ( ! empty( $_REQUEST['isnetwork'] ) && $_REQUEST['isnetwork'] ) {
574
			define( 'WP_NETWORK_ADMIN', true );
575
		}
576
		$settings_page = admin_url( 'admin.php?page=monsterinsights_settings' );
577
578
		// Only for Pro users, require a license key to be entered first so we can link to things.
579
		if ( monsterinsights_is_pro_version() ) {
580
			if ( ! MonsterInsights()->license->is_site_licensed() && ! MonsterInsights()->license->is_network_licensed() ) {
581
				wp_send_json_error( array(
582
					'message' => __( "You can't view MonsterInsights reports because you are not licensed.", 'google-analytics-for-wordpress' ),
583
					'footer'  => '<a href="' . $settings_page . '">' . __( 'Add your license', 'google-analytics-for-wordpress' ) . '</a>',
584
				) );
585
			} else if ( MonsterInsights()->license->is_site_licensed() && ! MonsterInsights()->license->site_license_has_error() ) {
586
				// Good to go: site licensed.
587
			} else if ( MonsterInsights()->license->is_network_licensed() && ! MonsterInsights()->license->network_license_has_error() ) {
588
				// Good to go: network licensed.
589
			} else {
590
				wp_send_json_error( array( 'message' => __( "You can't view MonsterInsights reports due to license key errors.", 'google-analytics-for-wordpress' ) ) );
591
			}
592
		}
593
594
		// We do not have a current auth.
595
		$site_auth = MonsterInsights()->auth->get_viewname();
596
		$ms_auth   = is_multisite() && MonsterInsights()->auth->get_network_viewname();
597
		if ( ! $site_auth && ! $ms_auth ) {
598
			wp_send_json_error( array( 'message' => __( 'You must authenticate with MonsterInsights before you can view reports.', 'google-analytics-for-wordpress' ) ) );
599
		}
600
601
		$report_name = isset( $_POST['report'] ) ? sanitize_text_field( wp_unslash( $_POST['report'] ) ) : '';
602
603
		if ( empty( $report_name ) ) {
604
			wp_send_json_error( array( 'message' => __( 'Unknown report. Try refreshing and retrying. Contact support if this issue persists.', 'google-analytics-for-wordpress' ) ) );
605
		}
606
607
		$report = MonsterInsights()->reporting->get_report( $report_name );
608
609
		$isnetwork = ! empty( $_REQUEST['isnetwork'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['isnetwork'] ) ) : '';
610
		$start     = ! empty( $_POST['start'] ) ? sanitize_text_field( wp_unslash( $_POST['start'] ) ) : $report->default_start_date();
611
		$end       = ! empty( $_POST['end'] ) ? sanitize_text_field( wp_unslash( $_POST['end'] ) ) : $report->default_end_date();
612
613
		$args      = array(
614
			'start' => $start,
615
			'end'   => $end,
616
		);
617
618
		if ( $isnetwork ) {
619
			$args['network'] = true;
620
		}
621
622
		if ( monsterinsights_is_pro_version() && ! MonsterInsights()->license->license_can( $report->level ) ) {
623
			$data = array(
624
				'success' => false,
625
				'error'   => 'license_level',
626
			);
627
		} else {
628
			$data = apply_filters( 'monsterinsights_vue_reports_data', $report->get_data( $args ), $report_name, $report );
629
		}
630
631
		if ( ! empty( $data['success'] ) && ! empty( $data['data'] ) ) {
632
			wp_send_json_success( $data['data'] );
633
		} else if ( isset( $data['success'] ) && false === $data['success'] && ! empty( $data['error'] ) ) {
634
			// Use a custom handler for invalid_grant errors.
635
			if ( strpos( $data['error'], 'invalid_grant' ) > 0 ) {
636
				wp_send_json_error(
637
					array(
638
						'message' => 'invalid_grant',
639
						'footer'  => '',
640
					)
641
				);
642
			}
643
644
			wp_send_json_error(
645
				array(
646
					'message' => $data['error'],
647
					'footer'  => isset( $data['data']['footer'] ) ? $data['data']['footer'] : '',
648
				)
649
			);
650
		}
651
652
		wp_send_json_error( array( 'message' => __( 'We encountered an error when fetching the report data.', 'google-analytics-for-wordpress' ) ) );
653
654
	}
655
656
	/**
657
	 * Install plugins which are not addons.
658
	 */
659
	public function install_plugin() {
660
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
661
662
		if ( ! current_user_can( 'install_plugins' ) ) {
663
			wp_send_json( array(
664
				'message' => esc_html__( 'You are not allowed to install plugins', 'ga-premium' ),
665
			) );
666
		}
667
668
		$slug = isset( $_POST['slug'] ) ? sanitize_text_field( wp_unslash( $_POST['slug'] ) ) : false;
669
670
		if ( ! $slug ) {
671
			wp_send_json( array(
672
				'message' => esc_html__( 'Missing plugin name.', 'ga-premium' ),
673
			) );
674
		}
675
676
		include_once ABSPATH . 'wp-admin/includes/plugin-install.php';
677
678
		$api = plugins_api( 'plugin_information', array(
679
			'slug'   => $slug,
680
			'fields' => array(
681
				'short_description' => false,
682
				'sections'          => false,
683
				'requires'          => false,
684
				'rating'            => false,
685
				'ratings'           => false,
686
				'downloaded'        => false,
687
				'last_updated'      => false,
688
				'added'             => false,
689
				'tags'              => false,
690
				'compatibility'     => false,
691
				'homepage'          => false,
692
				'donate_link'       => false,
693
			),
694
		) );
695
696
		if ( is_wp_error( $api ) ) {
697
			return $api->get_error_message();
698
		}
699
700
		$download_url = $api->download_link;
701
702
		$method = '';
703
		$url    = add_query_arg(
704
			array(
705
				'page' => 'monsterinsights-settings',
706
			),
707
			admin_url( 'admin.php' )
708
		);
709
		$url    = esc_url( $url );
710
711
		ob_start();
712
		if ( false === ( $creds = request_filesystem_credentials( $url, $method, false, false, null ) ) ) {
713
			$form = ob_get_clean();
714
715
			wp_send_json( array( 'form' => $form ) );
716
		}
717
718
		// If we are not authenticated, make it happen now.
719
		if ( ! WP_Filesystem( $creds ) ) {
720
			ob_start();
721
			request_filesystem_credentials( $url, $method, true, false, null );
722
			$form = ob_get_clean();
723
724
			wp_send_json( array( 'form' => $form ) );
725
726
		}
727
728
		// We do not need any extra credentials if we have gotten this far, so let's install the plugin.
729
		$base = MonsterInsights();
730
		require_once plugin_dir_path( $base->file ) . '/includes/admin/licensing/plugin-upgrader.php';
731
		require_once plugin_dir_path( $base->file ) . '/includes/admin/licensing/skin.php';
732
733
		// Prevent language upgrade in ajax calls.
734
		remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
735
		// Create the plugin upgrader with our custom skin.
736
		$installer = new MonsterInsights_Plugin_Upgrader( new MonsterInsights_Skin() );
737
		$installer->install( $download_url );
738
739
		// Flush the cache and return the newly installed plugin basename.
740
		wp_cache_flush();
741
		wp_send_json_success();
742
743
		wp_die();
744
	}
745
746
	/**
747
	 * Store that the first run notice has been dismissed so it doesn't show up again.
748
	 */
749
	public function dismiss_first_time_notice() {
750
751
		monsterinsights_update_option( 'monsterinsights_first_run_notice', true );
0 ignored issues
show
Bug introduced by
true of type true is incompatible with the type string expected by parameter $value of monsterinsights_update_option(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

751
		monsterinsights_update_option( 'monsterinsights_first_run_notice', /** @scrutinizer ignore-type */ true );
Loading history...
752
753
		wp_send_json_success();
754
	}
755
756
	/**
757
	 * Get the notice status by id.
758
	 */
759
	public function get_notice_status() {
760
761
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
762
763
		$notice_id = empty( $_POST['notice'] ) ? false : sanitize_text_field( wp_unslash( $_POST['notice'] ) );
764
		if ( ! $notice_id ) {
765
			wp_send_json_error();
766
		}
767
		$is_dismissed = MonsterInsights()->notices->is_dismissed( $notice_id );
768
769
		wp_send_json_success( array(
770
			'dismissed' => $is_dismissed,
771
		) );
772
	}
773
774
	/**
775
	 * Dismiss notices by id.
776
	 */
777
	public function dismiss_notice() {
778
779
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
780
781
		$notice_id = empty( $_POST['notice'] ) ? false : sanitize_text_field( wp_unslash( $_POST['notice'] ) );
782
		if ( ! $notice_id ) {
783
			wp_send_json_error();
784
		}
785
		MonsterInsights()->notices->dismiss( $notice_id );
786
787
		wp_send_json_success();
788
	}
789
}
790