Statsdot. * * @package Statsdot */ if ( ! defined( 'ABSPATH' ) ) { exit; } /** * Registers the option and its fields. */ function statsdot_register_settings() { register_setting( 'statsdot', 'statsdot_settings', array( 'type' => 'array', 'sanitize_callback' => 'statsdot_sanitize_settings', 'default' => array(), ) ); } add_action( 'admin_init', 'statsdot_register_settings' ); /** * Keeps only known keys; the domain must look like a hostname. * * @param mixed $input Submitted values. * @return array */ function statsdot_sanitize_settings( $input ) { $input = is_array( $input ) ? $input : array(); $domain = isset( $input['domain'] ) ? strtolower( trim( sanitize_text_field( wp_unslash( $input['domain'] ) ) ) ) : ''; $domain = (string) preg_replace( '#^https?://#', '', $domain ); $domain = (string) preg_replace( '#^www\.#', '', rtrim( $domain, '/' ) ); if ( '' !== $domain && ! preg_match( '/^([a-z0-9-]+\.)+[a-z]{2,}$/', $domain ) ) { add_settings_error( 'statsdot_settings', 'statsdot_domain', __( 'The domain should look like example.com, without https:// or a path.', 'statsdot-analytics' ) ); $domain = ''; } // The site id comes only from connecting; a domain changed by hand drops it. $previous = statsdot_settings(); $site_id = isset( $input['site_id'] ) ? absint( $input['site_id'] ) : ( $domain === $previous['domain'] ? $previous['site_id'] : 0 ); return array( 'enabled' => ! empty( $input['enabled'] ), 'domain' => $domain, 'site_id' => $site_id, 'exclude_admins' => ! empty( $input['exclude_admins'] ), 'auto' => ! empty( $input['auto'] ), 'woocommerce' => ! empty( $input['woocommerce'] ), 'revenue' => ! empty( $input['revenue'] ), 'order_id' => ! empty( $input['order_id'] ), 'scroll' => ! empty( $input['scroll'] ), 'bot_key' => isset( $input['bot_key'] ) && preg_match( '/^sdb_[A-Za-z0-9]{40}$/', trim( (string) $input['bot_key'] ) ) ? trim( (string) $input['bot_key'] ) : '', ); } /** * Adds Settings > Statsdot. */ function statsdot_add_menu() { add_options_page( 'Statsdot', 'Statsdot', 'manage_options', 'statsdot', 'statsdot_render_settings' ); } add_action( 'admin_menu', 'statsdot_add_menu' ); /** * "Settings" link in the plugins list. * * @param array $links Action links. * @return array */ function statsdot_action_links( $links ) { array_unshift( $links, '' . esc_html__( 'Settings', 'statsdot-analytics' ) . '' ); return $links; } add_filter( 'plugin_action_links_' . plugin_basename( dirname( __FILE__ ) . '/statsdot.php' ), 'statsdot_action_links' ); /** * Pending connection of the current user: the state sent to statsdot.com. * * @return string */ function statsdot_connect_transient() { return 'statsdot_connect_' . get_current_user_id(); } /** * Address of a "Connect" button: admin-post.php starts the connection on * click, so a state is only created when someone asks to connect. * * @param bool $new Whether to open the sign-up form instead of the login. * @return string */ function statsdot_connect_url( $new = false ) { $args = array( 'action' => 'statsdot_connect' ); if ( $new ) { $args['new'] = 1; } return wp_nonce_url( add_query_arg( $args, admin_url( 'admin-post.php' ) ), 'statsdot_connect' ); } /** * Starts "Connect with Statsdot": stores a random state for 15 minutes and * sends the administrator to statsdot.com, where they log in or sign up and * choose the site. Only this site's domain, the address of this settings page * and the state are sent. */ function statsdot_connect_start() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'Sorry, you are not allowed to manage options for this site.', 'statsdot-analytics' ), 403 ); } check_admin_referer( 'statsdot_connect' ); $state = wp_generate_password( 32, false ); set_transient( statsdot_connect_transient(), $state, 15 * MINUTE_IN_SECONDS ); $query = array( 'domain' => statsdot_default_domain(), 'return' => admin_url( 'options-general.php?page=statsdot' ), 'state' => $state, ); if ( ! empty( $_GET['new'] ) ) { $query['new'] = 1; } // phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect -- statsdot.com is the destination by design. wp_redirect( STATSDOT_URL . '/connect/wordpress?' . http_build_query( $query, '', '&', PHP_QUERY_RFC3986 ) ); exit; } add_action( 'admin_post_statsdot_connect', 'statsdot_connect_start' ); /** * Back from statsdot.com: with the state of this user's pending connection, * saves the chosen domain and site and turns tracking on (choosing the site * there is the administrator's explicit consent). */ function statsdot_connect_finish() { // The state stored by statsdot_connect_start() is this request's nonce. // phpcs:disable WordPress.Security.NonceVerification.Recommended if ( ! isset( $_GET['statsdot_state'] ) || ! current_user_can( 'manage_options' ) ) { return; } $state = sanitize_text_field( wp_unslash( $_GET['statsdot_state'] ) ); $expected = get_transient( statsdot_connect_transient() ); $domain = isset( $_GET['statsdot_domain'] ) ? sanitize_text_field( wp_unslash( $_GET['statsdot_domain'] ) ) : ''; $site_id = isset( $_GET['statsdot_site'] ) ? absint( $_GET['statsdot_site'] ) : 0; // phpcs:enable WordPress.Security.NonceVerification.Recommended $valid = is_string( $expected ) && '' !== $expected && hash_equals( $expected, $state ) && $site_id > 0 && preg_match( '/^([a-z0-9-]+\.)+[a-z]{2,}$/', $domain ); if ( $valid ) { delete_transient( statsdot_connect_transient() ); update_option( 'statsdot_settings', array_merge( statsdot_settings(), array( 'enabled' => true, 'domain' => $domain, 'site_id' => $site_id, ) ) ); } wp_safe_redirect( admin_url( 'options-general.php?page=statsdot&statsdot_connected=' . ( $valid ? '1' : '0' ) ) ); exit; } add_action( 'load-settings_page_statsdot', 'statsdot_connect_finish' ); /** * On the settings page only: "Connect" opens statsdot.com in a popup. When * the popup comes back here, it reloads this page and closes. If the popup * lost its link to this page (Google's sign-in pages cut it), this page * reloads when it gets the focus back while a connection is pending. * * @param string $hook The current admin page. */ function statsdot_admin_scripts( $hook ) { if ( 'settings_page_statsdot' !== $hook ) { return; } wp_register_script( 'statsdot-admin', false, array(), STATSDOT_VERSION, array( 'in_footer' => true ) ); wp_enqueue_script( 'statsdot-admin' ); wp_add_inline_script( 'statsdot-admin', '(function(){' . "var back=/[?&]statsdot_connected=/.test(location.search);" . "if(back&&window.opener&&window.opener!==window){try{if(window.opener.location.host===location.host){window.opener.location.href=location.href;window.close();return;}}catch(e){}}" . "document.addEventListener('click',function(e){var a=e.target.closest&&e.target.closest('a[data-statsdot-connect]');if(!a){return;}var w=window.open(a.href,'statsdot-connect','width=520,height=760');if(w){e.preventDefault();w.focus();window.addEventListener('focus',function(){location.reload();},{once:true});}});" . ( get_transient( statsdot_connect_transient() ) && ! isset( $_GET['statsdot_connected'] ) ? "window.addEventListener('focus',function(){location.reload();},{once:true});" : '' ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- only decides whether to reload. . '})();' ); } add_action( 'admin_enqueue_scripts', 'statsdot_admin_scripts' ); /** * Until tracking is turned on, a notice on the plugins screen points to the * settings. Nothing is loaded from statsdot.com before that. */ function statsdot_setup_notice() { $screen = get_current_screen(); $settings = statsdot_settings(); if ( ! $screen || 'plugins' !== $screen->id || $settings['enabled'] || ! current_user_can( 'manage_options' ) ) { return; } printf( '

%s %s

', esc_html__( 'Statsdot Analytics is installed but not measuring yet.', 'statsdot-analytics' ), esc_url( admin_url( 'options-general.php?page=statsdot' ) ), esc_html__( 'Connect your Statsdot account', 'statsdot-analytics' ) ); } add_action( 'admin_notices', 'statsdot_setup_notice' ); /** * Renders the settings page. */ function statsdot_render_settings() { if ( ! current_user_can( 'manage_options' ) ) { return; } $settings = statsdot_settings(); $saved = get_option( 'statsdot_settings', array() ); // Display only: the result of statsdot_connect_finish(). $connected = isset( $_GET['statsdot_connected'] ) ? sanitize_key( wp_unslash( $_GET['statsdot_connected'] ) ) : null; // phpcs:ignore WordPress.Security.NonceVerification.Recommended ?>

Statsdot

' . esc_html( $settings['domain'] ) . '' ); ?>