MonsterInsights_Rest_Routes::get_license()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 30
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 3
eloc 22
c 2
b 0
f 0
nc 2
nop 0
dl 0
loc 30
rs 9.568
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_update_settings_bulk', array( $this, 'update_settings_bulk' ) );
23
		add_action( 'wp_ajax_monsterinsights_vue_get_addons', array( $this, 'get_addons' ) );
24
		add_action( 'wp_ajax_monsterinsights_update_manual_v4', array( $this, 'update_manual_v4' ) );
25
		add_action( 'wp_ajax_monsterinsights_update_measurement_protocol_secret', array(
26
			$this,
27
			'update_measurement_protocol_secret'
28
		) );
29
		add_action( 'wp_ajax_monsterinsights_vue_get_report_data', array( $this, 'get_report_data' ) );
30
		add_action( 'wp_ajax_monsterinsights_vue_install_plugin', array( $this, 'install_plugin' ) );
31
		add_action( 'wp_ajax_monsterinsights_vue_notice_status', array( $this, 'get_notice_status' ) );
32
		add_action( 'wp_ajax_monsterinsights_vue_notice_dismiss', array( $this, 'dismiss_notice' ) );
33
		add_action( 'wp_ajax_monsterinsights_vue_grab_popular_posts_report', array(
34
			$this,
35
			'check_popular_posts_report'
36
		) );
37
		add_action( 'wp_ajax_monsterinsights_vue_popular_posts_update_theme_setting', array(
38
			$this,
39
			'update_popular_posts_theme_setting'
40
		) );
41
42
		add_action( 'wp_ajax_monsterinsights_get_posts', array( $this, 'get_posts' ) );
43
44
		// Search for taxonomies.
45
		add_action( 'wp_ajax_monsterinsights_get_terms', array( $this, 'get_taxonomy_terms' ) );
46
47
		add_action( 'wp_ajax_monsterinsights_get_post_types', array( $this, 'get_post_types' ) );
48
49
		add_action( 'wp_ajax_monsterinsights_handle_settings_import', array( $this, 'handle_settings_import' ) );
50
51
		add_action( 'admin_notices', array( $this, 'hide_old_notices' ), 0 );
52
53
		add_action( 'wp_ajax_monsterinsights_vue_dismiss_first_time_notice', array(
54
			$this,
55
			'dismiss_first_time_notice'
56
		) );
57
	}
58
59
	/**
60
	 * Ajax handler for grabbing the license
61
	 */
62
	public function get_license() {
63
64
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
65
66
		if ( ! current_user_can( 'monsterinsights_view_dashboard' ) || ! monsterinsights_is_pro_version() ) {
67
			return;
68
		}
69
70
		$site_license    = array(
71
			'key'         => MonsterInsights()->license->get_site_license_key(),
72
			'type'        => MonsterInsights()->license->get_site_license_type(),
73
			'is_disabled' => MonsterInsights()->license->site_license_disabled(),
74
			'is_expired'  => MonsterInsights()->license->site_license_expired(),
75
			'expiry_date' => MonsterInsights()->license->get_license_expiry_date(),
76
			'is_invalid'  => MonsterInsights()->license->site_license_invalid(),
77
			'is_agency'   => MonsterInsights()->license->site_is_agency(),
78
		);
79
		$network_license = array(
80
			'key'         => MonsterInsights()->license->get_network_license_key(),
81
			'type'        => MonsterInsights()->license->get_network_license_type(),
82
			'is_disabled' => MonsterInsights()->license->network_license_disabled(),
83
			'is_expired'  => MonsterInsights()->license->network_license_expired(),
84
			'expiry_date' => MonsterInsights()->license->get_license_expiry_date(),
85
			'is_invalid'  => MonsterInsights()->license->network_license_disabled(),
86
			'is_agency'   => MonsterInsights()->license->network_is_agency(),
87
		);
88
89
		wp_send_json( array(
90
			'site'    => $site_license,
91
			'network' => $network_license,
92
		) );
93
94
	}
95
96
	/**
97
	 * Ajax handler for grabbing the current authenticated profile.
98
	 */
99
	public function get_profile() {
100
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
101
102
		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
103
			return;
104
		}
105
106
		$auth = MonsterInsights()->auth;
107
108
		wp_send_json( array(
109
			'v4'                                  => $auth->get_v4_id(),
110
			'viewname'                            => $auth->get_viewname(),
111
			'manual_v4'                           => $auth->get_manual_v4_id(),
112
			'measurement_protocol_secret'         => $auth->get_measurement_protocol_secret(),
113
			'network_v4'                          => $auth->get_network_v4_id(),
114
			'network_viewname'                    => $auth->get_network_viewname(),
115
			'network_manual_v4'                   => $auth->get_network_manual_v4_id(),
116
			'network_measurement_protocol_secret' => $auth->get_network_measurement_protocol_secret(),
117
		) );
118
119
	}
120
121
	/**
122
	 * Ajax handler for grabbing the settings.
123
	 */
124
	public function get_settings() {
125
126
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
127
128
		if ( ! current_user_can( 'monsterinsights_view_dashboard' ) ) {
129
			return;
130
		}
131
132
		$options = monsterinsights_get_options();
133
134
		// Array fields are needed even if empty.
135
		$array_fields = array( 'view_reports', 'save_settings', 'ignore_users' );
136
		foreach ( $array_fields as $array_field ) {
137
			if ( ! isset( $options[ $array_field ] ) ) {
138
				$options[ $array_field ] = array();
139
			}
140
		}
141
142
		//add email summaries options
143
		if ( monsterinsights_is_pro_version() ) {
144
			$default_email = array(
145
				'email' => get_option( 'admin_email' ),
146
			);
147
148
			if ( ! isset( $options['email_summaries'] ) ) {
149
				$options['email_summaries'] = 'on';
150
			}
151
152
			if ( ! isset( $options['summaries_email_addresses'] ) ) {
153
				$options['summaries_email_addresses'] = array(
154
					$default_email,
155
				);
156
			}
157
158
			if ( ! isset( $options['summaries_html_template'] ) ) {
159
				$options['summaries_html_template'] = 'yes';
160
			}
161
162
163
			if ( ! isset( $options['summaries_carbon_copy'] ) ) {
164
				$options['summaries_carbon_copy'] = 'no';
165
			}
166
167
168
			if ( ! isset( $options['summaries_header_image'] ) ) {
169
				$options['summaries_header_image'] = '';
170
			}
171
172
			if ( ! isset( $options['local_gtag_file_modified_at'] ) ) {
173
				$options['local_gtag_file_modified_at'] = '';
174
			}
175
		}
176
177
		wp_send_json( $options );
178
179
	}
180
181
	/**
182
	 * Ajax handler for updating the settings.
183
	 */
184
	public function update_settings() {
185
186
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
187
188
		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
189
			return;
190
		}
191
192
		if ( isset( $_POST['setting'] ) ) {
193
			$setting = sanitize_text_field( wp_unslash( $_POST['setting'] ) );
194
			if ( isset( $_POST['value'] ) ) {
195
				$value = $this->handle_sanitization( $setting, $_POST['value'] ); // phpcs:ignore
196
				monsterinsights_update_option( $setting, $value );
197
				do_action( 'monsterinsights_after_update_settings', $setting, $value );
198
			} else {
199
				monsterinsights_update_option( $setting, false );
200
				do_action( 'monsterinsights_after_update_settings', $setting, false );
201
			}
202
		}
203
204
		wp_send_json_success();
205
206
	}
207
208
	/**
209
	 * Ajax handler for updating the settings.
210
	 */
211
	public function update_settings_bulk() {
212
213
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
214
215
		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
216
			return;
217
		}
218
219
		if ( isset( $_POST['settings'] ) ) {
220
			$settings = json_decode( sanitize_text_field( wp_unslash( $_POST['settings'] ) ), true );
221
			foreach ( $settings as $setting => $value ) {
222
				$value = $this->handle_sanitization( $setting, $value );
223
				monsterinsights_update_option( $setting, $value );
224
				do_action( 'monsterinsights_after_update_settings', $setting, $value );
225
			}
226
		}
227
228
		wp_send_json_success();
229
230
	}
231
232
	/**
233
	 * Sanitization specific to each field.
234
	 *
235
	 * @param string $field The key of the field to sanitize.
236
	 * @param string $value The value of the field to sanitize.
237
	 *
238
	 * @return mixed The sanitized input.
239
	 */
240
	private function handle_sanitization( $field, $value ) {
241
242
		$value = wp_unslash( $value );
243
244
		// Textarea fields.
245
		$textarea_fields = array();
246
247
		if ( in_array( $field, $textarea_fields, true ) ) {
248
			if ( function_exists( 'sanitize_textarea_field' ) ) {
249
				return sanitize_textarea_field( $value );
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type array; 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

249
				return sanitize_textarea_field( /** @scrutinizer ignore-type */ $value );
Loading history...
250
			} else {
251
				return wp_kses( $value, array() );
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type array; however, parameter $content 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

251
				return wp_kses( /** @scrutinizer ignore-type */ $value, array() );
Loading history...
252
			}
253
		}
254
255
		$array_value = json_decode( $value, true );
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type array; 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

255
		$array_value = json_decode( /** @scrutinizer ignore-type */ $value, true );
Loading history...
256
		if ( is_array( $array_value ) ) {
257
			$value = $array_value;
258
			// Don't save empty values.
259
			foreach ( $value as $key => $item ) {
260
				if ( is_array( $item ) ) {
261
					$empty = true;
262
					foreach ( $item as $item_value ) {
263
						if ( ! empty( $item_value ) ) {
264
							$empty = false;
265
						}
266
					}
267
					if ( $empty ) {
268
						unset( $value[ $key ] );
269
					}
270
				}
271
			}
272
273
			// Reset array keys because JavaScript can't handle arrays with non-sequential keys.
274
			$value = array_values( $value );
275
276
			return $value;
277
		}
278
279
		return sanitize_text_field( $value );
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type array; 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

279
		return sanitize_text_field( /** @scrutinizer ignore-type */ $value );
Loading history...
280
281
	}
