947 lines
37 KiB
PHP
947 lines
37 KiB
PHP
<?php
|
|
/**
|
|
* WP ADMIN assets will be enqueued here.
|
|
*
|
|
* @package monsterinsights
|
|
*/
|
|
|
|
/**
|
|
* Class MonsterInsights_Admin_Assets
|
|
* This class is responsible for load CSS and JS in admin panel.
|
|
*/
|
|
class MonsterInsights_Admin_Assets {
|
|
/**
|
|
* MonsterInsights handles.
|
|
*/
|
|
private $own_handles = array(
|
|
'monsterinsights-vue-script',
|
|
// 'monsterinsights-vue-frontend',
|
|
'monsterinsights-vue-reports',
|
|
'monsterinsights-vue-widget',
|
|
// Vue 3 handles (type=module)
|
|
'monsterinsights-vue3-custom-dashboard',
|
|
'monsterinsights-vue3-reports',
|
|
);
|
|
|
|
/**
|
|
* Store manifest.json file content.
|
|
*
|
|
* @var array
|
|
*/
|
|
private static $manifest_data;
|
|
|
|
/**
|
|
* Directory path of assets.
|
|
*/
|
|
private $version_path;
|
|
|
|
/**
|
|
* Store Vue 3 manifest.json file content.
|
|
*
|
|
* @var array
|
|
*/
|
|
private static $manifest_data_v3;
|
|
|
|
/**
|
|
* Class constructor.
|
|
*/
|
|
public function __construct() {
|
|
global $wp_version;
|
|
// This filter will only run if WP version is greater than 6.4.0.
|
|
if ( version_compare( $wp_version, '6.4', '>=' ) ) {
|
|
add_filter( 'wp_script_attributes', array( $this, 'set_scripts_as_type_module' ), 99999 );
|
|
} else {
|
|
// Use script_loader_tag if WordPress version is lower than 5.7.0.
|
|
add_filter( 'script_loader_tag', array( $this, 'script_loader_tag' ), 99999, 3 );
|
|
}
|
|
|
|
add_action( 'admin_enqueue_scripts', array( $this, 'admin_styles' ) );
|
|
|
|
add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
|
|
$this->get_manifest_data();
|
|
|
|
// CSS files path.
|
|
$this->version_path = monsterinsights_is_pro_version() ? 'pro' : 'lite';
|
|
|
|
$this->get_manifest_data_v3();
|
|
}
|
|
|
|
/**
|
|
* Updates the script type for the plugin's handles to type module.
|
|
*
|
|
* @param array $attrs Key-value pairs representing <script> tag attributes.
|
|
* @return array $attrs
|
|
*/
|
|
public function set_scripts_as_type_module( $attrs ) {
|
|
if ( isset( $attrs['id'] ) && in_array( str_replace( '-js', '', $attrs['id'] ), $this->own_handles, true ) ) {
|
|
$attrs['type'] = 'module';
|
|
}
|
|
return $attrs;
|
|
}
|
|
|
|
/**
|
|
* Update script tag.
|
|
* The vue code needs type=module.
|
|
*/
|
|
public function script_loader_tag( $tag, $handle, $src ) {
|
|
|
|
if ( ! in_array( $handle, $this->own_handles ) ) {
|
|
return $tag;
|
|
}
|
|
|
|
// Change the script tag by adding type="module" and return it.
|
|
$html = str_replace( '></script>', ' type="module"></script>', $tag );
|
|
|
|
$domain = monsterinsights_is_pro_version() ? 'google-analytics-premium' : 'google-analytics-for-wordpress';
|
|
$html = monsterinsights_get_printable_translations( $domain ) . $html;
|
|
|
|
return $html;
|
|
}
|
|
|
|
/**
|
|
* Loads styles for all MonsterInsights-based Administration Screens.
|
|
*
|
|
* @return null Return early if not on the proper screen.
|
|
*/
|
|
public function admin_styles() {
|
|
|
|
$suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
|
|
|
|
// Load Common admin styles.
|
|
wp_register_style( 'monsterinsights-admin-common-style', plugins_url( 'assets/css/admin-common' . $suffix . '.css', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version() );
|
|
wp_enqueue_style( 'monsterinsights-admin-common-style' );
|
|
|
|
wp_enqueue_style(
|
|
'monsterinsights-admin-common-build',
|
|
plugins_url( $this->version_path . '/assets/vue/css/admin.css', MONSTERINSIGHTS_PLUGIN_FILE ),
|
|
array(),
|
|
monsterinsights_get_asset_version()
|
|
);
|
|
|
|
// Get current screen.
|
|
$screen = get_current_screen();
|
|
|
|
// Bail if we're not on a MonsterInsights screen.
|
|
if ( empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) === false ) {
|
|
return;
|
|
}
|
|
|
|
// If this is a Vue 3 page, enqueue only Vue 3 styles and return early.
|
|
if ( $this->is_vue3_admin_page() ) {
|
|
// In dev mode, Vite injects CSS via JS; skip manual CSS enqueues.
|
|
if ( ! defined( 'MONSTERINSIGHTS_V3_DEV_URL' ) || ! MONSTERINSIGHTS_V3_DEV_URL ) {
|
|
// Map each Vue 3 page slug to its entry point.
|
|
$page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : '';
|
|
$entry_key = $this->get_vue3_entry_key( $page );
|
|
|
|
$this->enqueue_vue3_entry_css( $entry_key );
|
|
}
|
|
return;
|
|
}
|
|
|
|
// For the settings pages, load the Vue app scripts.
|
|
if ( monsterinsights_is_settings_page() ) {
|
|
if ( ! defined( 'MONSTERINSIGHTS_LOCAL_JS_URL' ) ) {
|
|
$this->enqueue_script_specific_css( 'src/modules/settings/settings.js' );
|
|
}
|
|
|
|
// Don't load other scripts on the settings page.
|
|
return;
|
|
}
|
|
|
|
// For the report pages, load the Vue app scripts.
|
|
if ( monsterinsights_is_reports_page() ) {
|
|
if ( ! defined( 'MONSTERINSIGHTS_LOCAL_JS_URL' ) ) {
|
|
$this->enqueue_script_specific_css( 'src/modules/reports/reports.js' );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// Tooltips
|
|
wp_enqueue_script( 'jquery-ui-tooltip' );
|
|
}
|
|
|
|
/**
|
|
* Loads scripts for all MonsterInsights-based Administration Screens.
|
|
*
|
|
* @return null Return early if not on the proper screen.
|
|
*/
|
|
public function admin_scripts() {
|
|
|
|
// Our Common Admin JS.
|
|
$suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
|
|
|
|
wp_enqueue_script( 'monsterinsights-admin-common-script', plugins_url( 'assets/js/admin-common' . $suffix . '.js', MONSTERINSIGHTS_PLUGIN_FILE ), array( 'jquery' ), monsterinsights_get_asset_version(), true );
|
|
|
|
wp_localize_script(
|
|
'monsterinsights-admin-common-script',
|
|
'monsterinsights_admin_common',
|
|
array(
|
|
'ajax' => admin_url( 'admin-ajax.php' ),
|
|
'dismiss_notice_nonce' => wp_create_nonce( 'monsterinsights-dismiss-notice' ),
|
|
)
|
|
);
|
|
|
|
// Flush Vue 3 localStorage cache registry if flagged (e.g. after Google re-auth).
|
|
if ( get_transient( 'monsterinsights_flush_cache_registry' ) ) {
|
|
delete_transient( 'monsterinsights_flush_cache_registry' );
|
|
wp_add_inline_script(
|
|
'monsterinsights-admin-common-script',
|
|
'try{localStorage.removeItem("mi_cache_registry")}catch(e){}',
|
|
'before'
|
|
);
|
|
}
|
|
|
|
// Load setup wizard handler script for all admin pages where the setup wizard link might appear
|
|
// This includes MonsterInsights pages and any admin page where the setup notice might show
|
|
wp_enqueue_script( 'monsterinsights-admin-setup-wizard', plugins_url( 'assets/js/admin-setup-wizard.js', MONSTERINSIGHTS_PLUGIN_FILE ), array( 'jquery' ), monsterinsights_get_asset_version(), true );
|
|
|
|
wp_localize_script(
|
|
'monsterinsights-admin-setup-wizard',
|
|
'monsterinsights',
|
|
array(
|
|
'ajax' => admin_url( 'admin-ajax.php' ),
|
|
'nonce' => wp_create_nonce( 'mi-admin-nonce' ),
|
|
)
|
|
);
|
|
|
|
// Get current screen.
|
|
$screen = get_current_screen();
|
|
|
|
// Bail if we're not on a MonsterInsights screen for other scripts.
|
|
if ( empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) === false ) {
|
|
return;
|
|
}
|
|
|
|
$version_path = monsterinsights_is_pro_version() ? 'pro' : 'lite';
|
|
$text_domain = monsterinsights_is_pro_version() ? 'google-analytics-premium' : 'google-analytics-for-wordpress';
|
|
|
|
$license = MonsterInsights()->license;
|
|
$license_info = array(
|
|
'type' => $license->get_license_type(),
|
|
'is_agency' => $license->is_agency(),
|
|
);
|
|
|
|
// Get auth data (shared across Vue 2 and Vue 3 apps)
|
|
$auth = MonsterInsights()->auth;
|
|
$auth_data = array(
|
|
'v4' => $auth->get_v4_id(),
|
|
'network_v4' => is_multisite() ? $auth->get_network_v4_id() : '',
|
|
'manual_v4' => $auth->get_manual_v4_id(),
|
|
'network_manual_v4' => is_multisite() ? $auth->get_network_manual_v4_id() : '',
|
|
'viewname' => $auth->get_viewname(),
|
|
'network_viewname' => is_multisite() ? $auth->get_network_viewname() : '',
|
|
'measurement_protocol_secret' => $auth->get_measurement_protocol_secret(),
|
|
'network_measurement_protocol_secret' => is_multisite() ? $auth->get_network_measurement_protocol_secret() : '',
|
|
);
|
|
|
|
// If this is a Vue 3 page, enqueue only Vue 3 script and return early.
|
|
if ( $this->is_vue3_admin_page() ) {
|
|
if(strpos($screen->id, 'monsterinsights_overview_report') !== false) {
|
|
$this->load_vue3_report_script($auth, $auth_data, $license_info, $version_path);
|
|
return;
|
|
}
|
|
|
|
$handle = 'monsterinsights-vue3-custom-dashboard';
|
|
|
|
if ( defined( 'MONSTERINSIGHTS_V3_DEV_URL' ) && MONSTERINSIGHTS_V3_DEV_URL ) {
|
|
$dev_url = trailingslashit( MONSTERINSIGHTS_V3_DEV_URL ) . 'src/modules/custom-dashboard/main.js';
|
|
wp_register_script( $handle, $dev_url, array( 'wp-i18n', 'wp-util' ), monsterinsights_get_asset_version(), true );
|
|
wp_enqueue_script( $handle );
|
|
} else {
|
|
list( $base_url, $entry ) = $this->get_vue3_entry( 'src/modules/custom-dashboard/main.js' );
|
|
if ( ! empty( $entry['file'] ) ) {
|
|
$src = $base_url . ltrim( $entry['file'], '/' );
|
|
wp_register_script( $handle, $src, array( 'wp-i18n', 'wp-util' ), monsterinsights_get_asset_version(), true );
|
|
wp_enqueue_script( $handle );
|
|
}
|
|
}
|
|
|
|
// Provide bootstrap payload for the Vue 3 app in build
|
|
$site_auth = $auth->get_viewname();
|
|
$ms_auth = is_multisite() && $auth->get_network_viewname();
|
|
|
|
// Get bearer token for direct browser-to-API requests.
|
|
$bearer_token_data = MonsterInsights_API_Token::get_token( is_network_admin() );
|
|
$bearer_token = '';
|
|
$bearer_expires = 0;
|
|
if ( ! is_wp_error( $bearer_token_data ) ) {
|
|
$bearer_token = $bearer_token_data['token'];
|
|
$bearer_expires = $bearer_token_data['expires_at'];
|
|
}
|
|
|
|
wp_localize_script(
|
|
$handle,
|
|
'monsterinsights',
|
|
array(
|
|
'ajax' => admin_url( 'admin-ajax.php' ),
|
|
'assets_url' => apply_filters( 'monsterinsights_vue3_assets_url', plugins_url( $version_path . '/assets/vue3', MONSTERINSIGHTS_PLUGIN_FILE ) ),
|
|
'nonce' => wp_create_nonce( 'mi-admin-nonce' ),
|
|
'cd_nonce' => wp_create_nonce( 'mi_custom_dashboard_ajax_nonce' ), // Custom Dashboard nonce
|
|
'network' => is_network_admin(),
|
|
'custom_dashboard_url' => add_query_arg( 'page', 'monsterinsights_custom_dashboard', admin_url( 'admin.php' ) ),
|
|
'license' => $license_info,
|
|
'auth' => $auth_data,
|
|
'authed' => $site_auth || $ms_auth, // Boolean for admin bar compatibility
|
|
'plugin_version' => MONSTERINSIGHTS_VERSION,
|
|
'wizard_url' => monsterinsights_get_onboarding_url(),
|
|
'rest_url' => get_rest_url(),
|
|
'rest_nonce' => wp_create_nonce( 'wp_rest' ),
|
|
// Direct API access (bypasses WordPress for performance).
|
|
'relay_api_url' => apply_filters( 'monsterinsights_api_url_custom_dashboard', 'https://app.monsterinsights.com/' ),
|
|
'bearer_token' => $bearer_token,
|
|
'bearer_expires' => $bearer_expires,
|
|
// Sample data mode: when true, frontend should bypass direct API and use WP AJAX for sample data.
|
|
'sample_data_enabled' => apply_filters( 'monsterinsights_sample_data_enabled', false ),
|
|
'can_view_reports' => current_user_can( 'monsterinsights_view_dashboard' ),
|
|
'update_settings' => current_user_can( 'monsterinsights_save_settings' ),
|
|
)
|
|
);
|
|
|
|
// Load translations for Vue 3 app using WordPress's script translation system
|
|
wp_set_script_translations( $handle, 'google-analytics-for-wordpress' );
|
|
|
|
return;
|
|
}
|
|
|
|
// For the settings page, load the Vue app.
|
|
if ( monsterinsights_is_settings_page() ) {
|
|
$app_js_url = self::get_js_url( 'src/modules/settings/settings.js' );
|
|
wp_register_script( 'monsterinsights-vue-script', $app_js_url, array( 'wp-i18n' ), monsterinsights_get_asset_version(), true );
|
|
wp_enqueue_script( 'monsterinsights-vue-script' );
|
|
|
|
$plugins = get_plugins();
|
|
$install_amp_url = false;
|
|
if ( monsterinsights_can_install_plugins() ) {
|
|
$amp_key = 'amp/amp.php';
|
|
if ( array_key_exists( $amp_key, $plugins ) ) {
|
|
$install_amp_url = wp_nonce_url( self_admin_url( 'plugins.php?action=activate&plugin=' . $amp_key ), 'activate-plugin_' . $amp_key );
|
|
} else {
|
|
$install_amp_url = wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=amp' ), 'install-plugin_amp' );
|
|
}
|
|
}
|
|
|
|
$install_woocommerce_url = false;
|
|
if ( monsterinsights_can_install_plugins() ) {
|
|
$woo_key = 'woocommerce/woocommerce.php';
|
|
if ( array_key_exists( $woo_key, $plugins ) ) {
|
|
$install_woocommerce_url = wp_nonce_url( self_admin_url( 'plugins.php?action=activate&plugin=' . $woo_key ), 'activate-plugin_' . $woo_key );
|
|
} else {
|
|
$install_woocommerce_url = wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=woocommerce' ), 'install-plugin_woocommerce' );
|
|
}
|
|
}
|
|
|
|
$prepared_dimensions = array();
|
|
if ( class_exists( 'MonsterInsights_Admin_Custom_Dimensions' ) ) {
|
|
$dimensions = new MonsterInsights_Admin_Custom_Dimensions();
|
|
$dimensions = $dimensions->custom_dimensions();
|
|
$prepared_dimensions = array();
|
|
foreach ( $dimensions as $dimension_type => $dimension ) {
|
|
$dimension['type'] = $dimension_type;
|
|
$prepared_dimensions[] = $dimension;
|
|
}
|
|
}
|
|
|
|
$is_authed = ( MonsterInsights()->auth->is_authed() || MonsterInsights()->auth->is_network_authed() );
|
|
|
|
wp_localize_script(
|
|
'monsterinsights-vue-script',
|
|
'monsterinsights',
|
|
array(
|
|
'ajax' => admin_url( 'admin-ajax.php' ),
|
|
'nonce' => wp_create_nonce( 'mi-admin-nonce' ),
|
|
'network' => is_network_admin(),
|
|
'assets' => plugins_url( $version_path . '/assets/vue', MONSTERINSIGHTS_PLUGIN_FILE ),
|
|
'roles' => monsterinsights_get_roles(),
|
|
'roles_manage_options' => monsterinsights_get_manage_options_roles(),
|
|
'shareasale_id' => monsterinsights_get_shareasale_id(),
|
|
'shareasale_url' => monsterinsights_get_shareasale_url( monsterinsights_get_shareasale_id(), '' ),
|
|
'addons_url' => is_multisite() ? network_admin_url( 'admin.php?page=monsterinsights_network#/addons' ) : admin_url( 'admin.php?page=monsterinsights_settings#/addons' ),
|
|
'seo_settings_page_url' => is_multisite() ? network_admin_url( 'admin.php?page=monsterinsights_network#/seo' ) : admin_url( 'admin.php?page=monsterinsights_settings#/seo' ),
|
|
'aioseo_dashboard_url' => is_multisite() ? network_admin_url( 'admin.php?page=aioseo' ) : admin_url( 'admin.php?page=aioseo' ),
|
|
'wp_plugins_page_url' => is_multisite() ? network_admin_url( 'plugins.php' ) : admin_url( 'plugins.php' ),
|
|
'email_summary_url' => admin_url( 'admin.php?monsterinsights_email_preview&monsterinsights_email_template=summary' ),
|
|
'install_amp_url' => $install_amp_url,
|
|
'install_woo_url' => $install_woocommerce_url,
|
|
'dimensions' => $prepared_dimensions,
|
|
'install_plugins' => monsterinsights_can_install_plugins(),
|
|
'unfiltered_html' => current_user_can( 'unfiltered_html' ),
|
|
'activate_nonce' => wp_create_nonce( 'monsterinsights-activate' ),
|
|
'deactivate_nonce' => wp_create_nonce( 'monsterinsights-deactivate' ),
|
|
'install_nonce' => wp_create_nonce( 'monsterinsights-install' ),
|
|
// Used to add notices for future deprecations.
|
|
'versions' => monsterinsights_get_php_wp_version_warning_data(),
|
|
'plugin_version' => MONSTERINSIGHTS_VERSION,
|
|
'is_admin' => true,
|
|
'admin_email' => get_option( 'admin_email' ),
|
|
'site_url' => get_site_url(),
|
|
'site_name' => get_bloginfo( 'name' ),
|
|
'reports_url' => add_query_arg( 'page', 'monsterinsights_overview_report', admin_url( 'admin.php' ) ),
|
|
'landing_pages_top_reports_url' => add_query_arg( 'page', 'monsterinsights_reports#/top-landing-pages', admin_url( 'admin.php' ) ),
|
|
'custom_view_url' => add_query_arg( 'page', 'monsterinsights_custom_dashboard', admin_url( 'admin.php' ) ),
|
|
'ecommerce_report_url' => add_query_arg( 'page', 'monsterinsights_reports#/ecommerce', admin_url( 'admin.php' ) ),
|
|
'ecommerce_settings_tab_url' => add_query_arg( 'page', 'monsterinsights_settings#/ecommerce', admin_url( 'admin.php' ) ),
|
|
'first_run_notice' => apply_filters( 'monsterinsights_settings_first_time_notice_hide', monsterinsights_get_option( 'monsterinsights_first_run_notice' ) ),
|
|
'getting_started_url' => is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_network#/about' ) : admin_url( 'admin.php?page=monsterinsights_settings#/about/getting-started' ),
|
|
'authed' => $is_authed,
|
|
'new_pretty_link_url' => admin_url( 'post-new.php?post_type=pretty-link' ),
|
|
'wpmailsmtp_admin_url' => admin_url( 'admin.php?page=wp-mail-smtp' ),
|
|
'load_headline_analyzer_settings' => monsterinsights_load_gutenberg_app() ? 'true' : 'false',
|
|
'exit_url' => add_query_arg( 'page', 'monsterinsights_settings', admin_url( 'admin.php' ) ),
|
|
'timezone' => date( 'e' ), // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date -- We need this to depend on the runtime timezone.
|
|
'funnelkit_stripe_woo_page_url' => admin_url( 'admin.php?page=wc-settings&tab=fkwcs_api_settings' ),
|
|
'funnelkit_stripe_woo_nonce' => wp_create_nonce( 'monsterinsights-funnelkit-stripe-woo-nonce' ),
|
|
'site_notes_export_synced' => monsterinsights_get_option( 'site_notes_export_synced', 0 ),
|
|
'site_notes_import_synced' => monsterinsights_get_option( 'site_notes_import_synced', 0 ),
|
|
'license' => $license_info,
|
|
'currency' => monsterinsights_get_ecommerce_currency(),
|
|
)
|
|
);
|
|
|
|
wp_scripts()->add_inline_script(
|
|
'monsterinsights-vue-script',
|
|
monsterinsights_get_printable_translations( $text_domain ),
|
|
'translation'
|
|
);
|
|
|
|
// Don't load other scripts on the settings page.
|
|
return;
|
|
}
|
|
|
|
// For the report pages, load the Vue app.
|
|
if ( monsterinsights_is_reports_page() ) {
|
|
|
|
$app_js_url = self::get_js_url( 'src/modules/reports/reports.js' );
|
|
wp_register_script( 'monsterinsights-vue-reports', $app_js_url, array( 'wp-i18n' ), monsterinsights_get_asset_version(), true );
|
|
wp_enqueue_script( 'monsterinsights-vue-reports' );
|
|
|
|
// We do not have a current auth.
|
|
$auth = MonsterInsights()->auth;
|
|
$site_auth = $auth->get_viewname();
|
|
$ms_auth = is_multisite() && $auth->get_network_viewname();
|
|
|
|
// Localize the script with the necessary data.
|
|
wp_localize_script(
|
|
'monsterinsights-vue-reports',
|
|
'monsterinsights',
|
|
array(
|
|
'ajax' => admin_url( 'admin-ajax.php' ),
|
|
'nonce' => wp_create_nonce( 'mi-admin-nonce' ),
|
|
'rest_nonce' => wp_create_nonce( 'wp_rest' ),
|
|
'rest_url' => get_rest_url(),
|
|
'network' => is_network_admin(),
|
|
'assets' => plugins_url( $version_path . '/assets/vue', MONSTERINSIGHTS_PLUGIN_FILE ),
|
|
'pro_assets' => plugins_url( $version_path . '/assets', MONSTERINSIGHTS_PLUGIN_FILE ),
|
|
'shareasale_id' => monsterinsights_get_shareasale_id(),
|
|
'shareasale_url' => monsterinsights_get_shareasale_url( monsterinsights_get_shareasale_id(), '' ),
|
|
'addons_url' => is_multisite() ? network_admin_url( 'admin.php?page=monsterinsights_network#/addons' ) : admin_url( 'admin.php?page=monsterinsights_settings#/addons' ),
|
|
'timezone' => date('e'), // phpcs:ignore
|
|
'authed' => $site_auth || $ms_auth,
|
|
'settings_url' => add_query_arg( 'page', 'monsterinsights_settings', admin_url( 'admin.php' ) ),
|
|
// Used to add notices for future deprecations.
|
|
'versions' => monsterinsights_get_php_wp_version_warning_data(),
|
|
'plugin_version' => MONSTERINSIGHTS_VERSION,
|
|
'is_admin' => true,
|
|
'admin_email' => get_option( 'admin_email' ),
|
|
'site_url' => get_site_url(),
|
|
'wizard_url' => is_network_admin() ? network_admin_url( 'index.php?page=monsterinsights-onboarding' ) : admin_url( 'index.php?page=monsterinsights-onboarding' ),
|
|
'install_nonce' => wp_create_nonce( 'monsterinsights-install' ),
|
|
'activate_nonce' => wp_create_nonce( 'monsterinsights-activate' ),
|
|
'deactivate_nonce' => wp_create_nonce( 'monsterinsights-deactivate' ),
|
|
'update_settings' => current_user_can( 'monsterinsights_save_settings' ),
|
|
'migrated' => monsterinsights_get_option( 'gadwp_migrated', 0 ),
|
|
'yearinreview' => monsterinsights_yearinreview_dates(),
|
|
'reports_url' => add_query_arg( 'page', 'monsterinsights_overview_report', admin_url( 'admin.php' ) ),
|
|
'feedback' => MonsterInsights_Feature_Feedback::get_settings(),
|
|
'addons_pre_check' => array(
|
|
'ai_insights' => is_plugin_active( 'monsterinsights-ai-insights/monsterinsights-ai-insights.php' ),
|
|
'woo_product_feed_pro' => is_plugin_active( 'woo-product-feed-pro/woocommerce-sea.php' ),
|
|
),
|
|
'license' => $license_info,
|
|
'charitablewp_notice' => $this->show_charitablewp_notice(),
|
|
'currency' => monsterinsights_get_ecommerce_currency(),
|
|
)
|
|
);
|
|
|
|
wp_scripts()->add_inline_script(
|
|
'monsterinsights-vue-reports',
|
|
monsterinsights_get_printable_translations( $text_domain ),
|
|
'translation'
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
// ublock notice
|
|
add_action( 'admin_print_footer_scripts', array( $this, 'monsterinsights_settings_ublock_error_js' ), 9999999 );
|
|
}
|
|
|
|
/**
|
|
* Need to identify why this function is using.
|
|
*/
|
|
public function monsterinsights_settings_ublock_error_js() {
|
|
echo "<script type='text/javascript'>\n";
|
|
echo "jQuery( document ).ready( function( $ ) {
|
|
if ( window.uorigindetected == null){
|
|
$('#monsterinsights-ublock-origin-error').show();
|
|
$('.monsterinsights-nav-tabs').hide();
|
|
$('.monsterinsights-nav-container').hide();
|
|
$('#monsterinsights-addon-heading').hide();
|
|
$('#monsterinsights-addons').hide();
|
|
$('#monsterinsights-reports').hide();
|
|
}
|
|
});";
|
|
echo "\n</script>";
|
|
}
|
|
|
|
/**
|
|
* Load CSS from manifest.json
|
|
*/
|
|
public static function enqueue_script_specific_css( $js_file_path ) {
|
|
if ( defined( 'MONSTERINSIGHTS_LOCAL_JS_URL' ) ) {
|
|
return;
|
|
}
|
|
|
|
$version_path = monsterinsights_is_pro_version() ? 'pro' : 'lite';
|
|
$plugin_path = plugin_dir_path( MONSTERINSIGHTS_PLUGIN_FILE );
|
|
|
|
if ( ! isset( self::$manifest_data[ $js_file_path ] ) ) {
|
|
return;
|
|
}
|
|
|
|
$js_imports = self::$manifest_data[ $js_file_path ]['imports'];
|
|
$css_file_path = $plugin_path . $version_path . '/assets/vue/';
|
|
|
|
// Add JS own CSS file.
|
|
if ( isset( self::$manifest_data[ $js_file_path ]['css'] ) ) {
|
|
self::add_js_own_css_files( self::$manifest_data[ $js_file_path ]['css'], $version_path );
|
|
}
|
|
|
|
// Loop through all imported js file of entry file.
|
|
foreach ( $js_imports as $js_filename ) {
|
|
// Check imported file available in manifest.json
|
|
if ( ! isset( self::$manifest_data[ $js_filename ] ) ) {
|
|
continue;
|
|
}
|
|
|
|
// Check imported js file has it's own css.
|
|
if ( ! isset( self::$manifest_data[ $js_filename ]['css'] ) ) {
|
|
continue;
|
|
}
|
|
|
|
$js_file_css = self::$manifest_data[ $js_filename ]['css'];
|
|
|
|
// css must be array.
|
|
if ( ! is_array( $js_file_css ) ) {
|
|
continue;
|
|
}
|
|
|
|
// Loop to css files of a imported js file.
|
|
foreach ( $js_file_css as $css_hash_name ) {
|
|
if ( file_exists( $css_file_path . $css_hash_name ) ) {
|
|
wp_enqueue_style(
|
|
'monsterinsights-style-' . basename( $css_hash_name ),
|
|
plugins_url( $version_path . '/assets/vue/' . $css_hash_name, MONSTERINSIGHTS_PLUGIN_FILE ),
|
|
array(),
|
|
monsterinsights_get_asset_version()
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add JS it's own CSS build file.
|
|
*/
|
|
private static function add_js_own_css_files( $css_files, $version_path ) {
|
|
foreach ( $css_files as $css_filename ) {
|
|
wp_enqueue_style(
|
|
'monsterinsights-style-' . basename( $css_filename ),
|
|
plugins_url( $version_path . '/assets/vue/' . $css_filename, MONSTERINSIGHTS_PLUGIN_FILE ),
|
|
array(),
|
|
monsterinsights_get_asset_version()
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get JS build file URL of a entry file.
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function get_js_url( $path ) {
|
|
if ( ! $path ) {
|
|
return;
|
|
}
|
|
|
|
if ( defined( 'MONSTERINSIGHTS_LOCAL_JS_URL' ) && MONSTERINSIGHTS_LOCAL_JS_URL ) {
|
|
return MONSTERINSIGHTS_LOCAL_JS_URL . $path;
|
|
}
|
|
|
|
// If the file is not available on manifest.
|
|
if ( ! isset( self::$manifest_data[ $path ] ) ) {
|
|
return;
|
|
}
|
|
|
|
$js_file = self::$manifest_data[ $path ]['file'];
|
|
$version_path = monsterinsights_is_pro_version() ? 'pro' : 'lite';
|
|
|
|
return plugins_url( $version_path . '/assets/vue/' . $js_file, MONSTERINSIGHTS_PLUGIN_FILE );
|
|
}
|
|
|
|
/**
|
|
* Fetch manifest.json data and store it to array for future use.
|
|
*
|
|
* @return void
|
|
*/
|
|
private function get_manifest_data() {
|
|
$version_path = monsterinsights_is_pro_version() ? 'pro' : 'lite';
|
|
$plugin_path = plugin_dir_path( MONSTERINSIGHTS_PLUGIN_FILE );
|
|
$manifest_path = $plugin_path . $version_path . '/assets/vue/manifest.json';
|
|
|
|
// Return if manifest.json not exists.
|
|
if ( ! file_exists( $manifest_path ) ) {
|
|
return;
|
|
}
|
|
|
|
self::$manifest_data = json_decode( file_get_contents( $manifest_path ), true );
|
|
}
|
|
|
|
/**
|
|
* Fetch Vue 3 manifest.json data and store it to array for future use.
|
|
*
|
|
* @return void
|
|
*/
|
|
private function get_manifest_data_v3() {
|
|
$version_path = monsterinsights_is_pro_version() ? 'pro' : 'lite';
|
|
$plugin_path = plugin_dir_path( MONSTERINSIGHTS_PLUGIN_FILE );
|
|
$manifest_path = $plugin_path . $version_path . '/assets/vue3/manifest.json';
|
|
|
|
if ( ! file_exists( $manifest_path ) ) {
|
|
return;
|
|
}
|
|
|
|
self::$manifest_data_v3 = json_decode( file_get_contents( $manifest_path ), true );
|
|
}
|
|
|
|
/**
|
|
* Map a Vue 3 page slug to its Vite entry point.
|
|
*
|
|
* @param string $page The sanitized page slug.
|
|
* @return string Entry key for the manifest (defaults to custom-dashboard).
|
|
*/
|
|
private function get_vue3_entry_key( $page ) {
|
|
$entry_map = apply_filters( 'monsterinsights_vue3_entry_map', array(
|
|
'monsterinsights_overview_report' => 'src/modules/reports/main.js',
|
|
'monsterinsights_custom_dashboard' => 'src/modules/custom-dashboard/main.js',
|
|
'monsterinsights-custom-dashboards' => 'src/modules/custom-dashboard/main.js',
|
|
) );
|
|
|
|
return isset( $entry_map[ $page ] ) ? $entry_map[ $page ] : 'src/modules/custom-dashboard/main.js';
|
|
}
|
|
|
|
/**
|
|
* Determine if current admin page should load Vue 3 assets.
|
|
* Uses the `page` query arg (menu_slug from add_submenu_page) and allows filters for future modules.
|
|
*
|
|
* @return bool
|
|
*/
|
|
private function is_vue3_admin_page() {
|
|
// Ensure we are on a MI admin screen first.
|
|
$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : false;
|
|
if ( empty( $screen ) || empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) === false ) {
|
|
return false;
|
|
}
|
|
|
|
$page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : '';
|
|
if ( empty( $page ) ) {
|
|
return false;
|
|
}
|
|
|
|
// Slugs that should be served by Vue 3. Start with Custom Views; extend via filter as modules migrate.
|
|
$vue3_pages = apply_filters( 'monsterinsights_vue3_pages', array(
|
|
'monsterinsights_custom_dashboard',
|
|
'monsterinsights-custom-dashboards', // Support hyphenated plural version
|
|
'monsterinsights_overview_report',
|
|
) );
|
|
|
|
return in_array( $page, $vue3_pages, true );
|
|
}
|
|
|
|
/**
|
|
* Get Vue 3 entry and base URL from manifest for a given key.
|
|
*
|
|
* @param string $entry_key Manifest key (e.g., 'custom-dashboard').
|
|
* @return array [ base_url, entry_array ]
|
|
*/
|
|
private function get_vue3_entry( $entry_key ) {
|
|
$version_path = monsterinsights_is_pro_version() ? 'pro' : 'lite';
|
|
$base_url = plugins_url( $version_path . '/assets/vue3/', MONSTERINSIGHTS_PLUGIN_FILE );
|
|
$entry = array();
|
|
|
|
if ( isset( self::$manifest_data_v3[ $entry_key ] ) ) {
|
|
$entry = self::$manifest_data_v3[ $entry_key ];
|
|
} elseif ( isset( self::$manifest_data_v3[ 'src/' . $entry_key . '/main.js' ] ) ) {
|
|
$entry = self::$manifest_data_v3[ 'src/' . $entry_key . '/main.js' ];
|
|
}
|
|
|
|
// Apply SCRIPT_DEBUG suffix pattern: use unminified version when debugging.
|
|
// Manifest always contains .min.js paths, but we also build .js versions.
|
|
if ( ! empty( $entry['file'] ) && defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
|
|
$entry['file'] = str_replace( '.min.js', '.js', $entry['file'] );
|
|
}
|
|
|
|
return array( $base_url, $entry );
|
|
}
|
|
|
|
/**
|
|
* Enqueue all CSS files for a Vue 3 entry point, including its imports and dynamic imports.
|
|
*
|
|
* Walks the manifest dependency tree to collect CSS from the entry, its static imports,
|
|
* and its dynamic imports (lazy-loaded chunks like route components).
|
|
*
|
|
* @param string $entry_key Manifest key (e.g., 'src/modules/reports/main.js').
|
|
*/
|
|
private function enqueue_vue3_entry_css( $entry_key ) {
|
|
list( $base_url, $entry ) = $this->get_vue3_entry( $entry_key );
|
|
|
|
if ( empty( $entry ) ) {
|
|
return;
|
|
}
|
|
|
|
$css_files = array();
|
|
$visited = array();
|
|
|
|
// Recursively collect CSS from entry and all its dependencies.
|
|
$this->collect_vue3_css( $entry_key, $css_files, $visited );
|
|
|
|
foreach ( $css_files as $i => $css_file ) {
|
|
wp_enqueue_style(
|
|
'monsterinsights-v3-style-' . $i,
|
|
$base_url . ltrim( $css_file, '/' ),
|
|
array(),
|
|
monsterinsights_get_asset_version()
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Recursively collect CSS files from a manifest entry and its imports/dynamic imports.
|
|
*
|
|
* @param string $key Manifest key to process.
|
|
* @param array $css_files Collected CSS files (passed by reference).
|
|
* @param array $visited Already visited keys to prevent cycles (passed by reference).
|
|
*/
|
|
private function collect_vue3_css( $key, &$css_files, &$visited ) {
|
|
if ( isset( $visited[ $key ] ) ) {
|
|
return;
|
|
}
|
|
$visited[ $key ] = true;
|
|
|
|
$entry = isset( self::$manifest_data_v3[ $key ] ) ? self::$manifest_data_v3[ $key ] : null;
|
|
if ( empty( $entry ) ) {
|
|
return;
|
|
}
|
|
|
|
// Collect CSS from this entry.
|
|
if ( ! empty( $entry['css'] ) && is_array( $entry['css'] ) ) {
|
|
foreach ( $entry['css'] as $css_file ) {
|
|
if ( ! in_array( $css_file, $css_files, true ) ) {
|
|
$css_files[] = $css_file;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Walk static imports (shared chunks like _Icon-xxx.js).
|
|
if ( ! empty( $entry['imports'] ) && is_array( $entry['imports'] ) ) {
|
|
foreach ( $entry['imports'] as $import_key ) {
|
|
$this->collect_vue3_css( $import_key, $css_files, $visited );
|
|
}
|
|
}
|
|
|
|
// Walk dynamic imports (lazy-loaded route chunks like OverviewReport.vue).
|
|
if ( ! empty( $entry['dynamicImports'] ) && is_array( $entry['dynamicImports'] ) ) {
|
|
foreach ( $entry['dynamicImports'] as $dynamic_key ) {
|
|
$this->collect_vue3_css( $dynamic_key, $css_files, $visited );
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sanitization specific to each field.
|
|
*
|
|
* @param string $field The key of the field to sanitize.
|
|
* @param string $value The value of the field to sanitize.
|
|
*
|
|
* @return mixed The sanitized input.
|
|
*/
|
|
private function handle_sanitization( $field, $value ) {
|
|
|
|
$value = wp_unslash( $value );
|
|
|
|
// Textarea fields.
|
|
$textarea_fields = array();
|
|
|
|
if ( in_array( $field, $textarea_fields, true ) ) {
|
|
if ( function_exists( 'sanitize_textarea_field' ) ) {
|
|
return sanitize_textarea_field( $value );
|
|
} else {
|
|
return wp_kses( $value, array() );
|
|
}
|
|
}
|
|
|
|
$array_value = $value;
|
|
if ( is_array( $array_value ) ) {
|
|
$value = $array_value;
|
|
// Don't save empty values.
|
|
foreach ( $value as $key => $item ) {
|
|
if ( is_array( $item ) ) {
|
|
$empty = true;
|
|
foreach ( $item as $item_value ) {
|
|
if ( ! empty( $item_value ) ) {
|
|
$empty = false;
|
|
}
|
|
}
|
|
if ( $empty ) {
|
|
unset( $value[ $key ] );
|
|
}
|
|
}
|
|
}
|
|
// Reset array keys because JavaScript can't handle arrays with non-sequential keys.
|
|
$value = array_values( $value );
|
|
|
|
return $value;
|
|
}
|
|
return sanitize_text_field( $value );
|
|
}
|
|
|
|
/**
|
|
* Check if the CharitableWP notice should be shown.
|
|
*/
|
|
private function show_charitablewp_notice() {
|
|
// Check if user has permission to show the notice.
|
|
if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
|
|
return false;
|
|
}
|
|
|
|
$installed_plugins = get_plugins();
|
|
$plugin_path = 'charitable/charitable.php';
|
|
|
|
if ( isset( $installed_plugins[$plugin_path] ) ) {
|
|
return false;
|
|
}
|
|
|
|
return monsterinsights_get_option( 'show_charitable_notice', false );
|
|
}
|
|
|
|
/**
|
|
* Load Vue 3 report script.
|
|
*/
|
|
private function load_vue3_report_script($auth, $auth_data, $license_info, $version_path) {
|
|
$handle = 'monsterinsights-vue3-reports';
|
|
|
|
if ( defined( 'MONSTERINSIGHTS_V3_DEV_URL' ) && MONSTERINSIGHTS_V3_DEV_URL ) {
|
|
$dev_url = trailingslashit( MONSTERINSIGHTS_V3_DEV_URL ) . 'src/modules/reports/main.js';
|
|
wp_register_script( $handle, $dev_url, array( 'wp-i18n', 'wp-util' ), monsterinsights_get_asset_version(), true );
|
|
wp_enqueue_script( $handle );
|
|
} else {
|
|
list( $base_url, $entry ) = $this->get_vue3_entry( 'src/modules/reports/main.js' );
|
|
if ( ! empty( $entry['file'] ) ) {
|
|
$src = $base_url . ltrim( $entry['file'], '/' );
|
|
wp_register_script( $handle, $src, array( 'wp-i18n', 'wp-util' ), monsterinsights_get_asset_version(), true );
|
|
wp_enqueue_script( $handle );
|
|
}
|
|
}
|
|
|
|
// Provide bootstrap payload for the Vue 3 app in build
|
|
$site_auth = $auth->get_viewname();
|
|
$ms_auth = is_multisite() && $auth->get_network_viewname();
|
|
|
|
// Reporting API credentials for direct client-side requests to api/v3/reporting/query
|
|
$reporting_api = array(
|
|
'url' => apply_filters( 'monsterinsights_api_url_custom_dashboard', 'https://app.monsterinsights.com/' ),
|
|
'license' => monsterinsights_is_pro_version() ? ( is_network_admin() ? MonsterInsights()->license->get_network_license_key() : MonsterInsights()->license->get_site_license_key() ) : '',
|
|
'key' => is_network_admin() ? $auth->get_network_key() : $auth->get_key(),
|
|
'token' => is_network_admin() ? $auth->get_network_token() : $auth->get_token(),
|
|
'site_url' => is_network_admin() ? network_admin_url() : home_url(),
|
|
);
|
|
|
|
// Bearer token for direct browser-to-API requests (Relay), same pattern as Custom Dashboard.
|
|
$bearer_token_data = MonsterInsights_API_Token::get_token( is_network_admin() );
|
|
$bearer_token = '';
|
|
$bearer_expires = 0;
|
|
|
|
if ( ! is_wp_error( $bearer_token_data ) ) {
|
|
$bearer_token = $bearer_token_data['token'];
|
|
$bearer_expires = $bearer_token_data['expires_at'];
|
|
}
|
|
|
|
// Build addon info (active, installed, basename) for Vue 3 report addon gates.
|
|
$installed_plugins = get_plugins();
|
|
$addon_defs = array(
|
|
'ecommerce' => array( 'monsterinsights-ecommerce', 'ga-ecommerce' ),
|
|
'dimensions' => array( 'monsterinsights-dimensions' ),
|
|
'forms' => array( 'monsterinsights-forms' ),
|
|
'page_insights' => array( 'monsterinsights-page-insights' ),
|
|
);
|
|
$addons_active = array();
|
|
$addons_info = array();
|
|
foreach ( $addon_defs as $key => $slugs ) {
|
|
$is_active = false;
|
|
$is_installed = false;
|
|
$basename = '';
|
|
foreach ( $slugs as $slug ) {
|
|
$bn = monsterinsights_get_plugin_basename_from_slug( $slug );
|
|
if ( $bn && isset( $installed_plugins[ $bn ] ) ) {
|
|
$is_installed = true;
|
|
$basename = $bn;
|
|
if ( is_plugin_active( $bn ) ) {
|
|
$is_active = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
$addons_active[ $key ] = $is_active;
|
|
$addons_info[ $key ] = array(
|
|
'installed' => $is_installed,
|
|
'basename' => $basename,
|
|
);
|
|
}
|
|
|
|
wp_localize_script(
|
|
$handle,
|
|
'monsterinsights',
|
|
array(
|
|
'ajax' => admin_url( 'admin-ajax.php' ),
|
|
'assets_url' => apply_filters( 'monsterinsights_vue3_assets_url', plugins_url( $version_path . '/assets/vue3', MONSTERINSIGHTS_PLUGIN_FILE ) ),
|
|
'nonce' => wp_create_nonce( 'mi-admin-nonce' ),
|
|
'license' => $license_info,
|
|
'auth' => $auth_data,
|
|
'authed' => $site_auth || $ms_auth, // Boolean for admin bar compatibility
|
|
'can_view_reports' => current_user_can( 'monsterinsights_view_dashboard' ),
|
|
'license_expired' => monsterinsights_is_pro_version() && MonsterInsights()->license->license_has_error(),
|
|
'plugin_version' => MONSTERINSIGHTS_VERSION,
|
|
'reporting_api' => $reporting_api,
|
|
// Direct API access (Relay) for Overview/Reports, aligned with Custom Dashboard.
|
|
'relay_api_url' => apply_filters( 'monsterinsights_api_url_custom_dashboard', 'https://app.monsterinsights.com/' ),
|
|
'bearer_token' => $bearer_token,
|
|
'bearer_expires' => $bearer_expires,
|
|
// Sample data mode: when true, frontend should bypass direct API and use WP AJAX for sample data.
|
|
'sample_data_enabled' => apply_filters( 'monsterinsights_sample_data_enabled', false ),
|
|
'wizard_url' => is_admin() ? monsterinsights_get_onboarding_url() : '',
|
|
'addons' => $addons_active,
|
|
'addons_info' => $addons_info,
|
|
'activate_nonce' => wp_create_nonce( 'monsterinsights-activate' ),
|
|
'install_nonce' => wp_create_nonce( 'monsterinsights-install' ),
|
|
'addons_page_url' => is_multisite() ? network_admin_url( 'admin.php?page=monsterinsights_network#/addons' ) : admin_url( 'admin.php?page=monsterinsights_settings#/addons' ),
|
|
'update_settings' => current_user_can( 'monsterinsights_save_settings' ),
|
|
)
|
|
);
|
|
// Load translations for Vue 3 app using WordPress's script translation system
|
|
wp_set_script_translations( $handle, 'google-analytics-for-wordpress' );
|
|
}
|
|
}
|
|
|
|
new MonsterInsights_Admin_Assets();
|