From 5d3ea2d1495521b5aed15c9cce6841abd4b6cc0a Mon Sep 17 00:00:00 2001 From: Dan0sz <18595395+Dan0sz@users.noreply.github.com> Date: Wed, 1 May 2024 09:50:18 +0200 Subject: [PATCH 1/7] Add migration script for any instance where the enhanced_measurements settings is broken. --- src/Admin/Upgrades.php | 21 +++++++++++++++++ tests/integration/Admin/UpgradesTest.php | 30 ++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 tests/integration/Admin/UpgradesTest.php diff --git a/src/Admin/Upgrades.php b/src/Admin/Upgrades.php index a9e9bc23..8e8f6b1a 100644 --- a/src/Admin/Upgrades.php +++ b/src/Admin/Upgrades.php @@ -73,6 +73,10 @@ public function run() { } // @codeCoverageIgnoreEnd + if ( version_compare( $plausible_analytics_version, '2.1.0', '<' ) ) { + $this->upgrade_to_210(); + } + // Add required upgrade routines for future versions here. } @@ -248,4 +252,21 @@ private function upgrade_to_203() { update_option( 'plausible_analytics_version', '2.0.3' ); } + + /** + * v2.0.8 and older contained a bug that + * + * @return void + */ + public function upgrade_to_210() { + $settings = Helpers::get_settings(); + + if ( ! is_array( $settings[ 'enhanced_measurements' ] ) ) { + $settings[ 'enhanced_measurements' ] = []; + } + + update_option( 'plausible_analytics_settings', $settings ); + + update_option( 'plausible_analytics_version', '2.1.0' ); + } } diff --git a/tests/integration/Admin/UpgradesTest.php b/tests/integration/Admin/UpgradesTest.php new file mode 100644 index 00000000..183cee27 --- /dev/null +++ b/tests/integration/Admin/UpgradesTest.php @@ -0,0 +1,30 @@ +upgrade_to_210(); + + $enhanced_measurements = Helpers::get_settings()[ 'enhanced_measurements' ]; + + $this->assertIsArray( $enhanced_measurements ); + } +} From fdfad95e7ddcf751e6817404199307aac80336d9 Mon Sep 17 00:00:00 2001 From: Dan0sz <18595395+Dan0sz@users.noreply.github.com> Date: Wed, 1 May 2024 10:41:01 +0200 Subject: [PATCH 2/7] Proper fix for is_list logic. --- src/Admin/Settings/API.php | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/Admin/Settings/API.php b/src/Admin/Settings/API.php index 9f7eb4c4..dffd528d 100644 --- a/src/Admin/Settings/API.php +++ b/src/Admin/Settings/API.php @@ -10,6 +10,7 @@ namespace Plausible\Analytics\WP\Admin\Settings; +use Plausible\Analytics\WP\Ajax; use Plausible\Analytics\WP\Helpers; /** @@ -581,23 +582,21 @@ public function render_group_field( array $group, $hide_header = false ) { - 1; ?> - 1 ); } - foreach ( $fields as $field ): ?> - - + ?> Date: Wed, 1 May 2024 11:09:33 +0200 Subject: [PATCH 3/7] Introduced get_hosted_domain() function, refactored logic to use it where needed and make sure Create API token and other relevant links use it as well. --- assets/src/js/admin/main.js | 2 +- assets/src/js/admin/main.min.js | 1 + src/Admin/Actions.php | 4 +- src/Admin/Settings/Hooks.php | 2 +- src/Admin/Settings/Page.php | 18 +++--- src/Helpers.php | 101 ++++++++++++++++---------------- 6 files changed, 64 insertions(+), 64 deletions(-) create mode 100644 assets/src/js/admin/main.min.js diff --git a/assets/src/js/admin/main.js b/assets/src/js/admin/main.js index 4378bca7..f3b52dc6 100644 --- a/assets/src/js/admin/main.js +++ b/assets/src/js/admin/main.js @@ -232,7 +232,7 @@ document.addEventListener('DOMContentLoaded', () => { let domain = document.getElementById('domain_name').value; domain = domain.replace('/', '%2F'); - window.open(`https://plausible.io/${domain}/settings/integrations?new_token=WordPress`, '_blank', 'location=yes,height=768,width=1024,scrollbars=yes,status=no'); + window.open(`${plausible_analytics_hosted_domain}/${domain}/settings/integrations?new_token=WordPress`, '_blank', 'location=yes,height=768,width=1024,scrollbars=yes,status=no'); }, /** diff --git a/assets/src/js/admin/main.min.js b/assets/src/js/admin/main.min.js new file mode 100644 index 00000000..04d91fa4 --- /dev/null +++ b/assets/src/js/admin/main.min.js @@ -0,0 +1 @@ +document.addEventListener("DOMContentLoaded",()=>{if(!document.location.href.includes("plausible_analytics")){return}let plausible={nonceElem:document.getElementById("_wpnonce"),nonce:"",showWizardElem:document.getElementById("show_wizard"),domainNameElem:document.getElementById("domain_name"),apiTokenElem:document.getElementById("api_token"),createAPITokenElems:document.getElementsByClassName("plausible-create-api-token"),buttonElems:document.getElementsByClassName("plausible-analytics-button"),stepElems:document.getElementsByClassName("plausible-analytics-wizard-next-step"),init:function(){if(document.location.hash===""&&document.getElementById("plausible-analytics-wizard")!==null){document.location.hash="#welcome_slide"}if(this.nonceElem!==null){this.nonce=this.nonceElem.value}this.toggleWizardStep();window.addEventListener("hashchange",this.toggleWizardStep);if(this.showWizardElem!==null){this.showWizardElem.addEventListener("click",this.showWizard)}if(this.domainNameElem!==null){this.domainNameElem.addEventListener("keyup",this.disableConnectButton)}if(this.apiTokenElem!==null){this.apiTokenElem.addEventListener("keyup",this.disableConnectButton)}if(this.createAPITokenElems.length>0){for(let i=0;i0){for(let i=0;i0){for(let i=0;in);if(currentlyCompletedSteps.length<1){return}currentlyCompletedSteps.forEach(function(step){let completedStep=document.getElementById("completed-step-"+step);let inactiveStep=document.getElementById("step-"+step);completedStep.classList.remove("hidden");inactiveStep.classList+=" hidden"})},ajax:function(data,button=null,showMessages=true){return fetch(ajaxurl,{method:"POST",body:data}).then(response=>{if(button){button.children[0].classList+=" hidden";button.removeAttribute("disabled")}if(response.status===200){return response.json()}return false}).then(response=>{if(showMessages===true){plausible.showMessages()}let event=new CustomEvent("plausibleAjaxDone",{detail:response});document.dispatchEvent(event);return response.data})},showMessages:function(){let messages=plausible.fetchMessages();messages.then(function(messages){if(messages.error!==false){plausible.showMessage(messages.error,"error")}else if(messages.notice!==false){plausible.showMessage(messages.notice,"notice")}else if(messages.success!==false){plausible.showMessage(messages.success,"success")}if(messages.additional.length===0||document.getElementById("plausible-analytics-wizard")!==null){return}if(messages.additional.id!==undefined&&messages.additional.message){plausible.showAdditionalMessage(messages.additional.message,messages.additional.id)}else if(messages.additional.id!==undefined&&messages.additional.message===""){plausible.removeAdditionalMessage(messages.additional.id)}})},fetchMessages:function(){let data=new FormData;data.append("action","plausible_analytics_messages");let result=plausible.ajax(data,null,false);return result.then(function(response){return response})},showMessage:function(message,type="success"){if(type==="error"){document.getElementById("icon-error").classList.remove("hidden");document.getElementById("icon-success").classList.add("hidden");document.getElementById("icon-notice").classList.add("hidden")}else if(type==="notice"){document.getElementById("icon-notice").classList.remove("hidden");document.getElementById("icon-error").classList.add("hidden");document.getElementById("icon-success").classList.add("hidden")}else{document.getElementById("icon-success").classList.remove("hidden");document.getElementById("icon-error").classList.add("hidden");document.getElementById("icon-notice").classList.add("hidden")}let notice=document.getElementById("plausible-analytics-notice");document.getElementById("plausible-analytics-notice-text").innerHTML=message;notice.classList.remove("hidden");setTimeout(function(){notice.classList.replace("opacity-0","opacity-100")},200);if(type!=="error"){setTimeout(function(){notice.classList.replace("opacity-100","opacity-0");setTimeout(function(){notice.classList+=" hidden"},200)},2e3)}},showAdditionalMessage:function(html,target){let targetElem=document.querySelector(`[name='${target}']`);let container=targetElem.closest(".plausible-analytics-group");container.innerHTML+=html},removeAdditionalMessage:function(target){let targetElem=document.querySelector(`[name="${target}"]`);let container=targetElem.closest(".plausible-analytics-group");let additionalMessage;if(container.children.length>0){for(let i=0;i diff --git a/src/Admin/Settings/Page.php b/src/Admin/Settings/Page.php index 15207475..5f916283 100644 --- a/src/Admin/Settings/Page.php +++ b/src/Admin/Settings/Page.php @@ -69,9 +69,7 @@ class Page extends API { public function __construct() { $this->init(); - $settings = Helpers::get_settings(); - $domain = Helpers::get_domain(); - $self_hosted_domain = defined( 'PLAUSIBLE_SELF_HOSTED_DOMAIN' ) ? PLAUSIBLE_SELF_HOSTED_DOMAIN : $settings[ 'self_hosted_domain' ]; + $settings = Helpers::get_settings(); $this->fields = [ 'general' => [ @@ -87,14 +85,14 @@ public function __construct() { ), 'post' ), - 'https://plausible.io/sites' + Helpers::get_hosted_domain() . '/sites' ), 'fields' => [ [ 'label' => esc_html__( 'Domain name', 'plausible-analytics' ), 'slug' => 'domain_name', 'type' => 'text', - 'value' => $domain, + 'value' => Helpers::get_domain(), ], [ 'label' => esc_html__( 'API token', 'plausible-analytics' ), @@ -333,7 +331,8 @@ public function __construct() { 'label' => esc_html__( 'Domain name', 'plausible-analytics' ), 'slug' => 'self_hosted_domain', 'type' => 'text', - 'value' => $self_hosted_domain, + 'value' => defined( 'PLAUSIBLE_SELF_HOSTED_DOMAIN' ) ? PLAUSIBLE_SELF_HOSTED_DOMAIN : + $settings[ 'self_hosted_domain' ], 'placeholder' => 'e.g. ' . Helpers::get_domain(), 'disabled' => Helpers::proxy_enabled(), ], @@ -368,8 +367,9 @@ public function __construct() { 'type' => 'text', 'value' => $settings[ 'self_hosted_shared_link' ], 'placeholder' => sprintf( - wp_kses( __( 'E.g. https://plausible.io/share/%s?auth=XXXXXXXXXXXX', 'plausible-analytics' ), 'post' ), - $domain + wp_kses( __( 'E.g. %s/share/%s?auth=XXXXXXXXXXXX', 'plausible-analytics' ), 'post' ), + Helpers::get_hosted_domain(), + Helpers::get_domain() ), 'disabled' => Helpers::proxy_enabled(), ], @@ -613,7 +613,7 @@ public function render_analytics_dashboard() { /** * Prior to this version, the default value would contain an example "auth" key, i.e. XXXXXXXXX. * When this option was saved to the database, underlying code would fail, throwing a CORS related error in browsers. - * Now, we explicitly check for the existence of this example "auth" key, and display a human readable error message to + * Now, we explicitly check for the existence of this example "auth" key, and display a human-readable error message to * those who haven't properly set it up. * * @since v1.2.5 diff --git a/src/Helpers.php b/src/Helpers.php index a0c98f3d..be9d143d 100644 --- a/src/Helpers.php +++ b/src/Helpers.php @@ -24,10 +24,7 @@ class Helpers { * @throws Exception */ public static function get_js_url( $local = false ) { - $settings = self::get_settings(); - $file_name = self::get_filename( $local ); - $default_domain = 'plausible.io'; - $domain = $default_domain; + $file_name = self::get_filename( $local ); /** * If Avoid ad blockers is enabled, return URL to local file. @@ -36,21 +33,36 @@ public static function get_js_url( $local = false ) { return esc_url( self::get_proxy_resource( 'cache_url' ) . $file_name . '.js' ); } - // Allows for hard-coding the self-hosted domain. - if ( defined( 'PLAUSIBLE_SELF_HOSTED_DOMAIN' ) ) { - $domain = PLAUSIBLE_SELF_HOSTED_DOMAIN; // @codeCoverageIgnore + return esc_url( self::get_hosted_domain() . "/js/$file_name.js" ); + } + + /** + * Get filename (without file extension) + * + * @since 1.3.0 + * @return string + * @throws Exception + */ + public static function get_filename( $local = false ) { + $settings = self::get_settings(); + $file_name = 'plausible'; + + if ( $local && self::proxy_enabled() ) { + return self::get_proxy_resource( 'file_alias' ); } - /** - * Set $domain to self_hosted_domain if it exists. - */ - if ( ! empty( $settings[ 'self_hosted_domain' ] ) && $domain === $default_domain ) { - $domain = $settings[ 'self_hosted_domain' ]; + foreach ( [ 'outbound-links', 'file-downloads', 'tagged-events', 'revenue', 'pageview-props', 'compat', 'hash' ] as $extension ) { + if ( is_array( $settings[ 'enhanced_measurements' ] ) && in_array( $extension, $settings[ 'enhanced_measurements' ], true ) ) { + $file_name .= '.' . $extension; + } } - $url = "https://{$domain}/js/{$file_name}.js"; + // Load exclusions.js if any excluded pages are set. + if ( ! empty( $settings[ 'excluded_pages' ] ) ) { + $file_name .= '.' . 'exclusions'; + } - return esc_url( $url ); + return $file_name; } /** @@ -81,34 +93,6 @@ public static function get_settings() { return apply_filters( 'plausible_analytics_settings', wp_parse_args( $settings, $defaults ) ); } - /** - * Get filename (without file extension) - * - * @since 1.3.0 - * @return string - */ - public static function get_filename( $local = false ) { - $settings = self::get_settings(); - $file_name = 'plausible'; - - if ( $local && self::proxy_enabled() ) { - return self::get_proxy_resource( 'file_alias' ); - } - - foreach ( [ 'outbound-links', 'file-downloads', 'tagged-events', 'revenue', 'pageview-props', 'compat', 'hash' ] as $extension ) { - if ( is_array( $settings[ 'enhanced_measurements' ] ) && in_array( $extension, $settings[ 'enhanced_measurements' ], true ) ) { - $file_name .= '.' . $extension; - } - } - - // Load exclusions.js if any excluded pages are set. - if ( ! empty( $settings[ 'excluded_pages' ] ) ) { - $file_name .= '.' . 'exclusions'; - } - - return $file_name; - } - /** * Is the proxy enabled? * @@ -185,6 +169,28 @@ public static function get_proxy_resources() { return $resources; } + /** + * Returns the domain where Plausible Analytics is hosted: self-hosted or cloud. + * + * @return string + */ + public static function get_hosted_domain() { + $settings = self::get_settings(); + + if ( defined( 'PLAUSIBLE_SELF_HOSTED_DOMAIN' ) ) { + return 'https://' . PLAUSIBLE_SELF_HOSTED_DOMAIN; + } + + if ( ! empty( $settings[ 'self_hosted_domain' ] ) ) { + /** + * Until proven otherwise, let's just assume people are all on SSL. + */ + return 'https://' . $settings[ 'self_hosted_domain' ]; + } + + return 'https://plausible.io'; + } + /** * @param $option_name * @param $option_value @@ -267,9 +273,6 @@ public static function get_domain() { * @return string */ public static function get_data_api_url() { - $settings = self::get_settings(); - $url = 'https://plausible.io/api/event'; - if ( self::proxy_enabled() ) { // This'll make sure the API endpoint is properly registered when we're testing. $append = isset( $_GET[ 'plausible_proxy' ] ) ? '?plausible_proxy=1' : ''; @@ -277,13 +280,7 @@ public static function get_data_api_url() { return self::get_rest_endpoint() . $append; } - // Triggered when self-hosted analytics is enabled. - if ( ! empty( $settings[ 'self_hosted_domain' ] ) ) { - $default_domain = $settings[ 'self_hosted_domain' ]; - $url = "https://{$default_domain}/api/event"; - } - - return esc_url( $url ); + return esc_url( self::get_hosted_domain() . '/api/event' ); } /** From 3660b20c506690c9c3aebe3e4861a51698b2271e Mon Sep 17 00:00:00 2001 From: Dan0sz <18595395+Dan0sz@users.noreply.github.com> Date: Wed, 1 May 2024 12:23:59 +0200 Subject: [PATCH 4/7] Fixed: auto-formatter messed up. --- src/Admin/Actions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Admin/Actions.php b/src/Admin/Actions.php index a8423208..bb8d1c8d 100644 --- a/src/Admin/Actions.php +++ b/src/Admin/Actions.php @@ -73,7 +73,7 @@ public function maybe_redirect_to_wizard() { $wizard_done = get_option( 'plausible_analytics_wizard_done', false ); if ( ! $wizard_done ) { - $url = admin_url( 'options - general . php ? page = plausible_analytics#welcome_slide' ); + $url = admin_url( 'options-general.php?page=plausible_analytics#welcome_slide' ); wp_redirect( $url ); From 21726279bb995bd263a54c739a78ea676e50a638 Mon Sep 17 00:00:00 2001 From: Dan0sz <18595395+Dan0sz@users.noreply.github.com> Date: Wed, 1 May 2024 12:29:58 +0200 Subject: [PATCH 5/7] Improved: JS for embedded Analytics is now also loaded from the self-hosted domain if applicable. Re-factored method name. --- src/Admin/Actions.php | 2 +- src/Admin/Settings/Hooks.php | 2 +- src/Admin/Settings/Page.php | 8 +++++--- src/Helpers.php | 14 +++++++------- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/Admin/Actions.php b/src/Admin/Actions.php index bb8d1c8d..cf6384a4 100644 --- a/src/Admin/Actions.php +++ b/src/Admin/Actions.php @@ -51,7 +51,7 @@ public function register_assets( $current_page ) { true ); - wp_add_inline_script( 'plausible-admin', 'var plausible_analytics_hosted_domain = "' . Helpers::get_hosted_domain() . '";' ); + wp_add_inline_script( 'plausible-admin', 'var plausible_analytics_hosted_domain = "' . Helpers::get_hosted_domain_url() . '";' ); } /** diff --git a/src/Admin/Settings/Hooks.php b/src/Admin/Settings/Hooks.php index 72ae6b52..2dba31c4 100644 --- a/src/Admin/Settings/Hooks.php +++ b/src/Admin/Settings/Hooks.php @@ -75,7 +75,7 @@ public function connect_button() { diff --git a/src/Admin/Settings/Page.php b/src/Admin/Settings/Page.php index 5f916283..6162af7e 100644 --- a/src/Admin/Settings/Page.php +++ b/src/Admin/Settings/Page.php @@ -85,7 +85,7 @@ public function __construct() { ), 'post' ), - Helpers::get_hosted_domain() . '/sites' + Helpers::get_hosted_domain_url() . '/sites' ), 'fields' => [ [ @@ -368,7 +368,7 @@ public function __construct() { 'value' => $settings[ 'self_hosted_shared_link' ], 'placeholder' => sprintf( wp_kses( __( 'E.g. %s/share/%s?auth=XXXXXXXXXXXX', 'plausible-analytics' ), 'post' ), - Helpers::get_hosted_domain(), + Helpers::get_hosted_domain_url(), Helpers::get_domain() ), 'disabled' => Helpers::proxy_enabled(), @@ -630,12 +630,14 @@ public function render_analytics_dashboard() { if ( $shared_link && $page_url ) { $shared_link .= "&page={$page_url}"; } + + $hosted_domain = Helpers::get_hosted_domain_url(); ?>
- +