282
283
	/**
284
	 * Return the state of the addons ( installed, activated )
285
	 */
286
	public function get_addons() {
287
		global $current_user;
288
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
289
290
		if ( ! current_user_can( 'monsterinsights_view_dashboard' ) ) {
291
			return;
292
		}
293
294
		if ( isset( $_POST['network'] ) && intval( $_POST['network'] ) > 0 ) {
295
			define( 'WP_NETWORK_ADMIN', true );
296
		}
297
298
		$addons_data       = monsterinsights_get_addons();
299
		$parsed_addons     = array();
300
		$installed_plugins = get_plugins();
301
302
		if ( ! is_array( $addons_data ) ) {
303
			$addons_data = array();
304
		}
305
306
		foreach ( $addons_data as $addons_type => $addons ) {
307
			foreach ( $addons as $addon ) {
308
				$slug = 'monsterinsights-' . $addon->slug;
309
				if ( 'monsterinsights-ecommerce' === $slug && 'm' === $slug[0] ) {
310
					$addon = $this->get_addon( $installed_plugins, $addons_type, $addon, $slug );
311
					if ( empty( $addon->installed ) ) {
312
						$slug  = 'ga-ecommerce';
313
						$addon = $this->get_addon( $installed_plugins, $addons_type, $addon, $slug );
314
					}
315
				} else {
316
					$addon = $this->get_addon( $installed_plugins, $addons_type, $addon, $slug );
317
				}
318
				$parsed_addons[ $addon->slug ] = $addon;
319
			}
320
		}
321
322
		// Include data about the plugins needed by some addons ( WooCommerce, EDD, Google AMP, CookieBot, etc ).
323
		// WooCommerce.
324
		$parsed_addons['woocommerce'] = array(
325
			'active' => class_exists( 'WooCommerce' ),
326
		);
327
		// Edd.
328
		$parsed_addons['easy_digital_downloads'] = array(
329
			'active'    => class_exists( 'Easy_Digital_Downloads' ),
330
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugins/plugin-edd.png',
331
			'title'     => 'Easy Digital Downloads',
332
			'excerpt'   => __( 'The best WordPress eCommerce plugin for selling digital downloads. Start selling eBooks, software, music, digital art, and more within minutes. Accept payments, manage subscriptions, advanced access control, and more.', 'google-analytics-for-wordpress' ),
333
			'installed' => array_key_exists( 'easy-digital-downloads/easy-digital-downloads.php', $installed_plugins ) || array_key_exists( 'easy-digital-downloads-pro/easy-digital-downloads.php', $installed_plugins ),
334
			'basename'  => array_key_exists( 'easy-digital-downloads-pro/easy-digital-downloads.php', $installed_plugins ) ? 'easy-digital-downloads-pro/easy-digital-downloads.php' : 'easy-digital-downloads/easy-digital-downloads.php',
335
			'slug'      => 'easy-digital-downloads',
336
			'settings'  => admin_url( 'edit.php?post_type=download' ),
337
		);
338
		// Ajax activation works only if the key is the same with the slug. keeping the older one for backwards compatibility
339
		$parsed_addons['easy-digital-downloads'] = $parsed_addons['easy_digital_downloads'];
340
		// MemberPress.
341
		$parsed_addons['memberpress'] = array(
342
			'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...
343
		);
344
		// MemberMouse.
345
		$parsed_addons['membermouse'] = array(
346
			'active' => class_exists( 'MemberMouse' ),
347
		);
348
		// LifterLMS.
349
		$parsed_addons['lifterlms'] = array(
350
			'active' => function_exists( 'LLMS' ) && version_compare( LLMS()->version, '3.32.0', '>=' ),
351
		);
352
		// Restrict Content Pro.
353
		$parsed_addons['rcp'] = array(
354
			'active' => class_exists( 'Restrict_Content_Pro' ) && version_compare( RCP_PLUGIN_VERSION, '3.5.4', '>=' ),
0 ignored issues
show
Bug introduced by
The constant RCP_PLUGIN_VERSION was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
355
		);
356
		// GiveWP.
357
		$parsed_addons['givewp'] = array(
358
			'active' => function_exists( 'Give' ),
359
		);
360
361
		// Charitable WP.
362
		$parsed_addons['charitable'] = array(
363
			'active'    => class_exists( 'Charitable' ),
364
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugins/plugin-charitable.png',
365
			'title'     => 'Charitable',
366
			'excerpt'   => __('Top-rated WordPress donation and fundraising plugin. Over 10,000+ non-profit organizations and website owners use Charitable to create fundraising campaigns and raise more money online.', 'google-analytics-for-wordpress'),
367
			'installed' => array_key_exists('charitable/charitable.php', $installed_plugins),
368
			'basename'  => 'charitable/charitable.php',
369
			'slug'      => 'charitable',
370
			'settings'  => admin_url('admin.php?page=charitable'),
371
		);
372
373
		// WPCode
374
		$parsed_addons['wpcode'] = array(
375
			'active'    => function_exists( 'WPCode' ),
376
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugins/plugin-wpcode.png',
377
			'title'     => 'WPCode',
378
			'excerpt'   => __('Future proof your WordPress customizations with the most popular code snippet management plugin for WordPress. Trusted by over 1,500,000+ websites for easily adding code to WordPress right from the admin area.', 'google-analytics-for-wordpress'),
379
			'installed' => array_key_exists('insert-headers-and-footers/ihaf.php', $installed_plugins),
380
			'basename'  => 'insert-headers-and-footers/ihaf.php',
381
			'slug'      => 'insert-headers-and-footers',
382
			'settings'  => admin_url('admin.php?page=wpcode-settings'),
383
		);
384
385
		// Duplicator
386
		$parsed_addons['duplicator'] = array(
387
			'active'    => defined( 'DUPLICATOR_VERSION' ),
388
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugins/plugin-duplicator.png',
389
			'title'     => 'Duplicator',
390
			'excerpt'   => __('Leading WordPress backup & site migration plugin. Over 1,500,000+ smart website owners use Duplicator to make reliable and secure WordPress backups to protect their websites. It also makes website migration really easy.', 'google-analytics-for-wordpress'),
391
			'installed' => array_key_exists('duplicator/duplicator.php', $installed_plugins),
392
			'basename'  => 'duplicator/duplicator.php',
393
			'slug'      => 'duplicator',
394
			'settings'  => admin_url('admin.php?page=duplicator-settings'),
395
		);
396
397
		// WishList Member.
398
		$parsed_addons['wishlist_member'] = array(
399
			'active' => function_exists( 'wishlistmember_instance' ),
400
		);
401
		// GiveWP Analytics.
402
		$parsed_addons['givewp_google_analytics'] = array(
403
			'active' => function_exists( 'Give_Google_Analytics' ),
404
		);
405
		// Cookiebot.
406
		$parsed_addons['cookiebot'] = array(
407
			'active' => function_exists( 'monsterinsights_is_cookiebot_active' ) && monsterinsights_is_cookiebot_active(),
408
		);
409
		// Cookie Notice.
410
		$parsed_addons['cookie_notice'] = array(
411
			'active' => class_exists( 'Cookie_Notice' ),
412
		);
413
		// Complianz.
414
		$parsed_addons['complianz'] = array(
415
			'active' => defined( 'cmplz_plugin' ) || defined( 'cmplz_premium' ),
416
		);
417
		// Cookie Yes
418
		$parsed_addons['cookie_yes'] = array(
419
			'active' => defined( 'CLI_SETTINGS_FIELD' ),
420
		);
421
		// Google AMP.
422
		$parsed_addons['google_amp'] = array(
423
			'active' => defined( 'AMP__FILE__' ),
424
		);
425
		// Yoast SEO.
426
		$parsed_addons['yoast_seo'] = array(
427
			'active' => defined( 'WPSEO_VERSION' ),
428
		);
429
		// EasyAffiliate.
430
		$parsed_addons['easy_affiliate'] = array(
431
			'active' => defined( 'ESAF_EDITION' ),
432
		);
433
434
		// AffiliateWP
435
		$parsed_addons['affiliate-wp'] = array(
436
			'active'    => class_exists('AffiliateWP_Core_Requirements_Check'),
437
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugins/plugin-affiliate-wp.png',
438
			'title'     => 'AffiliateWP',
439
			'excerpt'   => __('The #1 affiliate management plugin for WordPress. Easily create an affiliate program for your eCommerce store or membership site within minutes and start growing your sales with the power of referral marketing.', 'google-analytics-for-wordpress'),
440
			'installed' => array_key_exists('affiliate-wp/affiliate-wp.php', $installed_plugins),
441
			'basename'  => 'affiliate-wp/affiliate-wp.php',
442
			'slug'      => 'affiliate-wp',
443
			'settings'  => admin_url('admin.php?page=affiliate-wp-settings'),
444
			'redirect'  => 'https://affiliatewp.com',
445
		);
446
447
		// WP Simple Pay
448
		$parsed_addons['wpsimplepay'] = array(
449
			'active'    => defined('SIMPLE_PAY_VERSION'),
450
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugins/plugin-wp-simple-pay.png',
451
			'title'     => 'WP Simple Pay',
452
			'excerpt'   => __('The #1 Stripe payments plugin for WordPress. Start accepting one-time and recurring payments on your WordPress site without setting up a shopping cart. No code required.', 'google-analytics-for-wordpress'),
453
			'installed' => array_key_exists('stripe/stripe-checkout.php', $installed_plugins),
454
			'basename'  => 'stripe/stripe-checkout.php',
455
			'slug'      => 'stripe',
456
			'settings'  => admin_url('edit.php?post_type=simple-pay&page=simpay_settings'),
457
		);
458
459
		// Sugar Calendar
460
		$parsed_addons['sugarcalendar'] = array(
461
			'active'    => class_exists('Sugar_Calendar\\Requirements_Check'),
462
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugins/plugin-sugar-calendar.png',
463
			'title'     => 'Sugar Calendar',
464
			'excerpt'   => __('A simple & powerful event calendar plugin for WordPress that comes with all the event management features including payments, scheduling, timezones, ticketing, recurring events, and more.', 'google-analytics-for-wordpress'),
465
			'installed' => array_key_exists('sugar-calendar-lite/sugar-calendar-lite.php', $installed_plugins),
466
			'basename'  => 'sugar-calendar-lite/sugar-calendar-lite.php',
467
			'slug'      => 'sugar-calendar-lite',
468
			'settings'  => admin_url('admin.php?page=sugar-calendar'),
469
		);
470
471
		// WPForms.
472
		$parsed_addons['wpforms-lite'] = array(
473
			'active'    => function_exists( 'wpforms' ),
474
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugins/plugin-wpforms.png',
475
			'title'     => 'WPForms',
476
			'excerpt'   => __( 'The best drag & drop WordPress form builder. Easily create beautiful contact forms, surveys, payment forms, and more with our 1000+ form templates. Trusted by over 6 million websites as the best forms plugin.', 'google-analytics-for-wordpress' ),
477
			'installed' => array_key_exists( 'wpforms-lite/wpforms.php', $installed_plugins ) || array_key_exists( 'wpforms/wpforms.php', $installed_plugins ),
478
			'basename'  => 'wpforms-lite/wpforms.php',
479
			'slug'      => 'wpforms-lite',
480
			'settings'  => admin_url( 'admin.php?page=wpforms-overview' ),
481
		);
482
483
		// UserFeedback.
484
		$parsed_addons['userfeedback-lite'] = array(
485
			'active'    => function_exists( 'userfeedback' ),
486
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugin-userfeedback.png',
487
			'title'     => 'UserFeedback',
488
			'excerpt'   => __( 'Ask visitors questions about how they use your website or what features can make you more money.', 'google-analytics-for-wordpress' ),
489
			'installed' => array_key_exists( 'userfeedback-lite/userfeedback.php', $installed_plugins ) || array_key_exists( 'userfeedback/userfeedback.php', $installed_plugins ),
490
			'basename'  => 'userfeedback-lite/userfeedback.php',
491
			'slug'      => 'userfeedback-lite',
492
			'settings'  => admin_url( 'admin.php?page=userfeedback_settings' ),
493
		);
494
495
		// AIOSEO.
496
		$parsed_addons['aioseo'] = array(
497
			'active'    => function_exists( 'aioseo' ),
498
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugins/plugin-all-in-one-seo.png',
499
			'title'     => 'AIOSEO',
500
			'excerpt'   => __( 'The original WordPress SEO plugin and toolkit that improves your website’s search rankings. Comes with all the SEO features like Local SEO, WooCommerce SEO, sitemaps, SEO optimizer, schema, and more.', 'google-analytics-for-wordpress' ),
501
			'installed' => array_key_exists( 'all-in-one-seo-pack/all_in_one_seo_pack.php', $installed_plugins ) || array_key_exists( 'all-in-one-seo-pack-pro/all_in_one_seo_pack.php', $installed_plugins ),
502
			'basename'  => ( monsterinsights_is_installed_aioseo_pro() ) ? 'all-in-one-seo-pack-pro/all_in_one_seo_pack.php' : 'all-in-one-seo-pack/all_in_one_seo_pack.php',
503
			'slug'      => 'all-in-one-seo-pack',
504
			'settings'  => admin_url( 'admin.php?page=aioseo' ),
505
		);
506
507
		// FunnelKit Stripe Woo Payment Gateway.
508
		$parsed_addons['funnelkit-stripe-woo-payment-gateway'] = array(
509
			'active'    => class_exists( 'FKWCS_Gateway_Stripe' ),
510
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugins/plugin-funnelkit-stripe-woo-payment-gateway.png',
511
			'title'     => 'Stripe Payment Gateway for WooCommerce',
512
			'excerpt'   => __( 'Stripe Payment Gateway for WooCommerce is an integrated solution that lets you accept payments on your online store for web and mobile.', 'google-analytics-for-wordpress' ),
513
			'installed' => array_key_exists( 'funnelkit-stripe-woo-payment-gateway/funnelkit-stripe-woo-payment-gateway.php', $installed_plugins ),
514
			'basename'  => 'funnelkit-stripe-woo-payment-gateway/funnelkit-stripe-woo-payment-gateway.php',
515
			'slug'      => 'funnelkit-stripe-woo-payment-gateway',
516
			'settings'  => admin_url( 'admin.php?page=wc-settings&tab=fkwcs_api_settings' ),
517
		);
518
519
		// Use the plugin dir name as the array key since AJAX activation in add-ons page won't work.
520
		$parsed_addons['all-in-one-seo-pack'] = $parsed_addons['aioseo'];
521
522
		// OptinMonster.
523
		$parsed_addons['optinmonster'] = array(
524
			'active'    => class_exists( 'OMAPI' ),
525
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugins/plugin-om.png',
526
			'title'     => 'OptinMonster',
527
			'excerpt'   => __( 'Instantly get more subscribers, leads, and sales with the #1 conversion optimization toolkit. Create high converting popups, announcement bars, spin a wheel, and more with smart targeting and personalization.', 'google-analytics-for-wordpress' ),
528
			'installed' => array_key_exists( 'optinmonster/optin-monster-wp-api.php', $installed_plugins ),
529
			'basename'  => 'optinmonster/optin-monster-wp-api.php',
530
			'slug'      => 'optinmonster',
531
			'settings'  => admin_url( 'admin.php?page=optin-monster-dashboard' ),
532
		);
533
		// WP Mail Smtp.
534
		$parsed_addons['wp-mail-smtp'] = array(
535
			'active'    => function_exists( 'wp_mail_smtp' ),
536
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugins/plugin-smtp.png',
537
			'title'     => 'WP Mail SMTP',
538
			'excerpt'   => __( 'Improve your WordPress email deliverability and make sure that your website emails reach user’s inbox with the #1 SMTP plugin for WordPress. Over 3 million websites use it to fix WordPress email issues.', 'google-analytics-for-wordpress' ),
539
			'installed' => array_key_exists( 'wp-mail-smtp/wp_mail_smtp.php', $installed_plugins ),
540
			'basename'  => 'wp-mail-smtp/wp_mail_smtp.php',
541
			'slug'      => 'wp-mail-smtp',
542
		);
543
		// SeedProd.
544
		$parsed_addons['coming-soon'] = array(
545
			'active'    => defined( 'SEEDPROD_VERSION' ),
546
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugins/plugin-seedprod.png',
547
			'title'     => 'SeedProd',
548
			'excerpt'   => __( 'The fastest drag & drop landing page builder for WordPress. Create custom landing pages without writing code, connect them with your CRM, collect subscribers, and grow your audience. Trusted by 1 million sites.', 'google-analytics-for-wordpress' ),
549
			'installed' => array_key_exists( 'coming-soon/coming-soon.php', $installed_plugins ),
550
			'basename'  => 'coming-soon/coming-soon.php',
551
			'slug'      => 'coming-soon',
552
			'settings'  => admin_url( 'admin.php?page=seedprod_lite' ),
553
		);
554
		// RafflePress
555
		$parsed_addons['rafflepress'] = array(
556
			'active'    => defined('RAFFLEPRESS_VERSION'),
557
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugins/plugin-rafflepress.png',
558
			'title'     => 'RafflePress',
559
			'excerpt'   => __( 'Turn your website visitors into brand ambassadors! Easily grow your email list, website traffic, and social media followers with the most powerful giveaways & contests plugin for WordPress.', 'google-analytics-for-wordpress' ),
560
			'installed' => array_key_exists( 'rafflepress/rafflepress.php', $installed_plugins ),
561
			'basename'  => 'rafflepress/rafflepress.php',
562
			'slug'      => 'rafflepress',
563
			'settings'  => admin_url( 'admin.php?page=rafflepress_lite' ),
564
		);
565
		// TrustPulse
566
		$parsed_addons['trustpulse'] = array(
567
			'active'    => defined('TRUSTPULSE_PLUGIN_VERSION'),
568
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugins/plugin-trustpulse.png',
569
			'title'     => 'TrustPulse',
570
			'excerpt'   => __( 'Boost your sales and conversions by up to 15% with real-time social proof notifications. TrustPulse helps you show live user activity and purchases to help convince other users to purchase.', 'google-analytics-for-wordpress' ),
571
			'installed' => array_key_exists( 'trustpulse-api/trustpulse.php', $installed_plugins ),
572
			'basename'  => 'trustpulse-api/trustpulse.php',
573
			'slug'      => 'trustpulse-api',
574
		);
575
576
		$parsed_addons['trustpulse-api'] = $parsed_addons['trustpulse'];
577
578
		// SearchWP
579
		$parsed_addons['searchwp'] = array(
580
			'active'    => defined('SEARCHWP_LIVE_SEARCH_VERSION'),
581
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugins/plugin-searchwp.png',
582
			'title'     => 'SearchWP',
583
			'excerpt'   => __('The most advanced WordPress search plugin. Customize your WordPress search algorithm, reorder search results, track search metrics, and everything you need to leverage search to grow your business.', 'google-analytics-for-wordpress'),
584
			'installed' => array_key_exists('searchwp-live-ajax-search/searchwp-live-ajax-search.php', $installed_plugins),
585
			'basename'  => 'searchwp-live-ajax-search/searchwp-live-ajax-search.php',
586
			'slug'      => 'searchwp-live-ajax-search',
587
			'settings'  => admin_url('admin.php?page=searchwp-live-search'),
588
		);
589
590
		// Smash Balloon (Instagram)
591
		$parsed_addons['instagram-feed'] = array(
592
			'active'    => defined( 'SBIVER' ),
593
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugins/plugin-sb-instagram.png',
594
			'title'     => 'Smash Balloon Instagram Feeds',
595
			'excerpt'   => __( 'Easily display Instagram content on your WordPress site without writing any code. Comes with multiple templates, ability to show content from multiple accounts, hashtags, and more. Trusted by 1 million websites.', 'google-analytics-for-wordpress' ),
596
			'installed' => array_key_exists( 'instagram-feed/instagram-feed.php', $installed_plugins ),
597
			'basename'  => 'instagram-feed/instagram-feed.php',
598
			'slug'      => 'instagram-feed',
599
			'settings'  => admin_url( 'admin.php?page=sb-instagram-feed' ),
600
		);
601
602
		$parsed_addons['smash-balloon-instagram'] = $parsed_addons['instagram-feed'];
603
604
		// Smash Balloon (Facebook)
605
		$parsed_addons['custom-facebook-feed'] = array(
606
			'active'    => defined( 'CFFVER' ),
607
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugins/plugin-sb-facebook.png',
608
			'title'     => 'Smash Balloon Facebook Feeds',
609
			'excerpt'   => __( 'Easily display Facebook content on your WordPress site without writing any code. Comes with multiple templates, ability to embed albums, group content, reviews, live videos, comments, and reactions.', 'google-analytics-for-wordpress' ),
610
			'installed' => array_key_exists( 'custom-facebook-feed/custom-facebook-feed.php', $installed_plugins ),
611
			'basename'  => 'custom-facebook-feed/custom-facebook-feed.php',
612
			'slug'      => 'custom-facebook-feed',
613
			'settings'  => admin_url( 'admin.php?page=cff-feed-builder' ),
614
		);
615
616
		$parsed_addons['smash-balloon-facebook'] = $parsed_addons['custom-facebook-feed'];
617
618
		// Smash Balloon (YouTube)
619
		$parsed_addons['smash-balloon-youtube'] = array(
620
			'active'    => defined('SBYVER'),
621
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugins/plugin-sb-youtube.png',
622
			'title'     => 'Smash Balloon YouTube Feeds',
623
			'excerpt'   => __('Easily display YouTube videos on your WordPress site without writing any code. Comes with multiple layouts, ability to embed live streams, video filtering, ability to combine multiple channel videos, and more.', 'google-analytics-for-wordpress'),
624
			'installed' => array_key_exists('feeds-for-youtube/youtube-feed.php', $installed_plugins),
625
			'basename'  => 'feeds-for-youtube/youtube-feed.php',
626
			'slug'      => 'feeds-for-youtube',
627
			'settings'  => admin_url('admin.php?page=sby-feed-builder'),
628
		);
629
630
		// In Year in Review we need the exact slug for the key in order to make the AJAX activation work.
631
		$parsed_addons['feeds-for-youtube'] = $parsed_addons['smash-balloon-youtube'];
632
633
		// Smash Balloon (Twitter)
634
		$parsed_addons['smash-balloon-twitter'] = array(
635
			'active'    => defined('CTF_VERSION'),
636
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugins/plugin-sb-twitter.png',
637
			'title'     => 'Smash Balloon Twitter Feeds',
638
			'excerpt'   => __('Easily display Twitter content in WordPress without writing any code. Comes with multiple layouts, ability to combine multiple Twitter feeds, Twitter card support, tweet moderation, and more.', 'google-analytics-for-wordpress'),
639
			'installed' => array_key_exists('custom-twitter-feeds/custom-twitter-feed.php', $installed_plugins),
640
			'basename'  => 'custom-twitter-feeds/custom-twitter-feed.php',
641
			'slug'      => 'custom-twitter-feeds',
642
			'settings'  => admin_url('admin.php?page=ctf-feed-builder'),
643
		);
644
645
		// We need the key of the addon to be exactly the slug. We should deprecate `smash-balloon-twitter` next version.
646
		$parsed_addons['custom-twitter-feeds'] = $parsed_addons['smash-balloon-twitter'];
647
648
		// PushEngage
649
		$parsed_addons['pushengage'] = array(
650
			'active'    => defined('PUSHENGAGE_VERSION'),
651
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugins/plugin-pushengage.png',
652
			'title'     => 'PushEngage',
653
			'excerpt'   => __('Connect with your visitors after they leave your website with the leading web push notification software. Over 10,000+ businesses worldwide use PushEngage to send 15 billion notifications each month.', 'google-analytics-for-wordpress'),
654
			'installed' => array_key_exists( 'pushengage/main.php', $installed_plugins ),
655
			'basename'  => 'pushengage/main.php',
656
			'slug'      => 'pushengage',
657
		);
658
659
		// Uncanny Automator
660
		$parsed_addons['uncanny-automator'] = array(
661
			'active'    => function_exists('automator_get_recipe_id'),
662
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugins/plugin-uncanny-automator.png',
663
			'title'     => 'Uncanny Automator',
664
			'excerpt'   => __('Automate everything with the #1 no-code Automation tool for WordPress.', 'google-analytics-for-wordpress'),
665
			'installed' => array_key_exists('uncanny-automator/uncanny-automator.php', $installed_plugins),
666
			'basename'  => 'uncanny-automator/uncanny-automator.php',
667
			'slug'      => 'uncanny-automator',
668
			'setup_complete' => class_exists( 'Uncanny_Automator\Api_Server' ) ? !! \Uncanny_Automator\Api_Server::is_automator_connected() : false,
0 ignored issues
show
Bug introduced by
The type Uncanny_Automator\Api_Server was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
669
			'wizard_url'     => admin_url( 'edit.php?post_type=uo-recipe&page=uncanny-automator-setup-wizard' ),
670
			'recipe_url'     => admin_url( 'post-new.php?post_type=uo-recipe' ),
671
		);
672
673
		// Pretty Links
674
		$parsed_addons['pretty-link'] = array(
675
			'active'    => class_exists( 'PrliBaseController' ),
676
			'icon'      => '',
677
			'title'     => 'Pretty Links',
678
			'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' ),
679
			'installed' => array_key_exists( 'pretty-link/pretty-link.php', $installed_plugins ),
680
			'basename'  => 'pretty-link/pretty-link.php',
681
			'slug'      => 'pretty-link',
682
			'settings'  => admin_url( 'edit.php?post_type=pretty-link' ),
683
		);
