From 5fc6c6990c5d444cc1d5ffff713efe69457d51b8 Mon Sep 17 00:00:00 2001 From: Daan van den Bergh <18595395+Dan0sz@users.noreply.github.com> Date: Sun, 21 Jun 2026 14:59:24 +0200 Subject: [PATCH 01/74] First stab at settings screen. --- assets/src/js/admin/main.js | 90 +++++++++++++++++-- src/Admin/Settings/API.php | 62 ++++++++++++- src/Admin/Settings/OptionsParser.php | 75 ++++++++++++++++ src/Admin/Settings/Page.php | 9 ++ src/Ajax.php | 42 +++++++-- src/ClientFactory.php | 4 +- src/Helpers.php | 91 ++++++++++++++++++- tests/HelpersMultilangTest.php | 130 +++++++++++++++++++++++++++ tests/OptionsParserTest.php | 72 +++++++++++++++ 9 files changed, 561 insertions(+), 14 deletions(-) create mode 100644 src/Admin/Settings/OptionsParser.php create mode 100644 tests/HelpersMultilangTest.php create mode 100644 tests/OptionsParserTest.php diff --git a/assets/src/js/admin/main.js b/assets/src/js/admin/main.js index a870b69f..15c0fb51 100644 --- a/assets/src/js/admin/main.js +++ b/assets/src/js/admin/main.js @@ -20,6 +20,9 @@ document.addEventListener('DOMContentLoaded', () => { createAPITokenElems: document.getElementsByClassName('plausible-create-api-token'), buttonElems: document.getElementsByClassName('plausible-analytics-button'), stepElems: document.getElementsByClassName('plausible-analytics-wizard-next-step'), + multilangPairInputs: document.querySelectorAll('.multilang-domain-pair input'), + multilangSelector: document.getElementById('multilang_domain_selector'), + multilangConnectButtons: document.querySelectorAll('.multilang-domain-pair .plausible-analytics-connect-button'), /** * Bind events. @@ -77,6 +80,22 @@ document.addEventListener('DOMContentLoaded', () => { } } + if (this.multilangPairInputs.length > 0) { + for (let i = 0; i < this.multilangPairInputs.length; i++) { + this.multilangPairInputs[i].addEventListener('keyup', this.disableConnectButton); + } + } + + if (this.multilangSelector !== null) { + this.multilangSelector.addEventListener('change', this.switchMultilangDomain); + } + + if (this.multilangConnectButtons.length > 0) { + for (let i = 0; i < this.multilangConnectButtons.length; i++) { + this.multilangConnectButtons[i].addEventListener('click', this.saveMultilangOption); + } + } + /** * Run once on pageload. */ @@ -378,6 +397,57 @@ document.addEventListener('DOMContentLoaded', () => { plausible.ajax(form, button); }, + /** + * Switch visible multilang domain pair. + * + * @param e + */ + switchMultilangDomain: function (e) { + const selectedDomain = e.target.value; + const pairs = document.querySelectorAll('.multilang-domain-pair'); + + pairs.forEach(function (pair) { + if (pair.dataset.wpmlDomain === selectedDomain) { + pair.classList.remove('hidden'); + } else { + pair.classList.add('hidden'); + } + }); + }, + + /** + * Save multilang option (Domain Name + Plugin Token pair). + * + * @param e + */ + saveMultilangOption: function (e) { + e.preventDefault(); + + const button = e.target.closest('button'); + const pair = button.closest('.multilang-domain-pair'); + const inputs = pair.querySelectorAll('input'); + const form = new FormData(); + let options = []; + + inputs.forEach(function (input) { + input = plausible.validateInput(input); + + options.push({name: input.name, value: input.value}); + }); + + form.append('action', 'plausible_analytics_save_options'); + form.append('options', JSON.stringify(options)); + form.append('_nonce', plausible.nonce); + + if (button.children.length > 1) { + button.children[1].classList.remove('hidden'); + } + + button.setAttribute('disabled', 'disabled'); + + plausible.ajax(form, button); + }, + /** * Disable options based on the capabilities retrieved from the API. * @@ -413,7 +483,7 @@ document.addEventListener('DOMContentLoaded', () => { */ validateInput: function (input) { // Strip http(s)://(www.) from domain_name before sending it. - if (input.name === 'domain_name' && input.value.match(/^(https?:\/\/)?(www.)?/).length > 0) { + if ((input.name === 'domain_name' || input.name.startsWith('domain_name[')) && input.value.match(/^(https?:\/\/)?(www.)?/).length > 0) { input.value = input.value.replace(/^(https?:\/\/)?(www.)?/, ''); } @@ -467,7 +537,8 @@ document.addEventListener('DOMContentLoaded', () => { */ disableConnectButton: function (e) { let target = e.target; - let button = document.getElementById('connect_plausible_analytics'); + let pair = target.closest('.multilang-domain-pair'); + let button = pair ? pair.querySelector('.plausible-analytics-connect-button') : document.getElementById('connect_plausible_analytics'); let buttonIsHref = false; if (button === null) { @@ -508,7 +579,13 @@ document.addEventListener('DOMContentLoaded', () => { createAPIToken: function (e) { e.preventDefault(); - let domain = document.getElementById('domain_name').value; + let domainElem = document.querySelector('.multilang-domain-pair:not(.hidden) [id^="domain_name"]'); + + if (domainElem === null) { + domainElem = document.getElementById('domain_name'); + } + + let domain = domainElem ? domainElem.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'); @@ -610,10 +687,13 @@ document.addEventListener('DOMContentLoaded', () => { ).then(response => { if (button) { if (button.children.length > 0) { - button.children[0].classList += ' hidden'; + let spinner = button.querySelector('svg'); + if (spinner) { + spinner.classList.add('hidden'); + } } - if (button.id === 'connect_plausible_analytics' && response.status === 200) { + if ((button.id === 'connect_plausible_analytics' || button.classList.contains('plausible-analytics-connect-button')) && response.status === 200) { button.innerText = plausible_analytics_i18n.connected; } else { button.removeAttribute('disabled'); diff --git a/src/Admin/Settings/API.php b/src/Admin/Settings/API.php index 66f85a24..c3c1e743 100644 --- a/src/Admin/Settings/API.php +++ b/src/Admin/Settings/API.php @@ -147,7 +147,7 @@ public function settings_page() { render_navigation(); ?> -