diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 75a69633..c24f59b6 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -4,8 +4,8 @@ # # FILE INFORMATION # DEFGROUP: Gitea.Workflow -# INGROUP: mokocli.Automation -# VERSION: 01.00.00 +# INGROUP: moko-platform.Automation +# VERSION: 02.47.48 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/CHANGELOG.md b/CHANGELOG.md index c3fbb6a2..0255a01c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ INGROUP: MokoSuiteClient.Documentation REPO: https://github.com/mokoconsulting-tech/mokosuiteclient PATH: ./CHANGELOG.md - VERSION: 02.47.26 + VERSION: 02.47.48 BRIEF: Version history using `Keep a Changelog` --> diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index a9e3c072..551d08bc 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -14,7 +14,7 @@ DEFGROUP: Joomla.Plugin INGROUP: MokoSuiteClient.Documentation REPO: https://github.com/mokoconsulting-tech/mokosuiteclient - VERSION: 02.47.26 + VERSION: 02.47.48 PATH: ./CODE_OF_CONDUCT.md BRIEF: Reference + packaging repo for Moko Consulting Developer GPT Other Default --> diff --git a/GOVERNANCE.md b/GOVERNANCE.md index 6f407854..daf9a055 100644 --- a/GOVERNANCE.md +++ b/GOVERNANCE.md @@ -19,7 +19,7 @@ DEFGROUP: mokoconsulting-tech.MokoSuiteClientBrand INGROUP: MokoStandards.Governance REPO: https://github.com/mokoconsulting-tech/MokoSuiteClientBrand - VERSION: 02.47.26 + VERSION: 02.47.48 PATH: /GOVERNANCE.md BRIEF: Project governance rules, roles, and decision process for MokoSuiteClientBrand --> diff --git a/LICENSE.md b/LICENSE.md index 0167d8db..f7f03e47 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -15,7 +15,7 @@ INGROUP: MokoSuiteClient.Documentation REPO: https://github.com/mokoconsulting-tech/mokosuiteclient PATH: ./LICENSE.md - VERSION: 02.47.26 + VERSION: 02.47.48 BRIEF: Project license (GPL-3.0-or-later) --> GNU GENERAL PUBLIC LICENSE diff --git a/README.md b/README.md index 9b5de10d..260363a6 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ DEFGROUP: Joomla.Plugin INGROUP: MokoSuiteClient REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteClient - VERSION: 02.47.26 + VERSION: 02.47.48 PATH: /README.md BRIEF: MokoSuiteClient platform plugin for Joomla --> diff --git a/SECURITY.md b/SECURITY.md index 4e99535f..5efee604 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -23,7 +23,7 @@ DEFGROUP: [PROJECT_NAME] INGROUP: [PROJECT_NAME].Documentation REPO: [REPOSITORY_URL] PATH: /SECURITY.md -VERSION: 02.47.26 +VERSION: 02.47.48 BRIEF: Security vulnerability reporting and handling policy --> diff --git a/docs/guides/build-guide.md b/docs/guides/build-guide.md index 35fe04a7..a141e915 100644 --- a/docs/guides/build-guide.md +++ b/docs/guides/build-guide.md @@ -11,13 +11,13 @@ INGROUP: MokoSuiteClient.Build REPO: https://github.com/mokoconsulting-tech/mokosuiteclient FILE: build-guide.md - VERSION: 02.47.26 + VERSION: 02.47.48 PATH: /docs/guides/ BRIEF: Build and packaging guide for the MokoSuiteClient system plugin NOTE: Defines environment setup, repository layout, packaging rules, and release preparation --> -# MokoSuiteClient Build Guide (VERSION: 02.47.26) +# MokoSuiteClient Build Guide (VERSION: 02.47.48) ## 1. Purpose diff --git a/docs/guides/configuration-guide.md b/docs/guides/configuration-guide.md index 4e3bb9f8..492fd1be 100644 --- a/docs/guides/configuration-guide.md +++ b/docs/guides/configuration-guide.md @@ -10,13 +10,13 @@ DEFGROUP: Joomla.Plugin INGROUP: MokoSuiteClient.Guides REPO: https://github.com/mokoconsulting-tech/mokosuiteclient - VERSION: 02.47.26 + VERSION: 02.47.48 PATH: /docs/guides/configuration-guide.md BRIEF: Configuration guide for the MokoSuiteClient system plugin NOTE: Defines plugin parameters, expected behaviors, and recommended defaults --> -# MokoSuiteClient Configuration Guide (VERSION: 02.47.26) +# MokoSuiteClient Configuration Guide (VERSION: 02.47.48) ## 1. Objective diff --git a/docs/guides/installation-guide.md b/docs/guides/installation-guide.md index 58591542..fb2d2b9d 100644 --- a/docs/guides/installation-guide.md +++ b/docs/guides/installation-guide.md @@ -10,13 +10,13 @@ DEFGROUP: Joomla.Plugin INGROUP: MokoSuiteClient.Guides REPO: https://github.com/mokoconsulting-tech/mokosuiteclient - VERSION: 02.47.26 + VERSION: 02.47.48 PATH: /docs/guides/installation-guide.md BRIEF: Installation guide for the MokoSuiteClient system plugin NOTE: First document in the guide set --> -# MokoSuiteClient Installation Guide (VERSION: 02.47.26) +# MokoSuiteClient Installation Guide (VERSION: 02.47.48) ## Introduction diff --git a/docs/guides/operations-guide.md b/docs/guides/operations-guide.md index bb4523ec..9fb283f3 100644 --- a/docs/guides/operations-guide.md +++ b/docs/guides/operations-guide.md @@ -10,13 +10,13 @@ DEFGROUP: Joomla.Plugin INGROUP: MokoSuiteClient.Guides REPO: https://github.com/mokoconsulting-tech/mokosuiteclient - VERSION: 02.47.26 + VERSION: 02.47.48 PATH: /docs/guides/operations-guide.md BRIEF: Operational guide for administering and managing the MokoSuiteClient system plugin NOTE: Defines lifecycle, responsibilities, and operational behaviors --> -# MokoSuiteClient Operations Guide (VERSION: 02.47.26) +# MokoSuiteClient Operations Guide (VERSION: 02.47.48) ## Introduction diff --git a/docs/guides/rollback-and-recovery-guide.md b/docs/guides/rollback-and-recovery-guide.md index 84c9edb6..d4589ffa 100644 --- a/docs/guides/rollback-and-recovery-guide.md +++ b/docs/guides/rollback-and-recovery-guide.md @@ -10,13 +10,13 @@ DEFGROUP: Joomla.Plugin INGROUP: MokoSuiteClient.Guides REPO: https://github.com/mokoconsulting-tech/mokosuiteclient - VERSION: 02.47.26 + VERSION: 02.47.48 PATH: /docs/guides/rollback-and-recovery-guide.md BRIEF: Rollback and recovery guide for restoring stable operation after plugin related incidents NOTE: Completes the core guide set for Suite plugin governance --> -# MokoSuiteClient Rollback and Recovery Guide (VERSION: 02.47.26) +# MokoSuiteClient Rollback and Recovery Guide (VERSION: 02.47.48) ## Introduction diff --git a/docs/guides/testing-guide.md b/docs/guides/testing-guide.md index d93a4e7c..254cc67b 100644 --- a/docs/guides/testing-guide.md +++ b/docs/guides/testing-guide.md @@ -7,13 +7,13 @@ DEFGROUP: Joomla.Plugin INGROUP: MokoSuiteClient.Guides REPO: https://github.com/mokoconsulting-tech/mokosuiteclient - VERSION: 02.47.26 + VERSION: 02.47.48 PATH: /docs/guides/testing-guide.md BRIEF: Testing guide for MokoSuiteClient v02.01.08 NOTE: Covers manual test procedures for language overrides, install/uninstall, and configuration --> -# MokoSuiteClient Testing Guide (VERSION: 02.47.26) +# MokoSuiteClient Testing Guide (VERSION: 02.47.48) ## 1. Prerequisites diff --git a/docs/guides/troubleshooting-guide.md b/docs/guides/troubleshooting-guide.md index 36731463..622233a3 100644 --- a/docs/guides/troubleshooting-guide.md +++ b/docs/guides/troubleshooting-guide.md @@ -10,13 +10,13 @@ DEFGROUP: Joomla.Plugin INGROUP: MokoSuiteClient.Guides REPO: https://github.com/mokoconsulting-tech/mokosuiteclient - VERSION: 02.47.26 + VERSION: 02.47.48 PATH: /docs/guides/troubleshooting-guide.md BRIEF: Troubleshooting guide for diagnosing and resolving issues related to the MokoSuiteClient plugin NOTE: Designed for administrators and Suite operations teams --> -# MokoSuiteClient Troubleshooting Guide (VERSION: 02.47.26) +# MokoSuiteClient Troubleshooting Guide (VERSION: 02.47.48) ## Introduction diff --git a/docs/guides/upgrade-and-versioning-guide.md b/docs/guides/upgrade-and-versioning-guide.md index c77bf261..954d33a8 100644 --- a/docs/guides/upgrade-and-versioning-guide.md +++ b/docs/guides/upgrade-and-versioning-guide.md @@ -10,13 +10,13 @@ DEFGROUP: Joomla.Plugin INGROUP: MokoSuiteClient.Guides REPO: https://github.com/mokoconsulting-tech/mokosuiteclient - VERSION: 02.47.26 + VERSION: 02.47.48 PATH: /docs/guides/upgrade-and-versioning-guide.md BRIEF: Guide for updating, versioning, and maintaining the MokoSuiteClient plugin NOTE: Defines release flow, version rules, and upgrade validation --> -# MokoSuiteClient Upgrade and Versioning Guide (VERSION: 02.47.26) +# MokoSuiteClient Upgrade and Versioning Guide (VERSION: 02.47.48) ## Introduction diff --git a/docs/index.md b/docs/index.md index 075b3b81..80439ffd 100644 --- a/docs/index.md +++ b/docs/index.md @@ -10,13 +10,13 @@ DEFGROUP: Joomla.Plugin INGROUP: MokoSuiteClient.Documentation REPO: https://github.com/mokoconsulting-tech/mokosuiteclient - VERSION: 02.47.26 + VERSION: 02.47.48 PATH: /docs/index.md BRIEF: Master index of all documentation for the MokoSuiteClient plugin NOTE: Automatically maintained index for all guide canvases --> -# MokoSuiteClient Documentation Index (VERSION: 02.47.26) +# MokoSuiteClient Documentation Index (VERSION: 02.47.48) ## Introduction diff --git a/docs/plugin-basic.md b/docs/plugin-basic.md index 06ee42ce..966fb7b9 100644 --- a/docs/plugin-basic.md +++ b/docs/plugin-basic.md @@ -11,12 +11,12 @@ INGROUP: MokoSuiteClient REPO: https://github.com/mokoconsulting-tech/mokosuiteclient PATH: /docs/plugin-basic.md - VERSION: 02.47.26 + VERSION: 02.47.48 BRIEF: Baseline documentation for the MokoSuiteClient system plugin NOTE: Foundational reference for internal and external stakeholders --> -# MokoSuiteClient Plugin Overview (VERSION: 02.47.26) +# MokoSuiteClient Plugin Overview (VERSION: 02.47.48) ## Introduction diff --git a/docs/update-server.md b/docs/update-server.md index aa5fbb1c..de1fb183 100644 --- a/docs/update-server.md +++ b/docs/update-server.md @@ -10,7 +10,7 @@ DEFGROUP: MokoSuiteClient.Documentation INGROUP: MokoStandards.Templates REPO: https://github.com/mokoconsulting-tech/MokoSuiteClient PATH: /docs/update-server.md -VERSION: 02.47.26 +VERSION: 02.47.48 BRIEF: How this extension's Joomla update server file (update.xml) is managed --> diff --git a/source/packages/com_mokosuiteclient/admin/tmpl/dashboard/default.php b/source/packages/com_mokosuiteclient/admin/tmpl/dashboard/default.php index 9f6c4f80..c627f3a7 100644 --- a/source/packages/com_mokosuiteclient/admin/tmpl/dashboard/default.php +++ b/source/packages/com_mokosuiteclient/admin/tmpl/dashboard/default.php @@ -48,77 +48,36 @@ $actionLogsEnabled = Joomla\CMS\Component\ComponentHelper::isEnabled('com_action -
-
-
- - escape($siteInfo->sitename); ?> -
-
- MokoSuite - escape($siteInfo->mokosuiteclient_version); ?> -
+
+
+ + escape($siteInfo->sitename); ?> + MokoSuite escape($siteInfo->mokosuiteclient_version); ?> supportPin)): ?> -
- Support PIN - escape($this->supportPin); ?> -
+ escape($this->supportPin); ?> + -
- Joomla - escape($siteInfo->joomla_version); ?> -
-
- PHP - escape($siteInfo->php_version); ?> -
-
- - escape($siteInfo->db_type); ?> -
+ Joomla escape($siteInfo->joomla_version); ?> + PHP escape($siteInfo->php_version); ?> + escape($siteInfo->db_type); ?> debug): ?> -
- -
+ Debug ON offline): ?> -
- -
+ Offline -
+ escape($_SERVER['REMOTE_ADDR'] ?? ''); ?> -
+
- - -
- 'icon-cogs', - 'mod_mokosuiteclient_cpanel' => 'icon-tachometer-alt', - 'mod_mokosuiteclient_menu' => 'icon-bars', - 'mod_mokosuiteclient_cache' => 'icon-bolt', - 'mod_mokosuiteclient_categories' => 'icon-folder', - ]; - $extCount = count($mokoExts); - $colClass = $extCount > 0 ? 'col-' . max(1, (int) floor(12 / $extCount)) : 'col'; - foreach ($mokoExts as $ext): - $icon = $extIcons[$ext->element] ?? 'icon-puzzle-piece'; - $label = str_replace(['mod_mokosuiteclient_', 'com_mokosuiteclient'], ['', 'Component'], $ext->element); - $label = ucfirst($label ?: 'Component'); - ?> -
- - escape($label); ?> - escape($ext->version); ?> -
- -
- @@ -219,7 +178,7 @@ $actionLogsEnabled = Joomla\CMS\Component\ComponentHelper::isEnabled('com_action
-
+
diff --git a/source/packages/com_mokosuiteclient/media/js/dashboard.js b/source/packages/com_mokosuiteclient/media/js/dashboard.js index 05335437..065fde22 100644 --- a/source/packages/com_mokosuiteclient/media/js/dashboard.js +++ b/source/packages/com_mokosuiteclient/media/js/dashboard.js @@ -110,6 +110,40 @@ document.addEventListener('DOMContentLoaded', function () { }); } + // Heartbeat + PIN send button + var hbBtn = document.getElementById('mokosuiteclient-btn-heartbeat-pin'); + if (hbBtn) { + hbBtn.addEventListener('click', function () { + var btn = this; + var url = btn.dataset.url; + var token = btn.dataset.token; + var icon = btn.querySelector('span'); + + btn.disabled = true; + if (icon) icon.className = 'icon-spinner icon-spin'; + + var fd = new FormData(); + fd.append(token, '1'); + + fetch(url, {method: 'POST', body: fd, headers: {'X-Requested-With': 'XMLHttpRequest'}}) + .then(function (r) { return r.json(); }) + .then(function (d) { + if (d.success) { + Joomla.renderMessages({message: [d.message || 'Heartbeat sent to HQ.']}); + } else { + Joomla.renderMessages({error: [d.message || 'Heartbeat failed.']}); + } + }) + .catch(function () { + Joomla.renderMessages({error: ['Network error sending heartbeat.']}); + }) + .finally(function () { + btn.disabled = false; + if (icon) icon.className = 'icon-upload'; + }); + }); + } + // Akeeba import buttons ['btn-import-admintools', 'btn-import-ats-dash'].forEach(function(id) { var btn = document.getElementById(id); diff --git a/source/packages/com_mokosuiteclient/mokosuiteclient.xml b/source/packages/com_mokosuiteclient/mokosuiteclient.xml index afa55649..30006a05 100644 --- a/source/packages/com_mokosuiteclient/mokosuiteclient.xml +++ b/source/packages/com_mokosuiteclient/mokosuiteclient.xml @@ -20,7 +20,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 02.47.26 + 02.47.48 MokoSuiteClient admin dashboard and REST API. Provides a control panel for managing MokoSuiteClient feature plugins, site health monitoring, and remote management endpoints. Moko\Component\MokoSuiteClient diff --git a/source/packages/mod_mokosuiteclient_cache/mod_mokosuiteclient_cache.xml b/source/packages/mod_mokosuiteclient_cache/mod_mokosuiteclient_cache.xml index b710b04e..a25bb47f 100644 --- a/source/packages/mod_mokosuiteclient_cache/mod_mokosuiteclient_cache.xml +++ b/source/packages/mod_mokosuiteclient_cache/mod_mokosuiteclient_cache.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 02.47.26 + 02.47.48 MOD_MOKOSUITECLIENT_CACHE_DESC Moko\Module\MokoSuiteClientCache diff --git a/source/packages/mod_mokosuiteclient_cache/tmpl/default.php b/source/packages/mod_mokosuiteclient_cache/tmpl/default.php index 4ea7e30d..c1614b1e 100644 --- a/source/packages/mod_mokosuiteclient_cache/tmpl/default.php +++ b/source/packages/mod_mokosuiteclient_cache/tmpl/default.php @@ -11,33 +11,29 @@ defined('_JEXEC') or die; use Joomla\CMS\Session\Session; $token = Session::getFormToken(); -$cacheUrl = 'index.php?option=com_mokosuiteclient&task=clearCache&format=json'; -$tempUrl = 'index.php?option=com_mokosuiteclient&task=clearTemp&format=json'; +$cacheUrl = 'index.php?option=com_mokosuiteclient&task=display.clearCache&format=json'; +$tempUrl = 'index.php?option=com_mokosuiteclient&task=display.clearTemp&format=json'; $domain = $domain ?? ''; ?> - - -
- - - | - - Clear: - - Cache + +
+ +
+
+
+
+ +
+ diff --git a/source/packages/mod_mokosuiteclient_categories/mod_mokosuiteclient_categories.xml b/source/packages/mod_mokosuiteclient_categories/mod_mokosuiteclient_categories.xml index fb558792..6d14998b 100644 --- a/source/packages/mod_mokosuiteclient_categories/mod_mokosuiteclient_categories.xml +++ b/source/packages/mod_mokosuiteclient_categories/mod_mokosuiteclient_categories.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 02.47.26 + 02.47.48 MOD_MOKOSUITECLIENT_CATEGORIES_DESC Moko\Module\MokoSuiteClientCategories diff --git a/source/packages/mod_mokosuiteclient_cpanel/mod_mokosuiteclient_cpanel.xml b/source/packages/mod_mokosuiteclient_cpanel/mod_mokosuiteclient_cpanel.xml index 3c6d8d83..60eaa47a 100644 --- a/source/packages/mod_mokosuiteclient_cpanel/mod_mokosuiteclient_cpanel.xml +++ b/source/packages/mod_mokosuiteclient_cpanel/mod_mokosuiteclient_cpanel.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 02.47.26 + 02.47.48 MOD_MOKOSUITECLIENT_CPANEL_DESC Moko\Module\MokoSuiteClientCpanel diff --git a/source/packages/mod_mokosuiteclient_cpanel/tmpl/default.php b/source/packages/mod_mokosuiteclient_cpanel/tmpl/default.php index 7ab53552..29412f9e 100644 --- a/source/packages/mod_mokosuiteclient_cpanel/tmpl/default.php +++ b/source/packages/mod_mokosuiteclient_cpanel/tmpl/default.php @@ -8,6 +8,7 @@ defined('_JEXEC') or die; +use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; use Joomla\CMS\Session\Session; @@ -60,176 +61,30 @@ $diskColor = ($diskPct !== null && $diskPct > 90) ? 'bg-danger' : (($diskPct !== ?>
- -
- - - MokoSuite - mokosuiteclient_version ?? ''); ?> - - +
+ getIdentity()->authorise('core.manage', 'com_mokosuiteclient'); ?> + + + + + sitename ?? ''); ?> + MokoSuite mokosuiteclient_version ?? ''); ?> + + + + Joomla joomla_version ?? ''); ?> + PHP php_version ?? ''); ?> + db_type ?? ''); ?> debug)): ?> - Debug + Debug ON offline)): ?> Offline - moko_updates ?? 0) > 0): ?> - - moko_updates; ?> MokoSuite updatemoko_updates > 1 ? 's' : ''; ?> - - - updates > 0 && $counts->updates !== ($counts->moko_updates ?? 0)): ?> - - updates - ($counts->moko_updates ?? 0); ?> updateupdates - ($counts->moko_updates ?? 0)) > 1 ? 's' : ''; ?> - - - - - - - + + +
- - - -
- - - -
-
-
- - - Healthy - - - DB Error - -
-
-
-
- articles; ?> - Articles -
-
-
-
- users; ?> - Users -
-
-
-
- updates > 0): ?> - updates; ?> - Updates - - - Up to date - -
-
-
- - -
- - - - % - - free_mb ?? 0) / 1024, 1); ?>G free - - - - - - - - - SSL days_remaining; ?>d - - - - Jjoomla_version ?? ''); ?> / PHP php_version ?? ''); ?> - - - - - element] ?? $p->element; - $badge = $p->enabled ? 'bg-success' : 'bg-secondary'; - $icon = $p->enabled ? 'icon-check' : 'icon-times'; - $configUrl = Route::_('index.php?option=com_plugins&task=plugin.edit&extension_id=' . (int) $p->extension_id); - ?> - - - - - - - - - - Check Updates - - updates > 0): ?> - - updates; ?> updateupdates > 1 ? 's' : ''; ?> - - - -
- - -
- - diff --git a/source/packages/mod_mokosuiteclient_menu/mod_mokosuiteclient_menu.xml b/source/packages/mod_mokosuiteclient_menu/mod_mokosuiteclient_menu.xml index eb735cd0..6d0d50c6 100644 --- a/source/packages/mod_mokosuiteclient_menu/mod_mokosuiteclient_menu.xml +++ b/source/packages/mod_mokosuiteclient_menu/mod_mokosuiteclient_menu.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 02.47.26 + 02.47.48 MokoSuiteClient admin sidebar menu — renders a dedicated MokoSuiteClient section in the admin menu before Joomla's default menu. Moko\Module\MokoSuiteClientMenu diff --git a/source/packages/plg_system_mokosuiteclient/Extension/MokoSuiteClient.php b/source/packages/plg_system_mokosuiteclient/Extension/MokoSuiteClient.php index 0e66dd11..8362280b 100644 --- a/source/packages/plg_system_mokosuiteclient/Extension/MokoSuiteClient.php +++ b/source/packages/plg_system_mokosuiteclient/Extension/MokoSuiteClient.php @@ -22,7 +22,7 @@ * DEFGROUP: Joomla.Plugin * INGROUP: MokoSuiteClient * REPO: https://github.com/mokoconsulting-tech/mokosuiteclient - * VERSION: 02.47.26 + * VERSION: 02.47.48 * PATH: /src/Extension/MokoSuiteClient.php * NOTE: Core system plugin for MokoSuiteClient admin tools suite */ diff --git a/source/packages/plg_system_mokosuiteclient/Field/CopyableTokenField.php b/source/packages/plg_system_mokosuiteclient/Field/CopyableTokenField.php index f9bd25c1..f73a88b9 100644 --- a/source/packages/plg_system_mokosuiteclient/Field/CopyableTokenField.php +++ b/source/packages/plg_system_mokosuiteclient/Field/CopyableTokenField.php @@ -8,7 +8,7 @@ * FILE INFORMATION * DEFGROUP: Joomla.Plugin * INGROUP: MokoSuiteClient - * VERSION: 02.47.26 + * VERSION: 02.47.48 * PATH: /src/Field/CopyableTokenField.php * BRIEF: Read-only token field with a copy-to-clipboard button */ diff --git a/source/packages/plg_system_mokosuiteclient/mokosuiteclient.xml b/source/packages/plg_system_mokosuiteclient/mokosuiteclient.xml index 6998a1ca..0205bc8e 100644 --- a/source/packages/plg_system_mokosuiteclient/mokosuiteclient.xml +++ b/source/packages/plg_system_mokosuiteclient/mokosuiteclient.xml @@ -30,7 +30,7 @@ GNU General Public License version 3 or later; see LICENSE.md hello@mokoconsulting.tech https://mokoconsulting.tech - 02.47.26 + 02.47.48 MokoSuiteClient core system plugin — coordinates feature plugins, heartbeat, health checks, and admin customizations. Moko\Plugin\System\MokoSuiteClient script.php diff --git a/source/packages/plg_system_mokosuiteclient/script.php b/source/packages/plg_system_mokosuiteclient/script.php index 1f816357..f77b21fb 100644 --- a/source/packages/plg_system_mokosuiteclient/script.php +++ b/source/packages/plg_system_mokosuiteclient/script.php @@ -22,7 +22,7 @@ * DEFGROUP: Joomla.Plugin * INGROUP: MokoSuiteClient * REPO: https://github.com/mokoconsulting-tech/mokosuiteclient - * VERSION: 02.47.26 + * VERSION: 02.47.48 * PATH: /src/script.php * BRIEF: Installation script for MokoSuiteClient plugin * NOTE: Handles installation, update, and uninstallation tasks including language override deployment diff --git a/source/packages/plg_system_mokosuiteclient/services/provider.php b/source/packages/plg_system_mokosuiteclient/services/provider.php index c9e84f1e..8fb66051 100644 --- a/source/packages/plg_system_mokosuiteclient/services/provider.php +++ b/source/packages/plg_system_mokosuiteclient/services/provider.php @@ -22,7 +22,7 @@ * DEFGROUP: Joomla.Plugin * INGROUP: MokoSuiteClient * REPO: https://github.com/mokoconsulting-tech/mokosuiteclient - * VERSION: 02.47.26 + * VERSION: 02.47.48 * PATH: /src/services/provider.php * BRIEF: Service provider for dependency injection in Joomla 5.x * NOTE: Registers the plugin with Joomla's DI container diff --git a/source/packages/plg_system_mokosuiteclient_backup/mokosuiteclient_backup.xml b/source/packages/plg_system_mokosuiteclient_backup/mokosuiteclient_backup.xml index d95874dd..43ada9a1 100644 --- a/source/packages/plg_system_mokosuiteclient_backup/mokosuiteclient_backup.xml +++ b/source/packages/plg_system_mokosuiteclient_backup/mokosuiteclient_backup.xml @@ -8,7 +8,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 02.47.26 + 02.47.48 PLG_SYSTEM_MOKOSUITECLIENT_BACKUP_DESC Moko\Plugin\System\MokoSuiteClientBackup diff --git a/source/packages/plg_system_mokosuiteclient_dbip/mokosuiteclient_dbip.xml b/source/packages/plg_system_mokosuiteclient_dbip/mokosuiteclient_dbip.xml index 86d4eafb..8fe8e26f 100644 --- a/source/packages/plg_system_mokosuiteclient_dbip/mokosuiteclient_dbip.xml +++ b/source/packages/plg_system_mokosuiteclient_dbip/mokosuiteclient_dbip.xml @@ -8,7 +8,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 02.47.26 + 02.47.48 PLG_SYSTEM_MOKOSUITECLIENT_DBIP_DESC Moko\Plugin\System\MokoSuiteClientDBIP diff --git a/source/packages/plg_system_mokosuiteclient_devtools/language/en-GB/plg_system_mokosuiteclient_devtools.ini b/source/packages/plg_system_mokosuiteclient_devtools/language/en-GB/plg_system_mokosuiteclient_devtools.ini index 44d7cca4..b9680d26 100644 --- a/source/packages/plg_system_mokosuiteclient_devtools/language/en-GB/plg_system_mokosuiteclient_devtools.ini +++ b/source/packages/plg_system_mokosuiteclient_devtools/language/en-GB/plg_system_mokosuiteclient_devtools.ini @@ -15,6 +15,8 @@ PLG_SYSTEM_MOKOSUITECLIENT_DEVTOOLS_DELETE_VERSIONS_LABEL="Delete All Versions" PLG_SYSTEM_MOKOSUITECLIENT_DEVTOOLS_DELETE_VERSIONS_DESC="One-shot: delete all content version history on save. Automatically turns off after execution." PLG_SYSTEM_MOKOSUITECLIENT_DEVTOOLS_RESET_DLKEYS_LABEL="Reset Download Keys" PLG_SYSTEM_MOKOSUITECLIENT_DEVTOOLS_RESET_DLKEYS_DESC="One-shot: clear all download keys (dlid) from update sites on save. Automatically turns off after execution." +PLG_SYSTEM_MOKOSUITECLIENT_DEVTOOLS_RESET_TOURS_LABEL="Reset Tour Prompts" +PLG_SYSTEM_MOKOSUITECLIENT_DEVTOOLS_RESET_TOURS_DESC="One-shot: reset all guided tour completion flags on save. Allows tours to re-trigger for all users. Automatically turns off after execution." PLG_SYSTEM_MOKOSUITECLIENT_DEVTOOLS_FIELDSET_ALIASES="Mirror Domains & Staging Environments" PLG_SYSTEM_MOKOSUITECLIENT_DEVTOOLS_FIELDSET_ALIASES_DESC="Configure domain aliases that share this site's hosting folder. Each mirror can independently bypass offline mode and control search engine indexing." diff --git a/source/packages/plg_system_mokosuiteclient_devtools/mokosuiteclient_devtools.xml b/source/packages/plg_system_mokosuiteclient_devtools/mokosuiteclient_devtools.xml index b81e8659..b879f72c 100644 --- a/source/packages/plg_system_mokosuiteclient_devtools/mokosuiteclient_devtools.xml +++ b/source/packages/plg_system_mokosuiteclient_devtools/mokosuiteclient_devtools.xml @@ -8,7 +8,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 02.47.26 + 02.47.48 PLG_SYSTEM_MOKOSUITECLIENT_DEVTOOLS_DESC Moko\Plugin\System\MokoSuiteClientDevTools @@ -61,6 +61,14 @@ + + + + +
set('reset_download_keys', 0); } + // Reset tour prompts on save if toggled on + if ($params->get('reset_tour_prompts', 0)) + { + $this->resetTourPrompts(); + $params->set('reset_tour_prompts', 0); + } + // Reset the one-shot toggles if ($table->params !== $params->toString()) { @@ -160,6 +167,21 @@ class DevTools extends CMSPlugin implements SubscriberInterface return $count; } + private function resetTourPrompts(): int + { + $db = Factory::getDbo(); + $db->setQuery( + $db->getQuery(true) + ->delete($db->quoteName('#__user_profiles')) + ->where($db->quoteName('profile_key') . ' LIKE ' . $db->quote('guidedtours.tour%')) + )->execute(); + + $count = $db->getAffectedRows(); + $this->getApplication()->enqueueMessage(\sprintf('Reset %d guided tour completion flags.', $count), 'message'); + + return $count; + } + private function resetDownloadKeys(): int { $db = Factory::getDbo(); diff --git a/source/packages/plg_system_mokosuiteclient_firewall/mokosuiteclient_firewall.xml b/source/packages/plg_system_mokosuiteclient_firewall/mokosuiteclient_firewall.xml index 6551720a..de3d08c0 100644 --- a/source/packages/plg_system_mokosuiteclient_firewall/mokosuiteclient_firewall.xml +++ b/source/packages/plg_system_mokosuiteclient_firewall/mokosuiteclient_firewall.xml @@ -8,7 +8,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 02.47.26 + 02.47.48 PLG_SYSTEM_MOKOSUITECLIENT_FIREWALL_DESC Moko\Plugin\System\MokoSuiteClientFirewall diff --git a/source/packages/plg_system_mokosuiteclient_license/mokosuiteclient_license.xml b/source/packages/plg_system_mokosuiteclient_license/mokosuiteclient_license.xml index 21bb9520..84c28249 100644 --- a/source/packages/plg_system_mokosuiteclient_license/mokosuiteclient_license.xml +++ b/source/packages/plg_system_mokosuiteclient_license/mokosuiteclient_license.xml @@ -8,7 +8,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 02.47.26 + 02.47.48 PLG_SYSTEM_MOKOSUITECLIENT_LICENSE_DESC Moko\Plugin\System\MokoSuiteClientLicense srcserviceslanguage diff --git a/source/packages/plg_system_mokosuiteclient_offline/mokosuiteclient_offline.xml b/source/packages/plg_system_mokosuiteclient_offline/mokosuiteclient_offline.xml index 6904646b..f311cb6f 100644 --- a/source/packages/plg_system_mokosuiteclient_offline/mokosuiteclient_offline.xml +++ b/source/packages/plg_system_mokosuiteclient_offline/mokosuiteclient_offline.xml @@ -8,7 +8,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 02.47.26 + 02.47.48 PLG_SYSTEM_MOKOSUITECLIENT_OFFLINE_DESC Moko\Plugin\System\MokoSuiteClientOffline diff --git a/source/packages/plg_system_mokosuiteclient_tenant/mokosuiteclient_tenant.xml b/source/packages/plg_system_mokosuiteclient_tenant/mokosuiteclient_tenant.xml index 9c45c45d..80ffe40f 100644 --- a/source/packages/plg_system_mokosuiteclient_tenant/mokosuiteclient_tenant.xml +++ b/source/packages/plg_system_mokosuiteclient_tenant/mokosuiteclient_tenant.xml @@ -8,7 +8,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 02.47.26 + 02.47.48 PLG_SYSTEM_MOKOSUITECLIENT_TENANT_DESC Moko\Plugin\System\MokoSuiteClientTenant diff --git a/source/packages/plg_task_mokosuiteclientdemo/mokosuiteclientdemo.xml b/source/packages/plg_task_mokosuiteclientdemo/mokosuiteclientdemo.xml index 3b733d95..90eacc99 100644 --- a/source/packages/plg_task_mokosuiteclientdemo/mokosuiteclientdemo.xml +++ b/source/packages/plg_task_mokosuiteclientdemo/mokosuiteclientdemo.xml @@ -12,7 +12,7 @@ GNU General Public License version 3 or later; see LICENSE hello@mokoconsulting.tech https://mokoconsulting.tech - 02.47.26 + 02.47.48 PLG_TASK_MOKOSUITECLIENTDEMO_DESC Moko\Plugin\Task\MokoSuiteClientDemo diff --git a/source/packages/plg_task_mokosuiteclientdemo/src/Service/DemoResetService.php b/source/packages/plg_task_mokosuiteclientdemo/src/Service/DemoResetService.php index c531047d..4beb1702 100644 --- a/source/packages/plg_task_mokosuiteclientdemo/src/Service/DemoResetService.php +++ b/source/packages/plg_task_mokosuiteclientdemo/src/Service/DemoResetService.php @@ -10,7 +10,7 @@ * INGROUP: MokoSuiteClient * REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteClient * PATH: /src/packages/plg_system_mokosuiteclient/Service/DemoResetService.php - * VERSION: 02.47.26 + * VERSION: 02.47.48 * BRIEF: Content-only snapshot/restore for demo site reset */ diff --git a/source/packages/plg_task_mokosuiteclientsync/mokosuiteclientsync.xml b/source/packages/plg_task_mokosuiteclientsync/mokosuiteclientsync.xml index 1b9bd825..83a63190 100644 --- a/source/packages/plg_task_mokosuiteclientsync/mokosuiteclientsync.xml +++ b/source/packages/plg_task_mokosuiteclientsync/mokosuiteclientsync.xml @@ -12,7 +12,7 @@ GNU General Public License version 3 or later; see LICENSE hello@mokoconsulting.tech https://mokoconsulting.tech - 02.47.26 + 02.47.48 PLG_TASK_MOKOSUITECLIENTSYNC_DESC Moko\Plugin\Task\MokoSuiteClientSync diff --git a/source/packages/plg_task_mokosuiteclientsync/src/Service/ContentSyncReceiver.php b/source/packages/plg_task_mokosuiteclientsync/src/Service/ContentSyncReceiver.php index eb756d23..29c31482 100644 --- a/source/packages/plg_task_mokosuiteclientsync/src/Service/ContentSyncReceiver.php +++ b/source/packages/plg_task_mokosuiteclientsync/src/Service/ContentSyncReceiver.php @@ -10,7 +10,7 @@ * INGROUP: MokoSuiteClient * REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteClient * PATH: /src/packages/plg_system_mokosuiteclient/Service/ContentSyncReceiver.php - * VERSION: 02.47.26 + * VERSION: 02.47.48 * BRIEF: Receiver-side content sync — applies incoming payload to local DB */ diff --git a/source/packages/plg_task_mokosuiteclientsync/src/Service/ContentSyncService.php b/source/packages/plg_task_mokosuiteclientsync/src/Service/ContentSyncService.php index 3659d502..62b64f55 100644 --- a/source/packages/plg_task_mokosuiteclientsync/src/Service/ContentSyncService.php +++ b/source/packages/plg_task_mokosuiteclientsync/src/Service/ContentSyncService.php @@ -10,7 +10,7 @@ * INGROUP: MokoSuiteClient * REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteClient * PATH: /src/packages/plg_system_mokosuiteclient/Service/ContentSyncService.php - * VERSION: 02.47.26 + * VERSION: 02.47.48 * BRIEF: Sender-side content sync — builds payload and pushes to remote sites */ diff --git a/source/packages/plg_webservices_mokosuiteclient/mokosuiteclient.xml b/source/packages/plg_webservices_mokosuiteclient/mokosuiteclient.xml index cf533922..380fd970 100644 --- a/source/packages/plg_webservices_mokosuiteclient/mokosuiteclient.xml +++ b/source/packages/plg_webservices_mokosuiteclient/mokosuiteclient.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 02.47.26 + 02.47.48 Joomla Web Services API routes for MokoSuiteClient site management — health checks, cache, updates, backups, and site info. Moko\Plugin\WebServices\MokoSuiteClient diff --git a/source/pkg_mokosuiteclient.xml b/source/pkg_mokosuiteclient.xml index cf646af8..cfef48c6 100644 --- a/source/pkg_mokosuiteclient.xml +++ b/source/pkg_mokosuiteclient.xml @@ -2,7 +2,7 @@ Package - MokoSuiteClient mokosuiteclient - 02.47.26 + 02.47.48 2026-06-02 Moko Consulting hello@mokoconsulting.tech diff --git a/source/script.php b/source/script.php index f604699c..a332c0b3 100644 --- a/source/script.php +++ b/source/script.php @@ -108,6 +108,9 @@ class Pkg_MokosuiteclientInstallerScript // Set up MokoSuiteClient guided tours and unpublish Joomla defaults $this->setupGuidedTours(); + // Register MokoSuiteClient guided tour content (tours + steps) + $this->registerGuidedTours(); + // Clean up orphaned empty-element rows and stale files from old DEFAULT '' bug $this->cleanupEmptyElements(); @@ -1486,97 +1489,217 @@ class Pkg_MokosuiteclientInstallerScript ); $db->execute(); - // Define MokoSuiteClient tours + // Remove old-format tours (superseded by com_mokosuiteclient.* UIDs) + $oldUids = [ + $db->quote('mokosuiteclient-welcome'), + $db->quote('mokosuiteclient-firewall'), + $db->quote('mokosuiteclient-extensions'), + ]; + + // Delete orphaned steps first + $subQuery = $db->getQuery(true) + ->select($db->quoteName('id')) + ->from($db->quoteName('#__guidedtours')) + ->where($db->quoteName('uid') . ' IN (' . implode(',', $oldUids) . ')'); + $db->setQuery($subQuery); + $oldTourIds = $db->loadColumn(); + + if (!empty($oldTourIds)) + { + $db->setQuery( + $db->getQuery(true) + ->delete($db->quoteName('#__guidedtour_steps')) + ->where($db->quoteName('tour_id') . ' IN (' . implode(',', array_map('intval', $oldTourIds)) . ')') + )->execute(); + + $db->setQuery( + $db->getQuery(true) + ->delete($db->quoteName('#__guidedtours')) + ->where($db->quoteName('uid') . ' IN (' . implode(',', $oldUids) . ')') + )->execute(); + } + + // Tour registration is now handled by registerGuidedTours() + } + catch (\Throwable $e) + { + Log::add('Guided tours setup error: ' . $e->getMessage(), Log::WARNING, 'mokosuiteclient'); + } + } + + /** + * Register MokoSuiteClient guided tours and their steps. + * + * Inserts tour definitions into #__guidedtours and step definitions into + * #__guidedtour_steps. Skips if the tables do not exist (pre-Joomla 4.3) + * or if a tour with the same uid already exists. + * + * @return void + * + * @since 02.47.09 + */ + private function registerGuidedTours(): void + { + try + { + $db = Factory::getDbo(); + + // Check if #__guidedtours table exists (Joomla 4.3+) + $tables = $db->getTableList(); + $prefix = $db->getPrefix(); + + if (!\in_array($prefix . 'guidedtours', $tables, true)) + { + return; + } + + $now = date('Y-m-d H:i:s'); + + // Define tours $tours = [ [ - 'uid' => 'mokosuiteclient-welcome', - 'title' => 'Welcome to MokoSuiteClient', - 'desc' => 'Get started with the MokoSuiteClient Admin Tools Suite. This tour shows you the key areas of your admin dashboard.', - 'url' => 'administrator/index.php?option=com_mokosuiteclient', - 'steps' => [ - ['title' => 'MokoSuiteClient Dashboard', 'desc' => 'This is your MokoSuiteClient control center. You can see site info, feature plugins, WAF activity, and quick actions all in one place.', 'target' => '#mokosuiteclient-dashboard', 'type' => 0], - ['title' => 'Site Information', 'desc' => 'The info bar shows your Joomla version, PHP version, database type, and debug/offline status at a glance.', 'target' => '.mokosuiteclient-info-bar', 'type' => 0], - ['title' => 'Quick Actions', 'desc' => 'Use these buttons to clear cache, check updates, manage extensions, and perform common admin tasks with one click.', 'target' => '#mokosuiteclient-btn-cache', 'type' => 0], - ['title' => 'Feature Plugins', 'desc' => 'MokoSuiteClient features are split into toggleable plugins. Enable or disable security, tenant restrictions, developer tools, and more from here.', 'target' => '.mokosuiteclient-plugin-grid', 'type' => 0], - ['title' => 'MokoSuiteClient Menu', 'desc' => 'The MokoSuiteClient sidebar menu gives you quick access to all admin tools — Helpdesk, Extensions, WAF Log, Database Tools, and more.', 'target' => '.mokosuiteclient-admin-menu, [class*="mokosuiteclient"]', 'type' => 0], + 'uid' => 'com_mokosuiteclient.welcome', + 'title' => 'MokoSuite Welcome', + 'description' => 'Get started with MokoSuite — configure your health token, send your first heartbeat, and set up trusted IPs.', + 'extensions' => '["com_mokosuiteclient"]', + 'url' => 'administrator/index.php?option=com_mokosuiteclient', + 'steps' => [ + [ + 'title' => 'Welcome to MokoSuite', + 'description' => 'This is your MokoSuite control panel. Let\'s walk through the key features.', + 'target' => '#mokosuiteclient-dashboard', + 'type' => 2, + 'position' => 'bottom', + ], + [ + 'title' => 'Site Info Bar', + 'description' => 'Your site name, version, support PIN, and system info at a glance.', + 'target' => '.card.mb-4:first-child', + 'type' => 2, + 'position' => 'bottom', + ], + [ + 'title' => 'Quick Actions', + 'description' => 'Clear cache, check updates, manage extensions, and more.', + 'target' => '#mokosuiteclient-btn-cache', + 'type' => 2, + 'position' => 'right', + ], + [ + 'title' => 'Plugin Cards', + 'description' => 'Enable, disable, and configure MokoSuite plugins from here.', + 'target' => '.mokosuiteclient-plugin-card:first-child', + 'type' => 2, + 'position' => 'top', + ], ], ], [ - 'uid' => 'mokosuiteclient-firewall', - 'title' => 'MokoSuiteClient Firewall Setup', - 'desc' => 'Configure the Web Application Firewall to protect your site from common attacks.', - 'url' => 'administrator/index.php?option=com_plugins&task=plugin.edit&filter[search]=mokosuiteclient_firewall', - 'steps' => [ - ['title' => 'Firewall Plugin', 'desc' => 'The MokoSuiteClient Firewall provides 10 security shields including SQL injection, XSS, and malicious user agent detection.', 'target' => '', 'type' => 0], - ['title' => 'WAF Shields', 'desc' => 'Enable or disable individual WAF shields. Each shield protects against a specific attack vector. All shields are enabled by default.', 'target' => '', 'type' => 0], - ['title' => 'Security Headers', 'desc' => 'Configure HTTP security headers like X-Frame-Options, Content-Security-Policy, and HSTS to harden your site against browser-based attacks.', 'target' => '', 'type' => 0], - ['title' => 'IP Blocklist', 'desc' => 'Block specific IP addresses, CIDR ranges, or wildcard patterns. The auto-ban feature automatically blocks IPs that trigger too many WAF alerts.', 'target' => '', 'type' => 0], - ], - ], - [ - 'uid' => 'mokosuiteclient-extensions', - 'title' => 'Moko Extensions Manager', - 'desc' => 'Browse and install Moko Consulting extensions from the built-in catalog.', - 'url' => 'administrator/index.php?option=com_mokosuiteclient&view=extensions', - 'steps' => [ - ['title' => 'Extension Catalog', 'desc' => 'Browse all available Moko Consulting extensions. Each card shows the extension name, description, install status, and current version.', 'target' => '', 'type' => 0], - ['title' => 'Install Extensions', 'desc' => 'Click Install to add an extension from the Moko Consulting repository. Updates are handled through Joomla\'s standard update system.', 'target' => '', 'type' => 0], + 'uid' => 'com_mokosuiteclient.firewall', + 'title' => 'MokoSuite Firewall Setup', + 'description' => 'Configure your Web Application Firewall — trusted IPs, WAF shields, and security headers.', + 'extensions' => '["com_mokosuiteclient"]', + 'url' => 'administrator/index.php?option=com_plugins&task=plugin.edit&extension_id=0', + 'steps' => [ + [ + 'title' => 'Your Current IP', + 'description' => 'This shows your IP address. Copy it to add to the Trusted IPs list.', + 'target' => '#mokosuiteclient-current-ip', + 'type' => 2, + 'position' => 'bottom', + ], + [ + 'title' => 'Trusted IPs', + 'description' => 'Add IPs that should bypass WAF checks — your office, VPN, etc.', + 'target' => '#jform_params_trusted_ips', + 'type' => 2, + 'position' => 'top', + ], + [ + 'title' => 'WAF Shields', + 'description' => 'Enable protection against SQL injection, XSS, malicious agents, and more.', + 'target' => '#attrib-waf', + 'type' => 2, + 'position' => 'bottom', + ], ], ], ]; foreach ($tours as $tourDef) { - // Check if tour already exists - $db->setQuery( - $db->getQuery(true) - ->select('id') - ->from($db->quoteName('#__guidedtours')) - ->where($db->quoteName('uid') . ' = ' . $db->quote($tourDef['uid'])) - ); + // Check if tour already exists by uid + $query = $db->getQuery(true) + ->select($db->quoteName('id')) + ->from($db->quoteName('#__guidedtours')) + ->where($db->quoteName('uid') . ' = ' . $db->quote($tourDef['uid'])); + $db->setQuery($query); + $existingId = (int) $db->loadResult(); - if ($db->loadResult()) + if ($existingId) { - continue; + // Update existing tour metadata + $update = $db->getQuery(true) + ->update($db->quoteName('#__guidedtours')) + ->set($db->quoteName('title') . ' = ' . $db->quote($tourDef['title'])) + ->set($db->quoteName('description') . ' = ' . $db->quote($tourDef['description'])) + ->set($db->quoteName('extensions') . ' = ' . $db->quote($tourDef['extensions'])) + ->set($db->quoteName('url') . ' = ' . $db->quote($tourDef['url'])) + ->set($db->quoteName('published') . ' = 1') + ->set($db->quoteName('modified') . ' = ' . $db->quote($now)) + ->where($db->quoteName('id') . ' = ' . $existingId); + $db->setQuery($update)->execute(); + + // Delete existing steps so they are re-inserted fresh + $delete = $db->getQuery(true) + ->delete($db->quoteName('#__guidedtour_steps')) + ->where($db->quoteName('tour_id') . ' = ' . $existingId); + $db->setQuery($delete)->execute(); + + $tourId = $existingId; + } + else + { + // Insert new tour + $tour = (object) [ + 'title' => $tourDef['title'], + 'uid' => $tourDef['uid'], + 'description' => $tourDef['description'], + 'extensions' => $tourDef['extensions'], + 'url' => $tourDef['url'], + 'created' => $now, + 'created_by' => 0, + 'modified' => $now, + 'modified_by' => 0, + 'published' => 1, + 'language' => '*', + 'note' => 'MokoSuiteClient', + 'access' => 1, + 'ordering' => 0, + 'autostart' => 0, + ]; + + $db->insertObject('#__guidedtours', $tour, 'id'); + $tourId = (int) $tour->id; } - $tour = (object) [ - 'title' => $tourDef['title'], - 'uid' => $tourDef['uid'], - 'description' => $tourDef['desc'], - 'extensions' => '', - 'url' => $tourDef['url'], - 'created' => date('Y-m-d H:i:s'), - 'created_by' => 0, - 'modified' => date('Y-m-d H:i:s'), - 'modified_by' => 0, - 'published' => 1, - 'language' => '*', - 'note' => 'MokoSuiteClient', - 'access' => 3, - 'ordering' => 0, - 'autostart' => 0, - ]; - - $db->insertObject('#__guidedtours', $tour, 'id'); - $tourId = (int) $tour->id; - + // Insert steps foreach ($tourDef['steps'] as $i => $stepDef) { $step = (object) [ 'tour_id' => $tourId, 'title' => $stepDef['title'], - 'description' => $stepDef['desc'], + 'description' => $stepDef['description'], 'target' => $stepDef['target'], 'type' => $stepDef['type'], 'interactive_type' => 1, 'url' => '', - 'position' => 'bottom', + 'position' => $stepDef['position'], 'ordering' => $i + 1, 'published' => 1, - 'created' => date('Y-m-d H:i:s'), + 'created' => $now, 'created_by' => 0, - 'modified' => date('Y-m-d H:i:s'), + 'modified' => $now, 'modified_by' => 0, 'language' => '*', 'note' => '', @@ -1586,10 +1709,12 @@ class Pkg_MokosuiteclientInstallerScript $db->insertObject('#__guidedtour_steps', $step, 'id'); } } + + Log::add('Registered ' . \count($tours) . ' MokoSuiteClient guided tours.', Log::INFO, 'mokosuiteclient'); } catch (\Throwable $e) { - Log::add('Guided tours setup error: ' . $e->getMessage(), Log::WARNING, 'mokosuiteclient'); + Log::add('Guided tour registration error: ' . $e->getMessage(), Log::WARNING, 'mokosuiteclient'); } }