684
		// SearchWP
685
		$parsed_addons['searchwp-live-ajax-search'] = array(
686
			'active'    => defined( 'SEARCHWP_LIVE_SEARCH_VERSION' ),
687
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugin-searchwp.svg',
688
			'title'     => 'SearchWP',
689
			'excerpt'   => __( 'The most advanced WordPress search plugin. Customize your WordPress search algorithm, reorder search results, track search metrics, and everything you need to leverage search to grow your business.', 'google-analytics-for-wordpress' ),
690
			'installed' => array_key_exists( 'searchwp-live-ajax-search/searchwp-live-ajax-search.php', $installed_plugins ),
691
			'basename'  => 'searchwp-live-ajax-search/searchwp-live-ajax-search.php',
692
			'slug'      => 'searchwp-live-ajax-search',
693
			'settings'  => admin_url( 'admin.php?page=searchwp-live-search' ),
694
		);
695
		// Sugar Calendar Lite
696
		$parsed_addons['sugar-calendar-lite'] = array(
697
			'active'    => class_exists( 'Sugar_Calendar\\Requirements_Check' ),
698
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugin-sugar-calendar.svg',
699
			'title'     => 'Sugar Calendar',
700
			'excerpt'   => __( 'A simple & powerful event calendar plugin for WordPress that comes with all the event management features including payments, scheduling, timezones, ticketing, recurring events, and more.', 'google-analytics-for-wordpress' ),
701
			'installed' => array_key_exists( 'sugar-calendar-lite/sugar-calendar-lite.php', $installed_plugins ),
702
			'basename'  => 'sugar-calendar-lite/sugar-calendar-lite.php',
703
			'slug'      => 'sugar-calendar-lite',
704
			'settings'  => admin_url( 'admin.php?page=sugar-calendar' ),
705
		);
