diff --git a/assets/src/js/admin/main.js b/assets/src/js/admin/main.js index 0b830f9..f3f36ab 100644 --- a/assets/src/js/admin/main.js +++ b/assets/src/js/admin/main.js @@ -84,7 +84,7 @@ document.addEventListener('DOMContentLoaded', () => { * * @param e */ - toggleOption: function (e) { + toggleOption: async function (e) { /** * Make sure event target is a toggle. */ @@ -109,11 +109,13 @@ document.addEventListener('DOMContentLoaded', () => { // Toggle: off button.classList.replace('bg-indigo-600', 'bg-gray-200'); toggle.classList.replace('translate-x-5', 'translate-x-0'); + button.dataset.status = 'off'; toggleStatus = ''; } else { // Toggle: on button.classList.replace('bg-gray-200', 'bg-indigo-600'); toggle.classList.replace('translate-x-0', 'translate-x-5'); + button.dataset.status = 'on'; toggleStatus = 'on'; } @@ -126,7 +128,13 @@ document.addEventListener('DOMContentLoaded', () => { form.append('is_list', button.dataset.list); form.append('_nonce', plausible.nonce); - plausible.ajax(form); + let data = await plausible.ajax(form); + + if (data.capabilities === undefined) { + return; + } + + plausible.maybeDisableOptions(data.capabilities); }, /** @@ -160,6 +168,33 @@ document.addEventListener('DOMContentLoaded', () => { plausible.ajax(form, button); }, + /** + * Disable options based on the capabilities retrieved from the API. + * + * @param capabilities + */ + maybeDisableOptions: function (capabilities) { + let options = document.querySelectorAll('button[data-caps]'); + + options.forEach(function (option) { + let caps = option.dataset.caps.split(','); + let disable = false; + + caps.forEach(function (cap) { + if (capabilities[cap] === false) { + disable = true; + } + }); + + if (disable === true) { + // Trigger a click to make sure the option is disabled. + if (option.dataset.status === 'on') { + option.dispatchEvent(new Event('click', {bubbles: true})); + } + } + }); + }, + /** * Currently only validates the domain_name input, but can be used in the future for other custom input validations. * @@ -375,7 +410,8 @@ document.addEventListener('DOMContentLoaded', () => { } } - if (response.status === 200) { + // We still want the data, if it's a Payment Required error. + if (response.status === 200 || response.status === 402) { return response.json(); } @@ -478,6 +514,7 @@ document.addEventListener('DOMContentLoaded', () => { }, 2000); } }, + /** * Renders a HTML box containing additional information about the enabled option. * diff --git a/assets/src/js/admin/main.min.js b/assets/src/js/admin/main.min.js index b9929c6..79eb2d3 100644 --- a/assets/src/js/admin/main.min.js +++ b/assets/src/js/admin/main.min.js @@ -1 +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;i0){button.children[0].classList.remove("hidden")}button.setAttribute("disabled","disabled");plausible.ajax(form,button)},validateInput:function(input){if(input.name==="domain_name"&&input.value.match(/^(https?:\/\/)?(www.)?/).length>0){input.value=input.value.replace(/^(https?:\/\/)?(www.)?/,"")}return input},saveOptionOnNext:function(e){let hash=document.location.hash.replace("#","");if(hash!=="api_token_slide"&&hash!=="domain_name_slide"){return}let form=e.target.closest(".plausible-analytics-wizard-step-section");let inputs=form.getElementsByTagName("INPUT");let options=[];for(let input of inputs){input=plausible.validateInput(input);options.push({name:input.name,value:input.value})}let data=new FormData;data.append("action","plausible_analytics_save_options");data.append("options",JSON.stringify(options));data.append("_nonce",plausible.nonce);plausible.ajax(data).then(response=>{if(hash==="api_token_slide"&&response.success===true){let stats_button=document.getElementById("enable_analytics_dashboard_view_stats_in_wordpress");stats_button.removeAttribute("disabled")}})},disableConnectButton:function(e){let target=e.target;let button=document.getElementById("connect_plausible_analytics");let buttonIsHref=false;if(button===null){let slide_id=document.location.hash;button=document.querySelector(slide_id+" .plausible-analytics-wizard-next-step");buttonIsHref=true}if(button===null){return}if(target.value!==""){if(!buttonIsHref){button.disabled=false}else{button.classList.remove("pointer-events-none");button.classList.replace("bg-gray-200","bg-indigo-600")}return}if(!buttonIsHref){button.disabled=true;button.innerHTML=button.innerHTML.replace("Connected","Connect")}else{button.classList+=" pointer-events-none";button.classList.replace("bg-indigo-600","bg-gray-200")}},createAPIToken:function(e){e.preventDefault();let domain=document.getElementById("domain_name").value;domain=domain.replaceAll("/","%2F");window.open(`${plausible_analytics_hosted_domain}/${domain}/settings/integrations?new_token=WordPress`,"_blank","location=yes,height=768,width=1024,scrollbars=yes,status=no")},showWizard:function(e){let data=new FormData;data.append("action","plausible_analytics_show_wizard");data.append("_nonce",e.target.dataset.nonce);plausible.ajax(data)},toggleWizardStep:function(){if(document.getElementById("plausible-analytics-wizard")===null){return}const hash=document.location.hash.substring(1).replace("_slide","");let allSteps=document.querySelectorAll(".plausible-analytics-wizard-step");let activeSteps=document.querySelectorAll(".plausible-analytics-wizard-active-step");let completedSteps=document.querySelectorAll(".plausible-analytics-wizard-completed-step");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){if(button.children.length>0){button.children[0].classList+=" hidden"}if(button.id==="connect_plausible_analytics"&&response.status===200){button.innerText=plausible_analytics_i18n.connected}else{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);if(response.data!==undefined){return response.data}else{return response}})},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");if(container.children.length>0){for(let i=0;i0){for(let i=0;i{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;i0){button.children[0].classList.remove("hidden")}button.setAttribute("disabled","disabled");plausible.ajax(form,button)},maybeDisableOptions:function(capabilities){let options=document.querySelectorAll("button[data-caps]");options.forEach(function(option){let caps=option.dataset.caps.split(",");let disable=false;caps.forEach(function(cap){if(capabilities[cap]===false){disable=true}});if(disable===true){if(option.dataset.status==="on"){option.dispatchEvent(new Event("click",{bubbles:true}))}}})},validateInput:function(input){if(input.name==="domain_name"&&input.value.match(/^(https?:\/\/)?(www.)?/).length>0){input.value=input.value.replace(/^(https?:\/\/)?(www.)?/,"")}return input},saveOptionOnNext:function(e){let hash=document.location.hash.replace("#","");if(hash!=="api_token_slide"&&hash!=="domain_name_slide"){return}let form=e.target.closest(".plausible-analytics-wizard-step-section");let inputs=form.getElementsByTagName("INPUT");let options=[];for(let input of inputs){input=plausible.validateInput(input);options.push({name:input.name,value:input.value})}let data=new FormData;data.append("action","plausible_analytics_save_options");data.append("options",JSON.stringify(options));data.append("_nonce",plausible.nonce);plausible.ajax(data).then(response=>{if(hash==="api_token_slide"&&response.success===true){let stats_button=document.getElementById("enable_analytics_dashboard_view_stats_in_wordpress");stats_button.removeAttribute("disabled")}})},disableConnectButton:function(e){let target=e.target;let button=document.getElementById("connect_plausible_analytics");let buttonIsHref=false;if(button===null){let slide_id=document.location.hash;button=document.querySelector(slide_id+" .plausible-analytics-wizard-next-step");buttonIsHref=true}if(button===null){return}if(target.value!==""){if(!buttonIsHref){button.disabled=false}else{button.classList.remove("pointer-events-none");button.classList.replace("bg-gray-200","bg-indigo-600")}return}if(!buttonIsHref){button.disabled=true;button.innerHTML=button.innerHTML.replace("Connected","Connect")}else{button.classList+=" pointer-events-none";button.classList.replace("bg-indigo-600","bg-gray-200")}},createAPIToken:function(e){e.preventDefault();let domain=document.getElementById("domain_name").value;domain=domain.replaceAll("/","%2F");window.open(`${plausible_analytics_hosted_domain}/${domain}/settings/integrations?new_token=WordPress`,"_blank","location=yes,height=768,width=1024,scrollbars=yes,status=no")},showWizard:function(e){let data=new FormData;data.append("action","plausible_analytics_show_wizard");data.append("_nonce",e.target.dataset.nonce);plausible.ajax(data)},toggleWizardStep:function(){if(document.getElementById("plausible-analytics-wizard")===null){return}const hash=document.location.hash.substring(1).replace("_slide","");let allSteps=document.querySelectorAll(".plausible-analytics-wizard-step");let activeSteps=document.querySelectorAll(".plausible-analytics-wizard-active-step");let completedSteps=document.querySelectorAll(".plausible-analytics-wizard-completed-step");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){if(button.children.length>0){button.children[0].classList+=" hidden"}if(button.id==="connect_plausible_analytics"&&response.status===200){button.innerText=plausible_analytics_i18n.connected}else{button.removeAttribute("disabled")}}if(response.status===200||response.status===402){return response.json()}return false}).then(response=>{if(showMessages===true){plausible.showMessages()}let event=new CustomEvent("plausibleAjaxDone",{detail:response});document.dispatchEvent(event);if(response.data!==undefined){return response.data}else{return response}})},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");if(container.children.length>0){for(let i=0;i0){for(let i=0;islides_description['success'] = sprintf( + if ( empty( $settings[ 'enable_analytics_dashboard' ] ) ) { + $this->slides_description[ 'success' ] = sprintf( __( '

Congrats! Your traffic is now being counted without compromising the user experience and privacy of your visitors.

Note that visits from logged in users aren\'t tracked. If you want to track visits for certain user roles, then please specify them in the plugin\'s settings.

Need help? Our documentation is the best place to find most answers right away.

Still haven\'t found the answer you\'re looking for? We\'re here to help. Please contact our support.

', 'plausible-analytics' ), - admin_url( 'admin-ajax.php?action=plausible_analytics_quit_wizard&_nonce=' ) . - wp_create_nonce( 'plausible_analytics_quit_wizard' ) . - '&redirect=tracked_user_roles', + admin_url( 'admin-ajax.php?action=plausible_analytics_quit_wizard&_nonce=' ) . wp_create_nonce( 'plausible_analytics_quit_wizard' ) . '&redirect=tracked_user_roles', 'https://plausible.io/docs?utm_source=WordPress&utm_medium=Referral&utm_campaign=WordPress+plugin', 'https://plausible.io/contact?utm_source=WordPress&utm_medium=Referral&utm_campaign=WordPress+plugin' ); @@ -130,7 +126,7 @@ public function settings_page() { /** * Settings screen */ - $current_tab = ! empty( $_GET['tab'] ) ? $_GET['tab'] : 'general'; + $current_tab = ! empty( $_GET[ 'tab' ] ) ? $_GET[ 'tab' ] : 'general'; ?>
@@ -157,7 +153,7 @@ public function settings_page() { fields[ $current_tab ] as $tab => $field ): ?>
get_wizard_option_properties( $id ); if ( ! empty( $field ) ) { - $hide_header = $field['type'] === 'group'; - - echo call_user_func( [ - $this, - "render_{$field['type']}_field" - ], $field, $hide_header ); + $hide_header = $field[ 'type' ] === 'group'; + + echo call_user_func( + [ + $this, + "render_{$field['type']}_field", + ], + $field, + $hide_header + ); } ?> @@ -423,13 +423,13 @@ class="mt-1 text-sm leading-5 text-gray-500 dark:text-gray-200">

* @return array|mixed */ private function get_wizard_option_properties( $slug ) { - foreach ( $this->fields['general'] as $group ) { - if ( $group['slug'] === $slug ) { + foreach ( $this->fields[ 'general' ] as $group ) { + if ( $group[ 'slug' ] === $slug ) { return $group; } - foreach ( $group['fields'] as $field ) { - if ( $field['slug'] === $slug ) { + foreach ( $group[ 'fields' ] as $field ) { + if ( $field[ 'slug' ] === $slug ) { return $field; } } @@ -441,9 +441,9 @@ private function get_wizard_option_properties( $slug ) { /** * Render Header Navigation. * - * @return void * @since 1.3.0 * @access public + * @return void */ public function render_navigation() { $screen = get_current_screen(); @@ -453,7 +453,7 @@ public function render_navigation() { return; } - $current_tab = ! empty( $_GET['tab'] ) ? $_GET['tab'] : ''; + $current_tab = ! empty( $_GET[ 'tab' ] ) ? $_GET[ 'tab' ] : ''; $tabs = apply_filters( 'plausible_analytics_settings_navigation_tabs', [ @@ -474,9 +474,9 @@ public function render_navigation() { foreach ( $tabs as $tab ) { printf( '%3$s', - esc_url( $tab['url'] ), - esc_attr( $tab['class'] ), - esc_html( $tab['name'] ) + esc_url( $tab[ 'url' ] ), + esc_attr( $tab[ 'class' ] ), + esc_html( $tab[ 'name' ] ) ); } ?> @@ -486,8 +486,8 @@ public function render_navigation() { /** * Render Quick Actions * - * @return string * @since 1.3.0 + * @return string */ private function render_quick_actions() { ob_start(); @@ -495,13 +495,13 @@ private function render_quick_actions() { ?> 0 ) : ?> - + - - + + @@ -512,8 +512,8 @@ private function render_quick_actions() { /** * Get Quick Actions. * - * @return array * @since 1.3.0 + * @return array */ private function get_quick_actions() { $settings = Helpers::get_settings(); @@ -525,7 +525,7 @@ private function get_quick_actions() { 'url' => admin_url( "admin-ajax.php?action=plausible_analytics_show_wizard&_nonce=$nonce&redirect=1" ), 'id' => 'show_wizard', 'target' => '_self', - 'disabled' => ! empty( $settings['self_hosted_domain'] ), + 'disabled' => ! empty( $settings[ 'self_hosted_domain' ] ), ], 'view-docs' => [ 'label' => esc_html__( 'Documentation', 'plausible-analytics' ), @@ -545,13 +545,13 @@ private function get_quick_actions() { /** * Render Group Field. * - * @return string * @since 1.3.0 * @access public + * @return string */ public function render_group_field( array $group, $hide_header = false ) { - $toggle = $group['toggle'] ?? []; - $fields = $group['fields']; + $toggle = $group[ 'toggle' ] ?? []; + $fields = $group[ 'fields' ]; ob_start(); ?>

+ id="">
- +
- - + + @@ -578,7 +578,7 @@ class="
+ for="">
/>
@@ -630,12 +630,12 @@ class="block w-full !border-gray-300 !dark:border-gray-700 !rounded-md focus:rin */ public function render_button_field( array $field ) { ob_start(); - $disabled = isset( $field['disabled'] ) && $field['disabled'] === true; + $disabled = isset( $field[ 'disabled' ] ) && $field[ 'disabled' ] === true; ?>
- - - - - + + + @@ -700,29 +695,29 @@ class="plausible-analytics-toggle
+ name="">
-
@@ -776,9 +771,9 @@ class="w-5 h-12 text-yellow-400">
-
+
-

+

diff --git a/src/Admin/Settings/Page.php b/src/Admin/Settings/Page.php index 742e570..f87c60a 100644 --- a/src/Admin/Settings/Page.php +++ b/src/Admin/Settings/Page.php @@ -54,6 +54,14 @@ class Page extends API { 'hook_type' => 'success', ]; + const CAP_GOALS = 'goals'; + + const CAP_PROPS = 'props'; + + const CAP_FUNNELS = 'funnels'; + + const CAP_REVENUE = 'revenue'; + /** * @var array|array[] $fields */ @@ -117,15 +125,11 @@ public function __construct() { 'value' => $settings[ 'api_token' ], ], [ - 'label' => empty( $settings[ 'domain_name' ] ) || empty( $settings[ 'api_token' ] ) ? - esc_html__( 'Connect', 'plausible-analytics' ) : + 'label' => empty( $settings[ 'domain_name' ] ) || empty( $settings[ 'api_token' ] ) ? esc_html__( 'Connect', 'plausible-analytics' ) : esc_html__( 'Connected', 'plausible-analytics' ), 'slug' => 'connect_plausible_analytics', 'type' => 'button', - 'disabled' => empty( $settings[ 'domain_name' ] ) || - empty( $settings[ 'api_token' ] ) || - ! $this->client instanceof Client || - $this->client->is_api_token_valid(), + 'disabled' => empty( $settings[ 'domain_name' ] ) || empty( $settings[ 'api_token' ] ) || ! $this->client instanceof Client || $this->client->is_api_token_valid(), ], ], ], @@ -145,6 +149,7 @@ public function __construct() { 'slug' => 'enhanced_measurements', 'type' => 'checkbox', 'value' => '404', + 'caps' => [ self::CAP_GOALS ], ], 'outbound-links' => [ 'label' => esc_html__( 'Outbound links', 'plausible-analytics' ), @@ -152,6 +157,7 @@ public function __construct() { 'slug' => 'enhanced_measurements', 'type' => 'checkbox', 'value' => 'outbound-links', + 'caps' => [ self::CAP_GOALS ], ], 'file-downloads' => [ 'label' => esc_html__( 'File downloads', 'plausible-analytics' ), @@ -159,6 +165,7 @@ public function __construct() { 'slug' => 'enhanced_measurements', 'type' => 'checkbox', 'value' => 'file-downloads', + 'caps' => [ self::CAP_GOALS ], ], 'search' => [ 'label' => esc_html__( 'Search queries', 'plausible-analytics' ), @@ -166,6 +173,7 @@ public function __construct() { 'slug' => 'enhanced_measurements', 'type' => 'checkbox', 'value' => 'search', + 'caps' => [ self::CAP_GOALS, self::CAP_PROPS ], ], 'tagged-events' => [ 'label' => esc_html__( 'Custom events', 'plausible-analytics' ), @@ -173,14 +181,15 @@ public function __construct() { 'slug' => 'enhanced_measurements', 'type' => 'checkbox', 'value' => 'tagged-events', + 'caps' => [ self::CAP_GOALS ], ], 'revenue' => [ - 'label' => esc_html__( 'Ecommerce revenue', 'plausible-analytics' ), - 'docs' => 'https://plausible.io/wordpress-analytics-plugin#how-to-track-ecommerce-revenue', - 'slug' => 'enhanced_measurements', - 'type' => 'checkbox', - 'value' => 'revenue', - 'disabled' => ! empty( $settings[ 'self_hosted_domain' ] ), + 'label' => esc_html__( 'Ecommerce revenue', 'plausible-analytics' ), + 'docs' => 'https://plausible.io/wordpress-analytics-plugin#how-to-track-ecommerce-revenue', + 'slug' => 'enhanced_measurements', + 'type' => 'checkbox', + 'value' => 'revenue', + 'caps' => [ self::CAP_GOALS, self::CAP_FUNNELS, self::CAP_PROPS, self::CAP_REVENUE ], ], 'pageview-props' => [ 'label' => esc_html__( 'Authors and categories', 'plausible-analytics' ), @@ -188,6 +197,7 @@ public function __construct() { 'slug' => 'enhanced_measurements', 'type' => 'checkbox', 'value' => 'pageview-props', + 'caps' => [ self::CAP_PROPS ], ], 'form-completions' => [ 'label' => esc_html__( 'Form completions', 'plausible-analytics' ), @@ -195,6 +205,7 @@ public function __construct() { 'slug' => 'enhanced_measurements', 'type' => 'checkbox', 'value' => 'form-completions', + 'caps' => [ self::CAP_GOALS ], ], 'hash' => [ 'label' => esc_html__( 'Hash-based routing', 'plausible-analytics' ), @@ -202,6 +213,7 @@ public function __construct() { 'slug' => 'enhanced_measurements', 'type' => 'checkbox', 'value' => 'hash', + 'caps' => [], ], 'compat' => [ 'label' => esc_html__( 'IE compatibility', 'plausible-analytics' ), @@ -209,6 +221,7 @@ public function __construct() { 'slug' => 'enhanced_measurements', 'type' => 'checkbox', 'value' => 'compat', + 'caps' => [], ], ], ], @@ -227,8 +240,7 @@ public function __construct() { get_site_url( null, rest_get_url_prefix() ), empty( Helpers::get_settings()[ 'proxy_enabled' ] - ) ? 'a random directory/file for storing the JS file' : - 'a JS file, called ' . str_replace( + ) ? 'a random directory/file for storing the JS file' : 'a JS file, called ' . str_replace( ABSPATH, '', Helpers::get_proxy_resource( 'cache_dir' ) . Helpers::get_proxy_resource( @@ -263,8 +275,7 @@ public function __construct() { 'slug' => 'enable_analytics_dashboard', 'type' => 'checkbox', 'value' => 'on', - 'disabled' => empty( Helpers::get_settings()[ 'api_token' ] ) && - empty( Helpers::get_settings()[ 'self_hosted_domain' ] ), + 'disabled' => empty( Helpers::get_settings()[ 'api_token' ] ) && empty( Helpers::get_settings()[ 'self_hosted_domain' ] ), ], ], ], @@ -367,8 +378,7 @@ public function __construct() { 'label' => esc_html__( 'Domain name', 'plausible-analytics' ), 'slug' => 'self_hosted_domain', 'type' => 'text', - 'value' => defined( 'PLAUSIBLE_SELF_HOSTED_DOMAIN' ) ? PLAUSIBLE_SELF_HOSTED_DOMAIN : - $settings[ '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(), ], @@ -552,8 +562,7 @@ public function register_menu() { /** * Don't show the Analytics dashboard, if View Stats is disabled. */ - if ( ! empty( $settings[ 'enable_analytics_dashboard' ] ) || - ( ! empty( $settings[ 'self_hosted_domain' ] ) && ! empty( $settings[ 'self_hosted_shared_link' ] ) ) ) { + if ( ! empty( $settings[ 'enable_analytics_dashboard' ] ) || ( ! empty( $settings[ 'self_hosted_domain' ] ) && ! empty( $settings[ 'self_hosted_shared_link' ] ) ) ) { // Setup `Analytics` page under Dashboard. add_dashboard_page( esc_html__( 'Analytics', 'plausible-analytics' ), @@ -649,9 +658,7 @@ public function render_analytics_dashboard() { * For regular users, the shared link is provisioned by the API, so it shouldn't be empty. * @since v2.0.3 */ - if ( ( ! $self_hosted && ! empty( $analytics_enabled ) && ! empty( $shared_link ) ) || - ( $self_hosted && ! empty( $shared_link ) ) || - strpos( $shared_link, 'XXXXXX' ) !== false ) { + if ( ( ! $self_hosted && ! empty( $analytics_enabled ) && ! empty( $shared_link ) ) || ( $self_hosted && ! empty( $shared_link ) ) || strpos( $shared_link, 'XXXXXX' ) !== false ) { $page_url = isset( $_GET[ 'page-url' ] ) ? esc_url( $_GET[ 'page-url' ] ) : ''; // Append individual page URL if it exists. @@ -720,4 +727,20 @@ public function render_analytics_dashboard() { get_capabilities(); if ( $capabilities instanceof Capabilities ) { @@ -212,7 +212,47 @@ private function send_json_error( $e, $error_message ) { Messages::set_error( sprintf( $error_message, $message ) ); - wp_send_json_error( null, $code ); + $caps = $this->update_capabilities(); + + wp_send_json_error( [ 'capabilities' => $caps ], $code ); + } + + /** + * Stores the capabilities for the currently entered API token in the DB for later use. + * + * @param $token + * + * @return false|array + * + * @codeCoverageIgnore + */ + private function update_capabilities( $token = '' ) { + $client_factory = new ClientFactory( $token ); + /** @var Client $client */ + $client = $client_factory->build(); + + if ( ! $client instanceof Client ) { + return false; + } + + /** @var Client\Model\CapabilitiesFeatures $features */ + $features = $client->get_features(); + + if ( ! $features ) { + return false; + } + + $caps = [ + 'funnels' => $features->getFunnels(), + 'goals' => $features->getGoals(), + 'props' => $features->getProps(), + 'revenue' => $features->getRevenueGoals(), + 'stats' => $features->getStatsApi(), + ]; + + update_option( 'plausible_analytics_api_token_caps', $caps ); + + return $caps; } /**