706
		// Charitable
707
		$parsed_addons['charitable'] = array(
708
			'active'    => class_exists( 'Charitable' ),
709
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugins/plugin-charitable.png',
710
			'title'     => 'WP Charitable',
711
			'excerpt'   => __( 'Top-rated WordPress donation and fundraising plugin. Over 10,000+ non-profit organizations and website owners use Charitable to create fundraising campaigns and raise more money online.', 'google-analytics-for-wordpress' ),
712
			'installed' => array_key_exists( 'charitable/charitable.php', $installed_plugins ),
713
			'basename'  => 'charitable/charitable.php',
714
			'slug'      => 'charitable',
715
			'settings'  => admin_url( 'admin.php?page=charitable&install=true' ),
716
		);
717
		// WPCode
718
		$parsed_addons['insert-headers-and-footers'] = array(
719
			'active'    => class_exists( 'WPCode' ),
720
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugin-wpcode.svg',
721
			'title'     => 'WPCode',
722
			'excerpt'   => __( 'Future proof your WordPress customizations with the most popular code snippet management plugin for WordPress. Trusted by over 1,500,000+ websites for easily adding code to WordPress right from the admin area.', 'google-analytics-for-wordpress' ),
723
			'installed' => array_key_exists( 'insert-headers-and-footers/ihaf.php', $installed_plugins ),
724
			'basename'  => 'insert-headers-and-footers/ihaf.php',
725
			'slug'      => 'insert-headers-and-footers',
726
			'settings'  => admin_url( 'admin.php?page=wpcode' ),
727
		);
728
		// Duplicator
729
		$parsed_addons['duplicator'] = array(
730
			'active'    => class_exists( 'DuplicatorPhpVersionCheck' ),
731
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugins/plugin-duplicator.png',
732
			'title'     => 'Duplicator',
733
			'excerpt'   => __( 'Leading WordPress backup & site migration plugin. Over 1,500,000+ smart website owners use Duplicator to make reliable and secure WordPress backups to protect their websites. It also makes website migration really easy.', 'google-analytics-for-wordpress' ),
734
			'installed' => array_key_exists( 'duplicator/duplicator.php', $installed_plugins ),
735
			'basename'  => 'duplicator/duplicator.php',
736
			'slug'      => 'duplicator',
737
			'settings'  => admin_url( 'admin.php?page=duplicator' ),
738
		);
739
		// WP Simple Pay
740
		$parsed_addons['stripe'] = array(
741
			'active'    => defined( 'SIMPLE_PAY_MAIN_FILE' ),
742
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugin-simple-pay.svg',
743
			'title'     => 'WP Simple Pay',
744
			'excerpt'   => __( 'Start accepting one-time and recurring payments on your WordPress site without setting up a shopping cart. No code required.', 'google-analytics-for-wordpress' ),
745
			'installed' => array_key_exists( 'stripe/stripe-checkout.php', $installed_plugins ),
746
			'basename'  => 'stripe/stripe-checkout.php',
747
			'slug'      => 'stripe',
748
			'settings'  => admin_url( 'edit.php?post_type=simple-pay&page=simpay_settings&tab=general' ),
749
		);
750
		if ( function_exists( 'WC' ) ) {
751
			// Advanced Coupons
752
			$parsed_addons['advancedcoupons'] = array(
753
				'active'    => class_exists( 'ACFWF' ),
754
				'icon'      => '',
755
				'title'     => 'Advanced Coupons',
756
				'excerpt'   => __( 'Advanced Coupons for WooCommerce (Free Version) gives WooCommerce store owners extra coupon features so they can market their stores better.', 'google-analytics-for-wordpress' ),
757
				'installed' => array_key_exists( 'advanced-coupons-for-woocommerce-free/advanced-coupons-for-woocommerce-free.php', $installed_plugins ),
758
				'basename'  => 'advanced-coupons-for-woocommerce-free/advanced-coupons-for-woocommerce-free.php',
759
				'slug'      => 'advanced-coupons-for-woocommerce-free',
760
				'settings'  => admin_url( 'edit.php?post_type=shop_coupon&acfw' ),
761
			);
762
		}
763
764
		// UserFeedback.
765
		$parsed_addons['userfeedback-lite'] = array(
766
			'active'    => function_exists( 'userfeedback' ),
767
			'icon'      => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugins/plugin-userfeedback.png',
768
			'title'     => 'UserFeedback',
769
			'excerpt'   => __( 'See what your analytics software isn’t telling you with powerful UserFeedback surveys.', 'google-analytics-for-wordpress' ),
770
			'installed' => array_key_exists( 'userfeedback-lite/userfeedback.php', $installed_plugins ) || array_key_exists( 'userfeedback/userfeedback.php', $installed_plugins ),
771
			'basename'  => 'userfeedback-lite/userfeedback.php',
772
			'slug'      => 'userfeedback-lite',
773
			'settings'  => admin_url( 'admin.php?page=userfeedback_onboarding' ),
774
			'surveys'  => admin_url( 'admin.php?page=userfeedback_surveys' ),
775
			'setup_complete'  => (get_option('userfeedback_onboarding_complete', 0) == 1),
776
		);
777
778
		// Gravity Forms.
779
		$parsed_addons['gravity_forms'] = array(
780
			'active' => class_exists( 'GFCommon' ),
781
		);
782
		// Formidable Forms.
783
		$parsed_addons['formidable_forms'] = array(
784
			'active' => class_exists( 'FrmHooksController' ),
785
		);
786
		// Manual UA Addon.
787
		if ( ! isset( $parsed_addons['manual_ua'] ) ) {
788
			$parsed_addons['manual_ua'] = array(
789
				'active' => class_exists( 'MonsterInsights_Manual_UA' ),
790
			);
791
		}
792
793
		$parsed_addons = apply_filters('monsterinsights_parsed_addons', $parsed_addons);
794
795
		wp_send_json( $parsed_addons );
796
	}
797
798
	/**
799
	 * Wrapper around the monsterinsights_get_addon function.
800
	 * Kept for backwards compatibility.
801
	 *
802
	 * @param $installed_plugins
803
	 * @param $addons_type
804
	 * @param $addon
805
	 * @param $slug
806
	 * @deprecated Use monsterinsights_get_addon instead.
807
	 * @return mixed
808
	 */
809
	public function get_addon( $installed_plugins, $addons_type, $addon, $slug ) {
810
		return monsterinsights_get_addon($installed_plugins, $addons_type, $addon, $slug);
811
	}
812
813
	/**
814
	 * Use custom notices in the Vue app on the Settings screen.
815
	 */
816
	public function hide_old_notices() {
817
818
		global $wp_version;
819
		if ( version_compare( $wp_version, '4.6', '<' ) ) {
820
			// remove_all_actions triggers an infinite loop on older versions.
821
			return;
822
		}
823
824
		$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...
825
		// Bail if we're not on a MonsterInsights screen.
826
		if ( empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) === false ) {
827
			return;
828
		}
829
830
		// Hide admin notices on the settings screen.
831
		if ( monsterinsights_is_settings_page() ) {
832
			remove_all_actions( 'admin_notices' );
833
		}
834
835
	}
836
837
	/**
838
	 * Update manual v4.
839
	 */
840
	public function update_manual_v4() {
841
842
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
843
844
		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
845
			return;
846
		}
847
848
		$manual_v4_code = isset( $_POST['manual_v4_code'] ) ? sanitize_text_field( wp_unslash( $_POST['manual_v4_code'] ) ) : '';
849
		$manual_v4_code = monsterinsights_is_valid_v4_id( $manual_v4_code ); // Also sanitizes the string.
850
851
		if ( ! empty( $_REQUEST['isnetwork'] ) && sanitize_text_field( wp_unslash( $_REQUEST['isnetwork'] ) ) ) {
852
			define( 'WP_NETWORK_ADMIN', true );
853
		}
854
		$manual_v4_code_old = is_network_admin() ? MonsterInsights()->auth->get_network_manual_v4_id() : MonsterInsights()->auth->get_manual_v4_id();
855
856
		if ( $manual_v4_code && $manual_v4_code_old && $manual_v4_code_old === $manual_v4_code ) {
857
			// Same code we had before
858
			// Do nothing.
859
			wp_send_json_success();
860
		} else if ( $manual_v4_code && $manual_v4_code_old && $manual_v4_code_old !== $manual_v4_code ) {
861
			// Different UA code.
862
			if ( is_network_admin() ) {
863
				MonsterInsights()->auth->set_network_manual_v4_id( $manual_v4_code );
864
			} else {
865
				MonsterInsights()->auth->set_manual_v4_id( $manual_v4_code );
866
			}
867
		} else if ( $manual_v4_code && empty( $manual_v4_code_old ) ) {
868
			// Move to manual.
869
			if ( is_network_admin() ) {
870
				MonsterInsights()->auth->set_network_manual_v4_id( $manual_v4_code );
871
			} else {
872
				MonsterInsights()->auth->set_manual_v4_id( $manual_v4_code );
873
			}
874
		} else if ( empty( $manual_v4_code ) && $manual_v4_code_old ) {
875
			// Deleted manual.
876
			if ( is_network_admin() ) {
877
				MonsterInsights()->auth->delete_network_manual_v4_id();
878
			} else {
879
				MonsterInsights()->auth->delete_manual_v4_id();
880
			}
881
		} else if ( isset( $_POST['manual_v4_code'] ) && empty( $manual_v4_code ) ) {
882
			wp_send_json_error( array(
883
				'v4_error' => 1,
884
				// Translators: link tag starts with url, link tag ends.
885
				'error'    => sprintf(
886
					__( 'Oops! Please enter a valid Google Analytics 4 Measurement ID. %1$sLearn how to find your Measurement ID%2$s.', 'google-analytics-for-wordpress' ),
887
					'<a target="_blank" href="' . monsterinsights_get_url( 'notice', 'invalid-manual-gav4-code', 'https://www.monsterinsights.com/docs/how-to-set-up-dual-tracking/' ) . '">',
888
					'</a>'
889
				),
890
			) );
891
		}
892
893
		wp_send_json_success();
894
	}
895
896
	public function update_measurement_protocol_secret() {
897
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
898
899
		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
900
			return;
901
		}
902
903
		if ( ! empty( $_REQUEST['isnetwork'] ) && sanitize_text_field( wp_unslash( $_REQUEST['isnetwork'] ) ) ) {
904
			define( 'WP_NETWORK_ADMIN', true );
905
		}
906
907
		$value = empty( $_REQUEST['value'] ) ? '' : sanitize_text_field( wp_unslash( $_REQUEST['value'] ) );
908
909
		$auth = MonsterInsights()->auth;
910
911
		if ( is_network_admin() ) {
912
			$auth->set_network_measurement_protocol_secret( $value );
913
		} else {
914
			$auth->set_measurement_protocol_secret( $value );
915
		}
916
917
		// Send API request to Relay
918
		// TODO: Remove when token automation API is ready
919
		$api = new MonsterInsights_API_Request( 'auth/mp-token/', 'POST' );
920
		$api->set_additional_data( array(
921
			'mp_token' => $value,
922
		) );
923
924
		// Even if there's an error from Relay, we can still return a successful json
925
		// payload because we can try again with Relay token push in the future
926
		$data   = array();
927
		$result = $api->request();
928
		if ( is_wp_error( $result ) ) {
929
			// Just need to output the error in the response for debugging purpose
930
			$data['error'] = array(
931
				'message' => $result->get_error_message(),
932
				'code'    => $result->get_error_code(),
933
			);
934
		}
935
936
		wp_send_json_success( $data );
937
	}
938
939
940
	/**
941
	 * Import exported JSON file.
942
	 */
943
	public function handle_settings_import() {
944
945
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
946
947
		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
948
			return;
949
		}
950
951
		if ( ! isset( $_FILES['import_file'] ) ) {
952
			return;
953
		}
954
955
		$import_file = $_FILES['import_file']; // phpcs:ignore
956
957
		$extension = explode( '.', sanitize_text_field( wp_unslash( $import_file['name'] ) ) ); // phpcs:ignore
958
		$extension = end( $extension );
959
960
		if ( 'json' !== $extension ) {
961
			wp_send_json_error( array(
962
				'message' => esc_html__( 'Please upload a valid .json file', 'google-analytics-for-wordpress' ),
963
			) );
964
		}
965
966
		$file = file_get_contents( $import_file['tmp_name'] );
967
968
		if ( empty( $file ) ) {
969
			wp_send_json_error( array(
970
				'message' => esc_html__( 'Please select a valid file to upload.', 'google-analytics-for-wordpress' ),
971
			) );
972
		}
973
974
		// Retrieve the settings from the file and convert the json object to an array.
975
		$new_settings = json_decode( wp_json_encode( json_decode( $file ) ), true );
976
		$settings     = monsterinsights_get_options();
977
		$exclude      = array(
978
			'analytics_profile',
979
			'analytics_profile_code',
980
			'analytics_profile_name',
981
			'oauth_version',
982
			'cron_last_run',
983
			'monsterinsights_oauth_status',
984
		);
985
986
		$this->import_site_notes( $new_settings['site_notes'] );
987
		unset( $new_settings['site_notes'] );
988
989
		foreach ( $exclude as $e ) {
990
			if ( ! empty( $new_settings[ $e ] ) ) {
991
				unset( $new_settings[ $e ] );
992
			}
993
		}
994
995
		foreach ( $exclude as $e ) {
996
			if ( ! empty( $settings[ $e ] ) ) {
997
				$new_settings = $settings[ $e ];
998
			}
999
		}
1000
1001
		global $monsterinsights_settings;
1002
		$monsterinsights_settings = $new_settings;
1003
1004
		update_option( monsterinsights_get_option_name(), $new_settings );
1005
1006
		wp_send_json_success( $new_settings );
1007
1008
	}
1009
1010
	/**
1011
	 * Generic Ajax handler for grabbing report data in JSON.
1012
	 */
1013
	public function get_report_data() {
1014
1015
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
1016
1017
		if ( ! current_user_can( 'monsterinsights_view_dashboard' ) ) {
1018
			// Translators: link tag starts with url, link tag ends.
1019
			$message = sprintf(
1020
				esc_html__( 'Oops! You don not have permissions to view MonsterInsights reporting. Please check with your site administrator that your role is included in the MonsterInsights permissions settings. %1$sClick here for more information%2$s.', 'google-analytics-for-wordpress' ),
1021
				'<a target="_blank" href="' . monsterinsights_get_url( 'notice', 'cannot-view-reports', 'https://www.monsterinsights.com/docs/how-to-allow-user-roles-to-access-the-monsterinsights-reports-and-settings/' ) . '">',
1022
				'</a>'
1023
			);
1024
			wp_send_json_error( array( 'message' => $message ) );
1025
		}
1026
1027
		if ( ! empty( $_REQUEST['isnetwork'] ) && $_REQUEST['isnetwork'] ) {
1028
			define( 'WP_NETWORK_ADMIN', true );
1029
		}
1030
		$settings_page    = admin_url( 'admin.php?page=monsterinsights_settings' );
1031
		$reactivation_url = monsterinsights_get_url( 'admin-notices', 'expired-license', "https://www.monsterinsights.com/my-account/" );
0 ignored issues
show
Unused Code introduced by
The assignment to $reactivation_url is dead and can be removed.
Loading history...
1032
		$learn_more_link  = esc_url( 'https://www.monsterinsights.com/docs/faq/#licensedplugin' );
0 ignored issues
show
Unused Code introduced by
The assignment to $learn_more_link is dead and can be removed.
Loading history...
1033
1034
		// Only for Pro users, require a license key to be entered first so we can link to things.
1035
		if ( monsterinsights_is_pro_version() ) {
1036
			if ( ! MonsterInsights()->license->is_site_licensed() && ! MonsterInsights()->license->is_network_licensed() ) {
1037
				// Translators: Support link tag starts with url and Support link tag ends.
1038
				$message = sprintf(
1039
					esc_html__( 'Oops! You cannot view MonsterInsights reports because you are not licensed. Please try again in a few minutes. If the issue continues, please %1$scontact our support%2$s team.', 'google-analytics-for-wordpress' ),
1040
					'<a target="_blank" href="' . monsterinsights_get_url( 'notice', 'cannot-view-reports', 'https://www.monsterinsights.com/my-account/support/' ) . '">',
1041
					'</a>'
1042
				);
1043
				wp_send_json_error( array(
1044
					'message' => $message,
1045
					'footer'  => '<a href="' . $settings_page . '">' . __( 'Add your license', 'google-analytics-for-wordpress' ) . '</a>',
1046
				) );
1047
			} else if ( MonsterInsights()->license->is_site_licensed() && ! MonsterInsights()->license->site_license_has_error() ) {
1048
				// Good to go: site licensed.
1049
			} else if ( MonsterInsights()->license->is_network_licensed() && ! MonsterInsights()->license->network_license_has_error() ) {
1050
				// Good to go: network licensed.
1051
			} else {
1052
				// Translators: Support link tag starts with url and Support link tag ends.
1053
				$message = sprintf(
1054
					esc_html__( 'Oops! We had a problem due to a license key error. Please try again in a few minutes. If the problem persists, please %1$scontact our support%2$s team.', 'google-analytics-for-wordpress' ),
1055
					'<a target="_blank" href="' . monsterinsights_get_url( 'notice', 'cannot-view-reports', 'https://www.monsterinsights.com/my-account/support/' ) . '">',
1056
					'</a>'
1057
				);
1058
				wp_send_json_error( array( 'message' => $message ) );
1059
			}
1060
		}
1061
1062
		// We do not have a current auth.
1063
		$site_auth = MonsterInsights()->auth->get_viewname();
1064
		$ms_auth   = is_multisite() && MonsterInsights()->auth->get_network_viewname();
1065
		if ( ! $site_auth && ! $ms_auth ) {
1066
			$url = admin_url( 'admin.php?page=monsterinsights-onboarding' );
1067
1068
			// Check for MS dashboard
1069
			if ( is_network_admin() ) {
1070
				$url = network_admin_url( 'admin.php?page=monsterinsights-onboarding' );
1071
			}
1072
			// Translators: Wizard link tag starts with url and Wizard link tag ends.
1073
			$message = sprintf(
1074
				esc_html__( 'You need to authenticate into MonsterInsights before viewing reports. Please run our %1$ssetup wizard%2$s.', 'google-analytics-for-wordpress' ),
1075
				'<a href="' . esc_url( $url ) . '">',
1076
				'</a>'
1077
			);
1078
			wp_send_json_error( array( 'message' => $message ) );
1079
		}
1080
1081
		$report_name = isset( $_POST['report'] ) ? sanitize_text_field( wp_unslash( $_POST['report'] ) ) : '';
1082
1083
		if ( empty( $report_name ) ) {
1084
			// Translators: Support link tag starts with url and Support link tag ends.
1085
			$message = sprintf(
1086
				esc_html__( 'Oops! We ran into a problem displaying this report. Please %1$scontact our support%2$s team if this issue persists.', 'google-analytics-for-wordpress' ),
1087
				'<a target="_blank" href="' . monsterinsights_get_url( 'notice', 'cannot-display-reports', 'https://www.monsterinsights.com/my-account/support/' ) . '">',
1088
				'</a>'
1089
			);
1090
			wp_send_json_error( array( 'message' => $message ) );
1091
		}
1092
1093
		$report = MonsterInsights()->reporting->get_report( $report_name );
1094
1095
		$isnetwork = ! empty( $_REQUEST['isnetwork'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['isnetwork'] ) ) : '';
1096
		$start     = ! empty( $_POST['start'] ) ? sanitize_text_field( wp_unslash( $_POST['start'] ) ) : $report->default_start_date();
1097
		$end       = ! empty( $_POST['end'] ) ? sanitize_text_field( wp_unslash( $_POST['end'] ) ) : $report->default_end_date();
1098
1099
		$args = array(
1100
			'start' => $start,
1101
			'end'   => $end,
1102
		);
1103
1104
		// User want to show compare report.
1105
		if ( isset( $_POST['compare_report'] ) ) {
1106
			$args['compare_start'] = ! empty( $_POST['compare_start'] ) ? sanitize_text_field( wp_unslash( $_POST['compare_start'] ) ) : $report->default_compare_start_date();
1107
			$args['compare_end']   = ! empty( $_POST['compare_end'] ) ? sanitize_text_field( wp_unslash( $_POST['compare_end'] ) ) : $report->default_compare_end_date();
1108
		}
1109
1110
		if ( $isnetwork ) {
1111
			$args['network'] = true;
1112
		}
1113
1114
		if ( monsterinsights_is_pro_version() && ! MonsterInsights()->license->license_can( $report->level ) ) {
1115
			$data = array(
1116
				'success' => false,
1117
				'error'   => 'license_level',
1118
			);
1119
		} else {
1120
			$data = apply_filters( 'monsterinsights_vue_reports_data', $report->get_data( $args ), $report_name, $report );
1121
		}
1122
1123
		if ( ! empty( $data['success'] ) ) {
1124
			if ( empty( $data['data'] ) ) {
1125
				wp_send_json_success( new stdclass() );
1126
			} else {
1127
				wp_send_json_success( $data['data'] );
1128
			}
1129
		} else if ( isset( $data['success'] ) && false === $data['success'] && ! empty( $data['error'] ) ) {
1130
			// Use a custom handler for invalid_grant errors.
1131
			if ( strpos( $data['error'], 'invalid_grant' ) > 0 ) {
1132
				wp_send_json_error(
1133
					array(
1134
						'message' => 'invalid_grant',
1135
						'footer'  => '',
1136
					)
1137
				);
1138
			}
1139
1140
			wp_send_json_error(
1141
				array(
1142
					'message' => $data['error'],
1143
					'footer'  => isset( $data['data']['footer'] ) ? $data['data']['footer'] : '',
1144
					'type'    => isset( $data['data']['type'] ) ? $data['data']['type'] : '',
1145
				)
1146
			);
1147
		}
1148
1149
		// Translators: Support link tag starts with url and Support link tag ends.
1150
		$message = sprintf(
1151
			esc_html__( 'Oops! We encountered an error while generating your reports. Please wait a few minutes and try again. If the issue persists, please %1$scontact our support%2$s team.', 'google-analytics-for-wordpress' ),
1152
			'<a href="' . monsterinsights_get_url( 'notice', 'error-generating-reports', 'https://www.monsterinsights.com/my-account/support/' ) . '">',
1153
			'</a>'
1154
		);
1155
		wp_send_json_error( array( 'message' => $message ) );
1156
	}
1157
1158
	/**
1159
	 * Install plugins which are not addons.
1160
	 */
1161
	public function install_plugin() {
1162
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
1163
1164
		if ( ! monsterinsights_can_install_plugins() ) {
1165
			wp_send_json( array(
1166
				'error' => esc_html__( 'Oops! You are not allowed to install plugins. Please contact your website administrator for further assistance.', 'google-analytics-for-wordpress' ),
1167
			) );
1168
		}
1169
1170
		$slug = isset( $_POST['slug'] ) ? sanitize_text_field( wp_unslash( $_POST['slug'] ) ) : false;
1171
1172
		if ( ! $slug ) {
1173
			wp_send_json( array(
1174
				'message' => esc_html__( 'Missing plugin name.', 'google-analytics-for-wordpress' ),
1175
			) );
1176
		}
1177
1178
		include_once ABSPATH . 'wp-admin/includes/plugin-install.php';
1179
1180
		$api = plugins_api( 'plugin_information', array(
1181
			'slug'   => $slug,
1182
			'fields' => array(
1183
				'short_description' => false,
1184
				'sections'          => false,
1185
				'requires'          => false,
1186
				'rating'            => false,
1187
				'ratings'           => false,
1188
				'downloaded'        => false,
1189
				'last_updated'      => false,
1190
				'added'             => false,
1191
				'tags'              => false,
1192
				'compatibility'     => false,
1193
				'homepage'          => false,
1194
				'donate_link'       => false,
1195
			),
1196
		) );
1197
1198
		if ( is_wp_error( $api ) ) {
1199
			return $api->get_error_message();
1200
		}
1201
1202
		$download_url = $api->download_link;
1203
1204
		$method = '';
1205
		$url    = add_query_arg(
1206
			array(
1207
				'page' => 'monsterinsights-settings',
1208
			),
1209
			admin_url( 'admin.php' )
1210
		);
1211
		$url    = esc_url( $url );
1212
1213
		ob_start();
1214
		if ( false === ( $creds = request_filesystem_credentials( $url, $method, false, false, null ) ) ) {
1215
			$form = ob_get_clean();
1216
1217
			wp_send_json( array( 'form' => $form ) );
1218
		}
1219
1220
		// If we are not authenticated, make it happen now.
1221
		if ( ! WP_Filesystem( $creds ) ) {
1222
			ob_start();
1223
			request_filesystem_credentials( $url, $method, true, false, null );
1224
			$form = ob_get_clean();
1225
1226
			wp_send_json( array( 'form' => $form ) );
1227
1228
		}
1229
1230
		// We do not need any extra credentials if we have gotten this far, so let's install the plugin.
1231
		monsterinsights_require_upgrader();
1232
1233
		// Prevent language upgrade in ajax calls.
1234
		remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
1235
		// Create the plugin upgrader with our custom skin.
1236
		$installer = new MonsterInsights_Plugin_Upgrader( new MonsterInsights_Skin() );
1237
		$installer->install( $download_url );
1238
1239
		// Flush the cache and return the newly installed plugin basename.
1240
		wp_cache_flush();
1241
		wp_send_json_success();
1242
1243
		wp_die();
1244
	}
1245
1246
	/**
1247
	 * Store that the first run notice has been dismissed so it doesn't show up again.
1248
	 */
1249
	public function dismiss_first_time_notice() {
1250
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
1251
1252
		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
1253
			return;
1254
		}
1255
1256
		monsterinsights_update_option( 'monsterinsights_first_run_notice', true );
1257
1258
		wp_send_json_success();
1259
	}
1260
1261
	/**
1262
	 * Get the notice status by id.
1263
	 */
1264
	public function get_notice_status() {
1265
1266
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
1267
1268
		$notice_id = empty( $_POST['notice'] ) ? false : sanitize_text_field( wp_unslash( $_POST['notice'] ) );
1269
		if ( ! $notice_id ) {
1270
			wp_send_json_error();
1271
		}
1272
		$is_dismissed = MonsterInsights()->notices->is_dismissed( $notice_id );
1273
1274
		wp_send_json_success( array(
1275
			'dismissed' => $is_dismissed,
1276
		) );
1277
	}
1278
1279
	/**
1280
	 * Dismiss notices by id.
1281
	 */
1282
	public function dismiss_notice() {
1283
1284
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
1285
1286
		$notice_id = empty( $_POST['notice'] ) ? false : sanitize_text_field( wp_unslash( $_POST['notice'] ) );
1287
		if ( ! $notice_id ) {
1288
			wp_send_json_error();
1289
		}
1290
		MonsterInsights()->notices->dismiss( $notice_id );
1291
1292
		wp_send_json_success();
1293
	}
1294
1295
	/**
1296
	 * Retrieve posts/pages
1297
	 *
1298
	 * @access admin
1299
	 * @since 3.0.0
1300
	 */
1301
	public function get_posts() {
1302
1303
		// Run a security check first.
1304
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
1305
1306
		$post_type = isset( $_POST['post_type'] ) ? sanitize_text_field( wp_unslash( $_POST['post_type'] ) ) : 'any';
1307
1308
		$already_added = monsterinsights_get_option('popular_posts_inline_curated', []);
1309
		$exclude = array();
1310
		if( is_array( $already_added ) && !empty( $already_added ) ){
1311
			foreach ( $already_added as $key => $value ) {
1312
				$exclude[$value['id']] = $value['id'];
1313
			}
1314
		}
1315
1316
		$exclude = array_unique(array_values($exclude));
1317
1318
		$args = array(
1319
			's'              => isset( $_POST['keyword'] ) ? sanitize_text_field( wp_unslash( $_POST['keyword'] ) ) : '',
1320
			'post_type'      => $post_type,
1321
			'posts_per_page' => isset( $_POST['numberposts'] ) ? sanitize_text_field( wp_unslash( $_POST['numberposts'] ) ) : 25,
1322
			'orderby'        => 'post_title',
1323
			'order'          => 'ASC',
1324
			'post__not_in'   => $exclude,
1325
		);
1326
1327
		$array = array();
1328
		$posts = get_posts( $args );
1329
1330
		if ( in_array( $post_type, array( 'page', 'any' ), true ) ) {
1331
			$homepage = get_option( 'page_on_front' );
1332
			if ( ! $homepage ) {
1333
				$array[] = array(
1334
					'id'    => - 1,
1335
					'title' => __( 'Homepage', 'google-analytics-for-wordpress' ),
1336
				);
1337
			}
1338
		}
1339
1340
		if ( $posts ) {
1341
			foreach ( $posts as $post ) {
1342
				$array[] = array(
1343
					'id'    => $post->ID,
1344
					'title' => $post->post_title,
1345
				);
1346
			}
1347
		}
1348
1349
		wp_send_json_success( $array );
1350
	}
1351
1352
	/**
1353
	 * Search for taxonomy terms.
1354
	 *
1355
	 * @access admin
1356
	 * @since 3.0.0
1357
	 */
1358
	public function get_taxonomy_terms() {
1359
1360
		// Run a security check first.
1361
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
1362
1363
		$keyword  = isset( $_POST['keyword'] ) ? sanitize_text_field( wp_unslash( $_POST['keyword'] ) ) : '';
1364
		$taxonomy = isset( $_POST['taxonomy'] ) ? sanitize_text_field( wp_unslash( $_POST['taxonomy'] ) ) : 'category';
1365
1366
		$args = array(
1367
			'taxonomy'   => array( $taxonomy ),
1368
			'hide_empty' => false,
1369
			'name__like' => $keyword,
1370
		);
1371
1372
		$terms = get_terms( $args );
1373
		$array = array();
1374
1375
		if ( ! empty( $terms ) ) {
1376
			foreach ( $terms as $term ) {
1377
				$array[] = array(
1378
					'id'   => esc_attr( $term->term_id ),
1379
					'text' => esc_attr( $term->name ),
1380
				);
1381
			}
1382
		}
1383
1384
		wp_send_json_success( $array );
1385
	}
1386
1387
	/**
1388
	 * Get the post types in a name => Label array.
1389
	 */
1390
	public function get_post_types() {
1391
1392
		// Run a security check first.
1393
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
1394
1395
		$post_types_args = array(
1396
			'public' => true,
1397
		);
1398
		$post_types      = get_post_types( $post_types_args, 'objects' );
1399
1400
		$post_types_parsed = array();
1401
1402
		foreach ( $post_types as $post_type ) {
1403
			// Exclude post types that don't support the content editor.
1404
			// Exclude the WooCommerce product post type as that doesn't use the "the_content" filter and we can't auto-add popular posts to it.
1405
			if ( ! post_type_supports( $post_type->name, 'editor' ) || 'product' === $post_type->name ) {
1406
				continue;
1407
			}
1408
			$post_types_parsed[ $post_type->name ] = $post_type->labels->singular_name;
1409
		}
1410
1411
		$post_types_parsed = apply_filters( 'monsterinsights_vue_post_types_editor', $post_types_parsed );
1412
1413
		wp_send_json( $post_types_parsed );
1414
1415
	}
1416
1417
1418
	public function check_popular_posts_report() {
1419
1420
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
1421
1422
		if ( ! current_user_can( 'monsterinsights_view_dashboard' ) ) {
1423
			// Translators: Link tag starts with url and link tag ends.
1424
			$message = sprintf(
1425
				esc_html__( 'Oops! You don not have permissions to view or access Popular Posts. Please check with your site administrator that your role is included in the MonsterInsights permissions settings. %1$sClick here for more information%2$s.', 'google-analytics-for-wordpress' ),
1426
				'<a target="_blank" href="' . monsterinsights_get_url( 'notice', 'cannot-view-dashboard', 'https://www.monsterinsights.com/docs/how-to-allow-user-roles-to-access-the-monsterinsights-reports-and-settings/' ) . '">',
1427
				'</a>'
1428
			);
1429
			wp_send_json_error( array( 'message' => $message ) );
1430
		}
1431
1432
		if ( ! empty( $_REQUEST['isnetwork'] ) && $_REQUEST['isnetwork'] ) {
1433
			define( 'WP_NETWORK_ADMIN', true );
1434
		}
1435
		$settings_page = admin_url( 'admin.php?page=monsterinsights_settings' );
1436
1437
		// Only for Pro users, require a license key to be entered first so we can link to things.
1438
		if ( monsterinsights_is_pro_version() ) {
1439
			if ( ! MonsterInsights()->license->is_site_licensed() && ! MonsterInsights()->license->is_network_licensed() ) {
1440
				$url = admin_url( 'admin.php?page=monsterinsights_settings#/' );
1441
1442
				// Check for MS dashboard
1443
				if ( is_network_admin() ) {
1444
					$url = network_admin_url( 'admin.php?page=monsterinsights_settings#/' );
1445
				}
1446
				// Translators: Setting page link tag starts with url and Setting page link tag ends.
1447
				$message = sprintf(
1448
					esc_html__( 'Oops! We could not find a valid license key for MonsterInsights. Please %1$senter a valid license key%2$s to view this report.', 'google-analytics-for-wordpress' ),
1449
					'<a href="' . esc_url( $url ) . '">',
1450
					'</a>'
1451
				);
1452
				wp_send_json_error( array(
1453
					'message' => $message,
1454
					'footer'  => '<a href="' . $settings_page . '">' . __( 'Add your license', 'google-analytics-for-wordpress' ) . '</a>',
1455
				) );
1456
			} else if ( MonsterInsights()->license->is_site_licensed() && ! MonsterInsights()->license->site_license_has_error() ) {
1457
				// Good to go: site licensed.
1458
			} else if ( MonsterInsights()->license->is_network_licensed() && ! MonsterInsights()->license->network_license_has_error() ) {
1459
				// Good to go: network licensed.
1460
			} else {
1461
				// Translators: Account page link tag starts with url and Account page link tag ends.
1462
				$message = sprintf(
1463
					esc_html__( 'Oops! We could not find a valid license key. Please enter a valid license key to view this report. You can find your license by logging into your %1$sMonsterInsights account%2$s.', 'google-analytics-for-wordpress' ),
1464
					'<a target="_blank" href="' . monsterinsights_get_url( 'notice', 'license-errors', 'https://www.monsterinsights.com/my-account/licenses/' ) . '">',
1465
					'</a>'
1466
				);
1467
				wp_send_json_error( array( 'message' => $message ) );
1468
			}
1469
		}
1470
1471
		// We do not have a current auth.
1472
		$site_auth = MonsterInsights()->auth->get_viewname();
1473
		$ms_auth   = is_multisite() && MonsterInsights()->auth->get_network_viewname();
1474
		if ( ! $site_auth && ! $ms_auth ) {
1475
			$url = admin_url( 'admin.php?page=monsterinsights_settings#/' );
1476
1477
			// Check for MS dashboard
1478
			if ( is_network_admin() ) {
1479
				$url = network_admin_url( 'admin.php?page=monsterinsights_settings#/' );
1480
			}
1481
			// Translators: Wizard page link tag starts with url and Wizard page link tag ends.
1482
			$message = sprintf(
1483
				esc_html__( 'You need to authenticate into MonsterInsights before viewing reports. Please complete the setup by going through our %1$ssetup wizard%2$s.', 'google-analytics-for-wordpress' ),
1484
				'<a href="' . esc_url( $url ) . '">',
1485
				'</a>'
1486
			);
1487
			wp_send_json_error( array( 'message' => $message ) );
1488
		}
1489
1490
		$report_name = 'popularposts';
1491
1492
		if ( empty( $report_name ) ) {
1493
			// Translators: Support link tag starts with url and Support link tag ends.
1494
			$message = sprintf(
1495
				esc_html__( 'Oops! We encountered an error while generating your reports. Please wait a few minutes and try again. If the issue persists, please %1$scontact our support%2$s team.', 'google-analytics-for-wordpress' ),
1496
				'<a target="_blank" href="' . monsterinsights_get_url( 'notice', 'cannot-generate-reports', 'https://www.monsterinsights.com/my-account/support/' ) . '">',
1497
				'</a>'
1498
			);
1499
			wp_send_json_error( array( 'message' => $message ) );
1500
		}
1501
1502
		$report = MonsterInsights()->reporting->get_report( $report_name );
1503
1504
		$isnetwork = ! empty( $_REQUEST['isnetwork'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['isnetwork'] ) ) : '';
1505
		$start     = ! empty( $_POST['start'] ) ? sanitize_text_field( wp_unslash( $_POST['start'] ) ) : $report->default_start_date();
1506
		$end       = ! empty( $_POST['end'] ) ? sanitize_text_field( wp_unslash( $_POST['end'] ) ) : $report->default_end_date();
1507
1508
		$args = array(
1509
			'start' => $start,
1510
			'end'   => $end,
1511
		);
1512
1513
		if ( $isnetwork ) {
1514
			$args['network'] = true;
1515
		}
1516
1517
		if ( monsterinsights_is_pro_version() && ! MonsterInsights()->license->license_can( $report->level ) ) {
1518
			$data = array(
1519
				'success' => false,
1520
				'error'   => 'license_level',
1521
			);
1522
		} else {
1523
			$data = apply_filters( 'monsterinsights_vue_reports_data', $report->get_data( $args ), $report_name, $report );
1524
		}
1525
1526
		if ( ! empty( $data['success'] ) && ! empty( $data['data'] ) ) {
1527
			wp_send_json_success( $data['data'] );
1528
		} else if ( isset( $data['success'] ) && false === $data['success'] && ! empty( $data['error'] ) ) {
1529
			// Use a custom handler for invalid_grant errors.
1530
			if ( strpos( $data['error'], 'invalid_grant' ) > 0 ) {
1531
				wp_send_json_error(
1532
					array(
1533
						'message' => 'invalid_grant',
1534
						'footer'  => '',
1535
					)
1536
				);
1537
			}
1538
1539
			wp_send_json_error(
1540
				array(
1541
					'message' => $data['error'],
1542
					'footer'  => isset( $data['data']['footer'] ) ? $data['data']['footer'] : '',
1543
				)
1544
			);
1545
		}
1546
1547
		// Translators: Support link tag starts with url and Support link tag ends.
1548
		$message = sprintf(
1549
			__( 'Oops! We encountered an error while generating your reports. Please wait a few minutes and try again. If the issue persists, please %1$scontact our support%2$s team.', 'google-analytics-for-wordpress' ),
1550
			'<a target="_blank" href="' . monsterinsights_get_url( 'notice', 'cannot-generate-reports', 'https://www.monsterinsights.com/my-account/support/' ) . '">',
1551
			'</a>'
1552
		);
1553
		wp_send_json_error( array( 'message' => $message ) );
1554
	}
1555
1556
	/**
1557
	 * Ajax handler for popular posts theme customization settings.
1558
	 * Specific theme styles are stored separately so we can handle 20+ themes with their specific settings.
1559
	 */
1560
	public function update_popular_posts_theme_setting() {
1561
1562
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
1563
1564
		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
1565
			return;
1566
		}
1567
1568
		if ( ! empty( $_POST['type'] ) && ! empty( $_POST['theme'] ) && ! empty( $_POST['object'] ) && ! empty( $_POST['key'] ) && ! empty( $_POST['value'] ) ) {
1569
			$settings_key = 'monsterinsights_popular_posts_theme_settings';
1570
			$type         = sanitize_text_field( wp_unslash( $_POST['type'] ) ); // Type of Popular Posts instance: inline/widget/products.
1571
			$theme        = sanitize_text_field( wp_unslash( $_POST['theme'] ) );
1572
			$object       = sanitize_text_field( wp_unslash( $_POST['object'] ) ); // Style object like title, label, background, etc.
1573
			$key          = sanitize_text_field( wp_unslash( $_POST['key'] ) ); // Style key for the object like color, font size, etc.
1574
			$value        = sanitize_text_field( wp_unslash( $_POST['value'] ) ); // Value of custom style like 12px or #fff.
1575
			$settings     = get_option( $settings_key, array() );
1576
1577
			if ( ! isset( $settings[ $type ] ) ) {
1578
				$settings[ $type ] = array();
1579
			}
1580
			if ( ! isset( $settings[ $type ][ $theme ] ) ) {
1581
				$settings[ $type ][ $theme ] = array();
1582
			}
1583
1584
			if ( ! isset( $settings[ $type ][ $theme ][ $object ] ) ) {
1585
				$settings[ $type ][ $theme ][ $object ] = array();
1586
			}
1587
1588
			$settings[ $type ][ $theme ][ $object ][ $key ] = $value;
1589
1590
			update_option( $settings_key, $settings );
1591
1592
			wp_send_json_success();
1593
		}
1594
1595
		wp_send_json_error();
1596
1597
	}
1598
1599
	/**
1600
	 * Import site notes from exported file.
1601
	 */
1602
	private function import_site_notes( $site_notes ) {
1603
		$notes_db = new MonsterInsights_Site_Notes_DB_Base();
1604
1605
		// Import site-notes category.
1606
		foreach ( $site_notes['categories'] as $category ) {
1607
			$notes_db->create_category( array(
1608
				'name'             => $category['name'],
1609
				'background_color' => $category['color'],
1610
			) );
1611
		}
1612
1613
		foreach ( $site_notes['notes'] as $notes ) {
1614
			$category = get_term_by( 'name', $notes['category_name'], 'monsterinsights_note_category' );
1615
1616
			$notes_db->create( array(
1617
				'note'      => $notes['note_title'],
1618
				'date'      => $notes['note_date'],
1619
				'important' => $notes['important'],
1620
				'category'  => intval( ( ! empty( $category ) && ! empty( $category->term_id ) ) ? $category->term_id : 0 ),
1621
			) );
1622
		}
1623
	}
1624
}
1625