diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml
index 11958bdc..c315225b 100644
--- a/.mokogitea/workflows/issue-branch.yml
+++ b/.mokogitea/workflows/issue-branch.yml
@@ -5,7 +5,7 @@
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: mokocli.Automation
-# VERSION: 01.00.00
+# VERSION: 02.52.13
# BRIEF: Auto-create feature branch when an issue is opened
name: "Universal: Issue Branch"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 99380580..4c216bc4 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.52.04
+ VERSION: 02.52.13
BRIEF: Version history using `Keep a Changelog`
-->
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index b40626a2..5c122de1 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.52.04
+ VERSION: 02.52.13
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 1af65bff..0a969210 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.52.04
+ VERSION: 02.52.13
PATH: /GOVERNANCE.md
BRIEF: Project governance rules, roles, and decision process for MokoSuiteClientBrand
-->
diff --git a/LICENSE.md b/LICENSE.md
index 6f25d49d..f9d83118 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.52.04
+ VERSION: 02.52.13
BRIEF: Project license (GPL-3.0-or-later)
-->
GNU GENERAL PUBLIC LICENSE
diff --git a/README.md b/README.md
index 3ccb18a5..02248965 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.52.04
+ VERSION: 02.52.13
PATH: /README.md
BRIEF: MokoSuiteClient platform plugin for Joomla
-->
diff --git a/SECURITY.md b/SECURITY.md
index 42f17a00..961b2d54 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.52.04
+VERSION: 02.52.13
BRIEF: Security vulnerability reporting and handling policy
-->
diff --git a/docs/guides/build-guide.md b/docs/guides/build-guide.md
index 3671898a..4e49bce1 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.52.04
+ VERSION: 02.52.13
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.52.04)
+# MokoSuiteClient Build Guide (VERSION: 02.52.13)
## 1. Purpose
diff --git a/docs/guides/configuration-guide.md b/docs/guides/configuration-guide.md
index 81fccc07..0cbe0bf9 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.52.04
+ VERSION: 02.52.13
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.52.04)
+# MokoSuiteClient Configuration Guide (VERSION: 02.52.13)
## 1. Objective
diff --git a/docs/guides/installation-guide.md b/docs/guides/installation-guide.md
index 40791acf..5aa7d3a9 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.52.04
+ VERSION: 02.52.13
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.52.04)
+# MokoSuiteClient Installation Guide (VERSION: 02.52.13)
## Introduction
diff --git a/docs/guides/operations-guide.md b/docs/guides/operations-guide.md
index c6942e3e..99cd7452 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.52.04
+ VERSION: 02.52.13
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.52.04)
+# MokoSuiteClient Operations Guide (VERSION: 02.52.13)
## Introduction
diff --git a/docs/guides/rollback-and-recovery-guide.md b/docs/guides/rollback-and-recovery-guide.md
index a3f3bc68..41d27cfd 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.52.04
+ VERSION: 02.52.13
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.52.04)
+# MokoSuiteClient Rollback and Recovery Guide (VERSION: 02.52.13)
## Introduction
diff --git a/docs/guides/testing-guide.md b/docs/guides/testing-guide.md
index f9a4aa33..cd3df1c7 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.52.04
+ VERSION: 02.52.13
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.52.04)
+# MokoSuiteClient Testing Guide (VERSION: 02.52.13)
## 1. Prerequisites
diff --git a/docs/guides/troubleshooting-guide.md b/docs/guides/troubleshooting-guide.md
index 437388e7..e9b1c06c 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.52.04
+ VERSION: 02.52.13
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.52.04)
+# MokoSuiteClient Troubleshooting Guide (VERSION: 02.52.13)
## Introduction
diff --git a/docs/guides/upgrade-and-versioning-guide.md b/docs/guides/upgrade-and-versioning-guide.md
index c90d22d7..2adf9853 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.52.04
+ VERSION: 02.52.13
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.52.04)
+# MokoSuiteClient Upgrade and Versioning Guide (VERSION: 02.52.13)
## Introduction
diff --git a/docs/index.md b/docs/index.md
index 7af574b3..8526bc3c 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.52.04
+ VERSION: 02.52.13
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.52.04)
+# MokoSuiteClient Documentation Index (VERSION: 02.52.13)
## Introduction
diff --git a/docs/plugin-basic.md b/docs/plugin-basic.md
index 29dca6a5..95b4e434 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.52.04
+ VERSION: 02.52.13
BRIEF: Baseline documentation for the MokoSuiteClient system plugin
NOTE: Foundational reference for internal and external stakeholders
-->
-# MokoSuiteClient Plugin Overview (VERSION: 02.52.04)
+# MokoSuiteClient Plugin Overview (VERSION: 02.52.13)
## Introduction
diff --git a/docs/update-server.md b/docs/update-server.md
index 8cf24cd5..1deaec49 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.52.04
+VERSION: 02.52.13
BRIEF: How this extension's Joomla update server file (update.xml) is managed
-->
diff --git a/source/packages/com_mokosuiteclient/admin/language/en-GB/com_mokosuiteclient.sys.ini b/source/packages/com_mokosuiteclient/admin/language/en-GB/com_mokosuiteclient.sys.ini
index 1ac9f72b..ccc54f48 100644
--- a/source/packages/com_mokosuiteclient/admin/language/en-GB/com_mokosuiteclient.sys.ini
+++ b/source/packages/com_mokosuiteclient/admin/language/en-GB/com_mokosuiteclient.sys.ini
@@ -17,3 +17,9 @@ COM_MOKOSUITECLIENT_MENU_WAFLOG="WAF Log"
COM_MOKOSUITECLIENT_MENU_DATABASE="Database Tools"
COM_MOKOSUITECLIENT_MENU_CLEANUP="Cache Cleanup"
COM_MOKOSUITECLIENT_MENU_CACHE="Cache Management"
+COM_MOKOSUITECLIENT_MENU_CONDITIONS="Conditions"
+COM_MOKOSUITECLIENT_MENU_SNIPPETS="Snippets"
+COM_MOKOSUITECLIENT_MENU_TEMPLATES="Content Templates"
+COM_MOKOSUITECLIENT_MENU_REPLACEMENTS="Replacements"
+COM_MOKOSUITECLIENT_MENU_AUTOMATION="Automation"
+COM_MOKOSUITECLIENT_MENU_MODULES="Modules"
diff --git a/source/packages/com_mokosuiteclient/admin/src/Controller/DisplayController.php b/source/packages/com_mokosuiteclient/admin/src/Controller/DisplayController.php
index 18bfc8f8..09fb3d2e 100644
--- a/source/packages/com_mokosuiteclient/admin/src/Controller/DisplayController.php
+++ b/source/packages/com_mokosuiteclient/admin/src/Controller/DisplayController.php
@@ -36,6 +36,7 @@ class DisplayController extends BaseController
'templates' => 'mokosuiteclient.templates.manage',
'replacements' => 'mokosuiteclient.replacements.manage',
'conditions' => 'mokosuiteclient.conditions.manage',
+ 'modules' => 'core.admin',
];
public function display($cachable = false, $urlparams = [])
@@ -805,6 +806,65 @@ class DisplayController extends BaseController
$this->jsonResponse($this->getModel('Import')->importAdminTools());
}
+ // ==================================================================
+ // Toggle Published
+ // ==================================================================
+
+ public function togglePublished()
+ {
+ if (!Session::checkToken())
+ {
+ $this->jsonResponse(['success' => false, 'message' => Text::_('JINVALID_TOKEN')]);
+ return;
+ }
+
+ if (!$this->checkAcl('core.admin'))
+ {
+ $this->jsonForbidden();
+ return;
+ }
+
+ $app = Factory::getApplication();
+ $table = $app->getInput()->getString('table', '');
+ $id = $app->getInput()->getInt('id', 0);
+
+ $allowed = ['mokosuiteclient_conditions', 'mokosuiteclient_snippets',
+ 'mokosuiteclient_replacements', 'mokosuiteclient_content_templates', 'modules'];
+
+ if (!in_array($table, $allowed, true) || $id <= 0)
+ {
+ $this->jsonResponse(['success' => false, 'message' => 'Invalid table or ID.']);
+ return;
+ }
+
+ try
+ {
+ $db = Factory::getContainer()->get(\Joomla\Database\DatabaseInterface::class);
+ $dbTable = '#__' . $table;
+ $current = (int) $db->setQuery(
+ $db->getQuery(true)
+ ->select($db->quoteName('published'))
+ ->from($db->quoteName($dbTable))
+ ->where($db->quoteName('id') . ' = ' . $id)
+ )->loadResult();
+
+ $newState = $current ? 0 : 1;
+
+ $db->setQuery(
+ $db->getQuery(true)
+ ->update($db->quoteName($dbTable))
+ ->set($db->quoteName('published') . ' = ' . $newState)
+ ->where($db->quoteName('id') . ' = ' . $id)
+ )->execute();
+
+ $this->jsonResponse(['success' => true, 'published' => $newState]);
+ }
+ catch (\Throwable $e)
+ {
+ $this->jsonResponse(['success' => false, 'message' => $e->getMessage()]);
+ }
+ }
+
// ==================================================================
// Helpers
// ==================================================================
diff --git a/source/packages/com_mokosuiteclient/admin/src/Model/ConditionsModel.php b/source/packages/com_mokosuiteclient/admin/src/Model/ConditionsModel.php
new file mode 100644
index 00000000..2396bc3a
--- /dev/null
+++ b/source/packages/com_mokosuiteclient/admin/src/Model/ConditionsModel.php
@@ -0,0 +1,112 @@
+get(DatabaseInterface::class);
+ $query = $db->getQuery(true)
+ ->select([
+ $db->quoteName('c.id'),
+ $db->quoteName('c.alias'),
+ $db->quoteName('c.name'),
+ $db->quoteName('c.description'),
+ $db->quoteName('c.category'),
+ $db->quoteName('c.color'),
+ $db->quoteName('c.match_all'),
+ $db->quoteName('c.published'),
+ '(SELECT COUNT(*) FROM ' . $db->quoteName('#__mokosuiteclient_conditions_groups')
+ . ' WHERE ' . $db->quoteName('condition_id') . ' = ' . $db->quoteName('c.id') . ') AS group_count',
+ '(SELECT COUNT(*) FROM ' . $db->quoteName('#__mokosuiteclient_conditions_rules', 'r')
+ . ' INNER JOIN ' . $db->quoteName('#__mokosuiteclient_conditions_groups', 'g')
+ . ' ON ' . $db->quoteName('g.id') . ' = ' . $db->quoteName('r.group_id')
+ . ' WHERE ' . $db->quoteName('g.condition_id') . ' = ' . $db->quoteName('c.id') . ') AS rule_count',
+ ])
+ ->from($db->quoteName('#__mokosuiteclient_conditions', 'c'));
+
+ if (!empty($filters['search']))
+ {
+ $search = $db->quote('%' . $db->escape($filters['search'], true) . '%');
+ $query->where('(' . $db->quoteName('c.name') . ' LIKE ' . $search
+ . ' OR ' . $db->quoteName('c.alias') . ' LIKE ' . $search . ')');
+ }
+
+ if ($filters['published'] !== '' && $filters['published'] !== null)
+ {
+ $query->where($db->quoteName('c.published') . ' = ' . (int) $filters['published']);
+ }
+
+ $query->order($db->quoteName('c.name') . ' ASC');
+ $db->setQuery($query, $offset, $limit);
+
+ return $db->loadObjectList() ?: [];
+ }
+
+ public function getTotal(array $filters = []): int
+ {
+ $db = Factory::getContainer()->get(DatabaseInterface::class);
+ $query = $db->getQuery(true)
+ ->select('COUNT(*)')
+ ->from($db->quoteName('#__mokosuiteclient_conditions', 'c'));
+
+ if (!empty($filters['search']))
+ {
+ $search = $db->quote('%' . $db->escape($filters['search'], true) . '%');
+ $query->where('(' . $db->quoteName('c.name') . ' LIKE ' . $search
+ . ' OR ' . $db->quoteName('c.alias') . ' LIKE ' . $search . ')');
+ }
+
+ if ($filters['published'] !== '' && $filters['published'] !== null)
+ {
+ $query->where($db->quoteName('c.published') . ' = ' . (int) $filters['published']);
+ }
+
+ $db->setQuery($query);
+
+ return (int) $db->loadResult();
+ }
+
+ public function getGroupCount(int $conditionId): int
+ {
+ $db = Factory::getContainer()->get(DatabaseInterface::class);
+ $db->setQuery(
+ $db->getQuery(true)
+ ->select('COUNT(*)')
+ ->from($db->quoteName('#__mokosuiteclient_conditions_groups'))
+ ->where($db->quoteName('condition_id') . ' = ' . $conditionId)
+ );
+
+ return (int) $db->loadResult();
+ }
+
+ public function getRuleCount(int $conditionId): int
+ {
+ $db = Factory::getContainer()->get(DatabaseInterface::class);
+ $db->setQuery(
+ $db->getQuery(true)
+ ->select('COUNT(*)')
+ ->from($db->quoteName('#__mokosuiteclient_conditions_rules', 'r'))
+ ->join('INNER', $db->quoteName('#__mokosuiteclient_conditions_groups', 'g')
+ . ' ON ' . $db->quoteName('g.id') . ' = ' . $db->quoteName('r.group_id'))
+ ->where($db->quoteName('g.condition_id') . ' = ' . $conditionId)
+ );
+
+ return (int) $db->loadResult();
+ }
+}
diff --git a/source/packages/com_mokosuiteclient/admin/src/Model/ModulesModel.php b/source/packages/com_mokosuiteclient/admin/src/Model/ModulesModel.php
new file mode 100644
index 00000000..ae46be70
--- /dev/null
+++ b/source/packages/com_mokosuiteclient/admin/src/Model/ModulesModel.php
@@ -0,0 +1,93 @@
+get(DatabaseInterface::class);
+ $query = $db->getQuery(true)
+ ->select([
+ $db->quoteName('m.id'),
+ $db->quoteName('m.title'),
+ $db->quoteName('m.module'),
+ $db->quoteName('m.position'),
+ $db->quoteName('m.published'),
+ $db->quoteName('m.ordering'),
+ $db->quoteName('m.client_id'),
+ $db->quoteName('m.access'),
+ $db->quoteName('m.language'),
+ ])
+ ->from($db->quoteName('#__modules', 'm'));
+
+ if (!empty($filters['search']))
+ {
+ $search = $db->quote('%' . $db->escape($filters['search'], true) . '%');
+ $query->where('(' . $db->quoteName('m.title') . ' LIKE ' . $search
+ . ' OR ' . $db->quoteName('m.module') . ' LIKE ' . $search
+ . ' OR ' . $db->quoteName('m.position') . ' LIKE ' . $search . ')');
+ }
+
+ if ($filters['published'] !== '' && $filters['published'] !== null)
+ {
+ $query->where($db->quoteName('m.published') . ' = ' . (int) $filters['published']);
+ }
+
+ if ($filters['client_id'] !== '' && $filters['client_id'] !== null)
+ {
+ $query->where($db->quoteName('m.client_id') . ' = ' . (int) $filters['client_id']);
+ }
+
+ $query->order($db->quoteName('m.client_id') . ' ASC, '
+ . $db->quoteName('m.position') . ' ASC, '
+ . $db->quoteName('m.ordering') . ' ASC');
+ $db->setQuery($query, $offset, $limit);
+
+ return $db->loadObjectList() ?: [];
+ }
+
+ public function getTotal(array $filters = []): int
+ {
+ $db = Factory::getContainer()->get(DatabaseInterface::class);
+ $query = $db->getQuery(true)
+ ->select('COUNT(*)')
+ ->from($db->quoteName('#__modules', 'm'));
+
+ if (!empty($filters['search']))
+ {
+ $search = $db->quote('%' . $db->escape($filters['search'], true) . '%');
+ $query->where('(' . $db->quoteName('m.title') . ' LIKE ' . $search
+ . ' OR ' . $db->quoteName('m.module') . ' LIKE ' . $search
+ . ' OR ' . $db->quoteName('m.position') . ' LIKE ' . $search . ')');
+ }
+
+ if ($filters['published'] !== '' && $filters['published'] !== null)
+ {
+ $query->where($db->quoteName('m.published') . ' = ' . (int) $filters['published']);
+ }
+
+ if ($filters['client_id'] !== '' && $filters['client_id'] !== null)
+ {
+ $query->where($db->quoteName('m.client_id') . ' = ' . (int) $filters['client_id']);
+ }
+
+ $db->setQuery($query);
+
+ return (int) $db->loadResult();
+ }
+}
diff --git a/source/packages/com_mokosuiteclient/admin/src/Model/ReplacementsModel.php b/source/packages/com_mokosuiteclient/admin/src/Model/ReplacementsModel.php
new file mode 100644
index 00000000..b56a6190
--- /dev/null
+++ b/source/packages/com_mokosuiteclient/admin/src/Model/ReplacementsModel.php
@@ -0,0 +1,69 @@
+get(DatabaseInterface::class);
+ $query = $db->getQuery(true)
+ ->select('*')
+ ->from($db->quoteName('#__mokosuiteclient_replacements'));
+
+ if (!empty($filters['search']))
+ {
+ $search = $db->quote('%' . $db->escape($filters['search'], true) . '%');
+ $query->where('(' . $db->quoteName('name') . ' LIKE ' . $search
+ . ' OR ' . $db->quoteName('search') . ' LIKE ' . $search . ')');
+ }
+
+ if ($filters['published'] !== '' && $filters['published'] !== null)
+ {
+ $query->where($db->quoteName('published') . ' = ' . (int) $filters['published']);
+ }
+
+ $query->order($db->quoteName('ordering') . ' ASC, ' . $db->quoteName('name') . ' ASC');
+ $db->setQuery($query, $offset, $limit);
+
+ return $db->loadObjectList() ?: [];
+ }
+
+ public function getTotal(array $filters = []): int
+ {
+ $db = Factory::getContainer()->get(DatabaseInterface::class);
+ $query = $db->getQuery(true)
+ ->select('COUNT(*)')
+ ->from($db->quoteName('#__mokosuiteclient_replacements'));
+
+ if (!empty($filters['search']))
+ {
+ $search = $db->quote('%' . $db->escape($filters['search'], true) . '%');
+ $query->where('(' . $db->quoteName('name') . ' LIKE ' . $search
+ . ' OR ' . $db->quoteName('search') . ' LIKE ' . $search . ')');
+ }
+
+ if ($filters['published'] !== '' && $filters['published'] !== null)
+ {
+ $query->where($db->quoteName('published') . ' = ' . (int) $filters['published']);
+ }
+
+ $db->setQuery($query);
+
+ return (int) $db->loadResult();
+ }
+}
diff --git a/source/packages/com_mokosuiteclient/admin/src/Model/SnippetsModel.php b/source/packages/com_mokosuiteclient/admin/src/Model/SnippetsModel.php
new file mode 100644
index 00000000..7dfefd67
--- /dev/null
+++ b/source/packages/com_mokosuiteclient/admin/src/Model/SnippetsModel.php
@@ -0,0 +1,69 @@
+get(DatabaseInterface::class);
+ $query = $db->getQuery(true)
+ ->select('*')
+ ->from($db->quoteName('#__mokosuiteclient_snippets'));
+
+ if (!empty($filters['search']))
+ {
+ $search = $db->quote('%' . $db->escape($filters['search'], true) . '%');
+ $query->where('(' . $db->quoteName('name') . ' LIKE ' . $search
+ . ' OR ' . $db->quoteName('alias') . ' LIKE ' . $search . ')');
+ }
+
+ if ($filters['published'] !== '' && $filters['published'] !== null)
+ {
+ $query->where($db->quoteName('published') . ' = ' . (int) $filters['published']);
+ }
+
+ $query->order($db->quoteName('ordering') . ' ASC, ' . $db->quoteName('name') . ' ASC');
+ $db->setQuery($query, $offset, $limit);
+
+ return $db->loadObjectList() ?: [];
+ }
+
+ public function getTotal(array $filters = []): int
+ {
+ $db = Factory::getContainer()->get(DatabaseInterface::class);
+ $query = $db->getQuery(true)
+ ->select('COUNT(*)')
+ ->from($db->quoteName('#__mokosuiteclient_snippets'));
+
+ if (!empty($filters['search']))
+ {
+ $search = $db->quote('%' . $db->escape($filters['search'], true) . '%');
+ $query->where('(' . $db->quoteName('name') . ' LIKE ' . $search
+ . ' OR ' . $db->quoteName('alias') . ' LIKE ' . $search . ')');
+ }
+
+ if ($filters['published'] !== '' && $filters['published'] !== null)
+ {
+ $query->where($db->quoteName('published') . ' = ' . (int) $filters['published']);
+ }
+
+ $db->setQuery($query);
+
+ return (int) $db->loadResult();
+ }
+}
diff --git a/source/packages/com_mokosuiteclient/admin/src/Model/TemplatesModel.php b/source/packages/com_mokosuiteclient/admin/src/Model/TemplatesModel.php
new file mode 100644
index 00000000..a90f7141
--- /dev/null
+++ b/source/packages/com_mokosuiteclient/admin/src/Model/TemplatesModel.php
@@ -0,0 +1,69 @@
+get(DatabaseInterface::class);
+ $query = $db->getQuery(true)
+ ->select('*')
+ ->from($db->quoteName('#__mokosuiteclient_content_templates'));
+
+ if (!empty($filters['search']))
+ {
+ $search = $db->quote('%' . $db->escape($filters['search'], true) . '%');
+ $query->where('(' . $db->quoteName('name') . ' LIKE ' . $search
+ . ' OR ' . $db->quoteName('alias') . ' LIKE ' . $search . ')');
+ }
+
+ if ($filters['published'] !== '' && $filters['published'] !== null)
+ {
+ $query->where($db->quoteName('published') . ' = ' . (int) $filters['published']);
+ }
+
+ $query->order($db->quoteName('ordering') . ' ASC, ' . $db->quoteName('name') . ' ASC');
+ $db->setQuery($query, $offset, $limit);
+
+ return $db->loadObjectList() ?: [];
+ }
+
+ public function getTotal(array $filters = []): int
+ {
+ $db = Factory::getContainer()->get(DatabaseInterface::class);
+ $query = $db->getQuery(true)
+ ->select('COUNT(*)')
+ ->from($db->quoteName('#__mokosuiteclient_content_templates'));
+
+ if (!empty($filters['search']))
+ {
+ $search = $db->quote('%' . $db->escape($filters['search'], true) . '%');
+ $query->where('(' . $db->quoteName('name') . ' LIKE ' . $search
+ . ' OR ' . $db->quoteName('alias') . ' LIKE ' . $search . ')');
+ }
+
+ if ($filters['published'] !== '' && $filters['published'] !== null)
+ {
+ $query->where($db->quoteName('published') . ' = ' . (int) $filters['published']);
+ }
+
+ $db->setQuery($query);
+
+ return (int) $db->loadResult();
+ }
+}
diff --git a/source/packages/com_mokosuiteclient/admin/src/View/Conditions/HtmlView.php b/source/packages/com_mokosuiteclient/admin/src/View/Conditions/HtmlView.php
new file mode 100644
index 00000000..34933d65
--- /dev/null
+++ b/source/packages/com_mokosuiteclient/admin/src/View/Conditions/HtmlView.php
@@ -0,0 +1,55 @@
+getInput();
+
+ $this->filters = [
+ 'search' => $input->getString('filter_search', ''),
+ 'published' => $input->get('filter_published', ''),
+ ];
+
+ $page = max(1, $input->getInt('page', 1));
+ $limit = 50;
+ $offset = ($page - 1) * $limit;
+
+ $this->items = $model->getItems($this->filters, $limit, $offset);
+ $this->total = $model->getTotal($this->filters);
+
+ $this->addToolbar();
+
+ $wa = Factory::getApplication()->getDocument()->getWebAssetManager();
+ $wa->registerAndUseStyle('com_mokosuiteclient.dashboard', 'com_mokosuiteclient/dashboard.css');
+
+ parent::display($tpl);
+ }
+
+ protected function addToolbar(): void
+ {
+ ToolbarHelper::title('Conditions', 'shuffle');
+ ToolbarHelper::back('JTOOLBAR_BACK', 'index.php?option=com_mokosuiteclient');
+ }
+}
diff --git a/source/packages/com_mokosuiteclient/admin/src/View/Modules/HtmlView.php b/source/packages/com_mokosuiteclient/admin/src/View/Modules/HtmlView.php
new file mode 100644
index 00000000..b496ed5f
--- /dev/null
+++ b/source/packages/com_mokosuiteclient/admin/src/View/Modules/HtmlView.php
@@ -0,0 +1,56 @@
+getInput();
+
+ $this->filters = [
+ 'search' => $input->getString('filter_search', ''),
+ 'published' => $input->get('filter_published', ''),
+ 'client_id' => $input->get('filter_client', ''),
+ ];
+
+ $page = max(1, $input->getInt('page', 1));
+ $limit = 50;
+ $offset = ($page - 1) * $limit;
+
+ $this->items = $model->getItems($this->filters, $limit, $offset);
+ $this->total = $model->getTotal($this->filters);
+
+ $this->addToolbar();
+
+ $wa = Factory::getApplication()->getDocument()->getWebAssetManager();
+ $wa->registerAndUseStyle('com_mokosuiteclient.dashboard', 'com_mokosuiteclient/dashboard.css');
+
+ parent::display($tpl);
+ }
+
+ protected function addToolbar(): void
+ {
+ ToolbarHelper::title('Module Manager', 'cube');
+ ToolbarHelper::back('JTOOLBAR_BACK', 'index.php?option=com_mokosuiteclient');
+ }
+}
diff --git a/source/packages/com_mokosuiteclient/admin/src/View/Replacements/HtmlView.php b/source/packages/com_mokosuiteclient/admin/src/View/Replacements/HtmlView.php
new file mode 100644
index 00000000..53681010
--- /dev/null
+++ b/source/packages/com_mokosuiteclient/admin/src/View/Replacements/HtmlView.php
@@ -0,0 +1,55 @@
+getInput();
+
+ $this->filters = [
+ 'search' => $input->getString('filter_search', ''),
+ 'published' => $input->get('filter_published', ''),
+ ];
+
+ $page = max(1, $input->getInt('page', 1));
+ $limit = 50;
+ $offset = ($page - 1) * $limit;
+
+ $this->items = $model->getItems($this->filters, $limit, $offset);
+ $this->total = $model->getTotal($this->filters);
+
+ $this->addToolbar();
+
+ $wa = Factory::getApplication()->getDocument()->getWebAssetManager();
+ $wa->registerAndUseStyle('com_mokosuiteclient.dashboard', 'com_mokosuiteclient/dashboard.css');
+
+ parent::display($tpl);
+ }
+
+ protected function addToolbar(): void
+ {
+ ToolbarHelper::title('Replacements', 'right-left');
+ ToolbarHelper::back('JTOOLBAR_BACK', 'index.php?option=com_mokosuiteclient');
+ }
+}
diff --git a/source/packages/com_mokosuiteclient/admin/src/View/Snippets/HtmlView.php b/source/packages/com_mokosuiteclient/admin/src/View/Snippets/HtmlView.php
new file mode 100644
index 00000000..526f0561
--- /dev/null
+++ b/source/packages/com_mokosuiteclient/admin/src/View/Snippets/HtmlView.php
@@ -0,0 +1,55 @@
+getInput();
+
+ $this->filters = [
+ 'search' => $input->getString('filter_search', ''),
+ 'published' => $input->get('filter_published', ''),
+ ];
+
+ $page = max(1, $input->getInt('page', 1));
+ $limit = 50;
+ $offset = ($page - 1) * $limit;
+
+ $this->items = $model->getItems($this->filters, $limit, $offset);
+ $this->total = $model->getTotal($this->filters);
+
+ $this->addToolbar();
+
+ $wa = Factory::getApplication()->getDocument()->getWebAssetManager();
+ $wa->registerAndUseStyle('com_mokosuiteclient.dashboard', 'com_mokosuiteclient/dashboard.css');
+
+ parent::display($tpl);
+ }
+
+ protected function addToolbar(): void
+ {
+ ToolbarHelper::title('Snippets', 'code');
+ ToolbarHelper::back('JTOOLBAR_BACK', 'index.php?option=com_mokosuiteclient');
+ }
+}
diff --git a/source/packages/com_mokosuiteclient/admin/src/View/Templates/HtmlView.php b/source/packages/com_mokosuiteclient/admin/src/View/Templates/HtmlView.php
new file mode 100644
index 00000000..3d8c5c49
--- /dev/null
+++ b/source/packages/com_mokosuiteclient/admin/src/View/Templates/HtmlView.php
@@ -0,0 +1,55 @@
+getInput();
+
+ $this->filters = [
+ 'search' => $input->getString('filter_search', ''),
+ 'published' => $input->get('filter_published', ''),
+ ];
+
+ $page = max(1, $input->getInt('page', 1));
+ $limit = 50;
+ $offset = ($page - 1) * $limit;
+
+ $this->items = $model->getItems($this->filters, $limit, $offset);
+ $this->total = $model->getTotal($this->filters);
+
+ $this->addToolbar();
+
+ $wa = Factory::getApplication()->getDocument()->getWebAssetManager();
+ $wa->registerAndUseStyle('com_mokosuiteclient.dashboard', 'com_mokosuiteclient/dashboard.css');
+
+ parent::display($tpl);
+ }
+
+ protected function addToolbar(): void
+ {
+ ToolbarHelper::title('Content Templates', 'file-lines');
+ ToolbarHelper::back('JTOOLBAR_BACK', 'index.php?option=com_mokosuiteclient');
+ }
+}
diff --git a/source/packages/com_mokosuiteclient/admin/tmpl/conditions/default.php b/source/packages/com_mokosuiteclient/admin/tmpl/conditions/default.php
new file mode 100644
index 00000000..a416ec36
--- /dev/null
+++ b/source/packages/com_mokosuiteclient/admin/tmpl/conditions/default.php
@@ -0,0 +1,142 @@
+items;
+$total = $this->total;
+$filters = $this->filters;
+$token = Session::getFormToken();
+$input = Factory::getApplication()->getInput();
+$page = max(1, $input->getInt('page', 1));
+$pages = max(1, ceil($total / 50));
+?>
+
+
+
+
+
+
+
+
+
+
+ | ID |
+ Name |
+ Alias |
+ Category |
+ Match |
+ Groups |
+ Rules |
+ Status |
+
+
+
+
+ | No conditions found. |
+
+
+
+ | id; ?> |
+
+ color): ?>
+
+
+ name, ENT_QUOTES, 'UTF-8'); ?>
+ |
+ alias, ENT_QUOTES, 'UTF-8'); ?> |
+
+ category): ?>
+ category, ENT_QUOTES, 'UTF-8'); ?>
+
+ |
+ match_all ? 'ALL' : 'ANY'; ?> |
+ group_count; ?> |
+ rule_count; ?> |
+
+
+ published ? 'Published' : 'Unpublished'; ?>
+
+ |
+
+
+
+
+
+
+
+
+ 1): ?>
+
+
+
+
+
diff --git a/source/packages/com_mokosuiteclient/admin/tmpl/modules/default.php b/source/packages/com_mokosuiteclient/admin/tmpl/modules/default.php
new file mode 100644
index 00000000..b85ec70b
--- /dev/null
+++ b/source/packages/com_mokosuiteclient/admin/tmpl/modules/default.php
@@ -0,0 +1,152 @@
+items;
+$total = $this->total;
+$filters = $this->filters;
+$token = Session::getFormToken();
+$input = Factory::getApplication()->getInput();
+$page = max(1, $input->getInt('page', 1));
+$pages = max(1, ceil($total / 50));
+
+$publishedLabels = [1 => 'Published', 0 => 'Unpublished', -2 => 'Trashed'];
+$publishedColors = [1 => 'success', 0 => 'danger', -2 => 'dark'];
+?>
+
+
+
+
+
+
+
+
+
+
+ | ID |
+ Title |
+ Position |
+ Type |
+ Client |
+ Order |
+ Status |
+
+
+
+
+ | No modules found. |
+
+
+
+ | id; ?> |
+
+
+ title, ENT_QUOTES, 'UTF-8'); ?>
+
+ |
+ position ?: '(none)', ENT_QUOTES, 'UTF-8'); ?> |
+ module, ENT_QUOTES, 'UTF-8'); ?> |
+ client_id ? 'Admin' : 'Site'; ?> |
+ ordering; ?> |
+
+ published;
+ $label = $publishedLabels[$pub] ?? 'Unknown';
+ $color = $publishedColors[$pub] ?? 'secondary';
+ ?>
+
+
+
+ |
+
+
+
+
+
+
+
+
+ 1): ?>
+
+
+
+
+
diff --git a/source/packages/com_mokosuiteclient/admin/tmpl/replacements/default.php b/source/packages/com_mokosuiteclient/admin/tmpl/replacements/default.php
new file mode 100644
index 00000000..28d5013f
--- /dev/null
+++ b/source/packages/com_mokosuiteclient/admin/tmpl/replacements/default.php
@@ -0,0 +1,142 @@
+items;
+$total = $this->total;
+$filters = $this->filters;
+$token = Session::getFormToken();
+$input = Factory::getApplication()->getInput();
+$page = max(1, $input->getInt('page', 1));
+$pages = max(1, ceil($total / 50));
+?>
+
+
+
+
+
+
+
+
+
+
+ | ID |
+ Name |
+ Search |
+ Replace |
+ Area |
+ Regex |
+ Category |
+ Status |
+
+
+
+
+ | No replacement rules found. |
+
+
+
+ | id; ?> |
+
+ color): ?>
+
+
+ name, ENT_QUOTES, 'UTF-8'); ?>
+ |
+ search, 0, 50, '...'), ENT_QUOTES, 'UTF-8'); ?> |
+ replace_value, 0, 50, '...'), ENT_QUOTES, 'UTF-8'); ?> |
+ area, ENT_QUOTES, 'UTF-8'); ?> |
+ regex ? 'Yes' : ''; ?> |
+
+ category): ?>
+ category, ENT_QUOTES, 'UTF-8'); ?>
+
+ |
+
+
+ published ? 'Published' : 'Unpublished'; ?>
+
+ |
+
+
+
+
+
+
+
+
+ 1): ?>
+
+
+
+
+
diff --git a/source/packages/com_mokosuiteclient/admin/tmpl/snippets/default.php b/source/packages/com_mokosuiteclient/admin/tmpl/snippets/default.php
new file mode 100644
index 00000000..5540495a
--- /dev/null
+++ b/source/packages/com_mokosuiteclient/admin/tmpl/snippets/default.php
@@ -0,0 +1,141 @@
+items;
+$total = $this->total;
+$filters = $this->filters;
+$token = Session::getFormToken();
+$input = Factory::getApplication()->getInput();
+$page = max(1, $input->getInt('page', 1));
+$pages = max(1, ceil($total / 50));
+?>
+
+
+
+
+
+
+
+
+
+
+ | ID |
+ Name |
+ Alias |
+ Category |
+ Order |
+ Status |
+
+
+
+
+ | No snippets found. |
+
+
+
+ | id; ?> |
+
+ color): ?>
+
+
+ name, ENT_QUOTES, 'UTF-8'); ?>
+ description): ?>
+ description, 0, 80, '...'), ENT_QUOTES, 'UTF-8'); ?>
+
+ |
+ {snippet alias, ENT_QUOTES, 'UTF-8'); ?>} |
+
+ category): ?>
+ category, ENT_QUOTES, 'UTF-8'); ?>
+
+ |
+ ordering; ?> |
+
+
+ published ? 'Published' : 'Unpublished'; ?>
+
+ |
+
+
+
+
+
+
+
+
+ 1): ?>
+
+
+
+
+
diff --git a/source/packages/com_mokosuiteclient/admin/tmpl/templates/default.php b/source/packages/com_mokosuiteclient/admin/tmpl/templates/default.php
new file mode 100644
index 00000000..e2687125
--- /dev/null
+++ b/source/packages/com_mokosuiteclient/admin/tmpl/templates/default.php
@@ -0,0 +1,141 @@
+items;
+$total = $this->total;
+$filters = $this->filters;
+$token = Session::getFormToken();
+$input = Factory::getApplication()->getInput();
+$page = max(1, $input->getInt('page', 1));
+$pages = max(1, ceil($total / 50));
+?>
+
+
+
+
+
+
+
+
+
+
+ | ID |
+ Name |
+ Alias |
+ Category |
+ Order |
+ Status |
+
+
+
+
+ | No content templates found. |
+
+
+
+ | id; ?> |
+
+ color): ?>
+
+
+ name, ENT_QUOTES, 'UTF-8'); ?>
+ description): ?>
+ description, 0, 80, '...'), ENT_QUOTES, 'UTF-8'); ?>
+
+ |
+ alias, ENT_QUOTES, 'UTF-8'); ?> |
+
+ category): ?>
+ category, ENT_QUOTES, 'UTF-8'); ?>
+
+ |
+ ordering; ?> |
+
+
+ published ? 'Published' : 'Unpublished'; ?>
+
+ |
+
+
+
+
+
+
+
+
+ 1): ?>
+
+
+
+
+
diff --git a/source/packages/com_mokosuiteclient/media/js/dashboard.js b/source/packages/com_mokosuiteclient/media/js/dashboard.js
index 4ab80ad8..9d071b19 100644
--- a/source/packages/com_mokosuiteclient/media/js/dashboard.js
+++ b/source/packages/com_mokosuiteclient/media/js/dashboard.js
@@ -112,7 +112,6 @@ document.addEventListener('DOMContentLoaded', function () {
// Heartbeat + PIN send button
var hbBtn = document.getElementById('mokosuiteclient-btn-heartbeat-pin');
- var hbIconTimeout = null;
if (hbBtn) {
hbBtn.addEventListener('click', function () {
var btn = this;
@@ -120,7 +119,6 @@ document.addEventListener('DOMContentLoaded', function () {
var token = btn.dataset.token;
var icon = btn.querySelector('span');
- if (hbIconTimeout) { clearTimeout(hbIconTimeout); hbIconTimeout = null; }
btn.disabled = true;
if (icon) { icon.className = 'icon-spinner icon-spin'; icon.style.color = ''; }
@@ -150,9 +148,8 @@ document.addEventListener('DOMContentLoaded', function () {
})
.finally(function () {
btn.disabled = false;
- hbIconTimeout = setTimeout(function () {
+ setTimeout(function () {
if (icon) { icon.className = 'icon-upload'; icon.style.color = ''; }
- hbIconTimeout = null;
}, 3000);
});
});
diff --git a/source/packages/com_mokosuiteclient/mokosuiteclient.xml b/source/packages/com_mokosuiteclient/mokosuiteclient.xml
index cbf8d919..262dcf4e 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.52.04
+ 02.52.13
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
@@ -47,6 +47,12 @@
+
+
+
+
+
+
diff --git a/source/packages/mod_mokosuiteclient_cache/mod_mokosuiteclient_cache.xml b/source/packages/mod_mokosuiteclient_cache/mod_mokosuiteclient_cache.xml
index 4f9371ee..20f40a3a 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.52.04
+ 02.52.13
MOD_MOKOSUITECLIENT_CACHE_DESC
Moko\Module\MokoSuiteClientCache
diff --git a/source/packages/mod_mokosuiteclient_categories/mod_mokosuiteclient_categories.xml b/source/packages/mod_mokosuiteclient_categories/mod_mokosuiteclient_categories.xml
index 8577e1e1..4aaace1a 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.52.04
+ 02.52.13
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 63cc14c6..65d7ea75 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.52.04
+ 02.52.13
MOD_MOKOSUITECLIENT_CPANEL_DESC
Moko\Module\MokoSuiteClientCpanel
diff --git a/source/packages/mod_mokosuiteclient_menu/mod_mokosuiteclient_menu.xml b/source/packages/mod_mokosuiteclient_menu/mod_mokosuiteclient_menu.xml
index d24255b4..71925e91 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.52.04
+ 02.52.13
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/mod_mokosuiteclient_menu/tmpl/default.php b/source/packages/mod_mokosuiteclient_menu/tmpl/default.php
index e03a2931..d03a3529 100644
--- a/source/packages/mod_mokosuiteclient_menu/tmpl/default.php
+++ b/source/packages/mod_mokosuiteclient_menu/tmpl/default.php
@@ -28,6 +28,7 @@ $allViews = [
['icon' => 'fa-solid fa-file-lines', 'title' => 'Templates', 'link' => 'index.php?option=com_mokosuiteclient&view=templates', 'acl' => 'mokosuiteclient.templates.manage'],
['icon' => 'fa-solid fa-right-left', 'title' => 'Replacements', 'link' => 'index.php?option=com_mokosuiteclient&view=replacements','acl' => 'mokosuiteclient.replacements.manage'],
['icon' => 'fa-solid fa-shuffle', 'title' => 'Conditions', 'link' => 'index.php?option=com_mokosuiteclient&view=conditions', 'acl' => 'mokosuiteclient.conditions.manage'],
+ ['icon' => 'icon-cube', 'title' => 'Modules', 'link' => 'index.php?option=com_mokosuiteclient&view=modules', 'acl' => 'core.admin'],
['icon' => 'icon-database', 'title' => 'Database Tools', 'link' => 'index.php?option=com_mokosuiteclient&view=database', 'acl' => 'core.admin'],
['icon' => 'icon-trash', 'title' => 'Cache Cleanup', 'link' => 'index.php?option=com_mokosuiteclient&view=cleanup', 'acl' => 'mokosuiteclient.cache'],
['icon' => 'icon-power-off', 'title' => 'Feature Plugins', 'link' => 'index.php?option=com_plugins&filter[folder]=system&filter[search]=mokosuiteclient', 'acl' => 'core.admin'],
@@ -42,9 +43,10 @@ $iconOverrides = [
'com_mokosuiteclient' => 'icon-shield-alt',
'com_mokosuitehq' => 'icon-tachometer-alt',
'com_mokosuitebackup' => 'icon-archive',
- 'com_mokosuitecrm' => 'icon-address-book',
- 'com_mokosuiteerp' => 'icon-briefcase',
+ 'com_mokosuite_crm' => 'icon-address-book',
+ 'com_mokosuite_erp' => 'icon-briefcase',
'com_mokosuiteshop' => 'icon-shopping-cart',
+ 'com_mokoshop' => 'icon-shopping-cart',
'com_mokosuitepos' => 'icon-calculator',
'com_mokosuitemrp' => 'icon-cogs',
'com_mokosuitehrm' => 'icon-id-badge',
@@ -56,8 +58,24 @@ $iconOverrides = [
'com_mokosuiteforms' => 'icon-list-alt',
'com_mokosuitecommunity' => 'icon-comments',
'com_mokosuitecross' => 'icon-share-alt',
+ 'com_mokoog' => 'icon-globe',
'com_mokosuiteopengraph' => 'icon-globe',
'com_mokosuitestorelocator' => 'icon-map-marker-alt',
+ 'com_mokosuiteanalytics' => 'icon-chart-line',
+ 'com_mokosuitesecurity' => 'icon-lock',
+ 'com_mokosuitenotify' => 'icon-bell',
+ 'com_mokosuiteworkflow' => 'icon-random',
+ 'com_mokosuiteai' => 'icon-magic',
+ 'com_mokosuiteauto' => 'icon-car',
+ 'com_mokosuitebeauty' => 'icon-spa',
+ 'com_mokosuiteconstruction' => 'icon-hard-hat',
+ 'com_mokosuiteeditor' => 'icon-edit',
+ 'com_mokosuiteevent' => 'icon-calendar',
+ 'com_mokosuiteinsight' => 'icon-lightbulb',
+ 'com_mokosuitelibrary' => 'icon-book',
+ 'com_mokosuiterealty' => 'icon-home',
+ 'com_mokosuitesupport' => 'icon-life-ring',
+ 'com_mokosuitetaxi' => 'icon-taxi',
];
$childIconMap = [
diff --git a/source/packages/plg_system_mokosuiteclient/Extension/MokoSuiteClient.php b/source/packages/plg_system_mokosuiteclient/Extension/MokoSuiteClient.php
index 69256abb..3383f45e 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.52.04
+ * VERSION: 02.52.13
* PATH: /src/Extension/MokoSuiteClient.php
* NOTE: Core system plugin for MokoSuiteClient admin tools suite
*/
diff --git a/source/packages/plg_system_mokosuiteclient/Field/ArticlesField.php b/source/packages/plg_system_mokosuiteclient/Field/ArticlesField.php
index 1a06b149..5c7c4379 100644
--- a/source/packages/plg_system_mokosuiteclient/Field/ArticlesField.php
+++ b/source/packages/plg_system_mokosuiteclient/Field/ArticlesField.php
@@ -8,7 +8,7 @@
* FILE INFORMATION
* DEFGROUP: Joomla.Plugin
* INGROUP: MokoSuiteClient
- * VERSION: 02.52.04
+ * VERSION: 02.52.13
* PATH: /src/Field/ArticlesField.php
* BRIEF: List field that populates with published Joomla articles
*/
diff --git a/source/packages/plg_system_mokosuiteclient/Field/CopyableTokenField.php b/source/packages/plg_system_mokosuiteclient/Field/CopyableTokenField.php
index 64897a51..32a2bc22 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.52.04
+ * VERSION: 02.52.13
* 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 1fc6ccd2..0ea8e044 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.52.04
+ 02.52.13
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 36d435b5..f1c0e567 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.52.04
+ * VERSION: 02.52.13
* 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 c55d3324..a4cf5c00 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.52.04
+ * VERSION: 02.52.13
* 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 b897e3e0..2f433943 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.52.04
+ 02.52.13
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 33c6d97a..9c34d3d5 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.52.04
+ 02.52.13
PLG_SYSTEM_MOKOSUITECLIENT_DBIP_DESC
Moko\Plugin\System\MokoSuiteClientDBIP
diff --git a/source/packages/plg_system_mokosuiteclient_devtools/mokosuiteclient_devtools.xml b/source/packages/plg_system_mokosuiteclient_devtools/mokosuiteclient_devtools.xml
index c943ef2c..76e80304 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.52.04
+ 02.52.13
PLG_SYSTEM_MOKOSUITECLIENT_DEVTOOLS_DESC
Moko\Plugin\System\MokoSuiteClientDevTools
diff --git a/source/packages/plg_system_mokosuiteclient_firewall/mokosuiteclient_firewall.xml b/source/packages/plg_system_mokosuiteclient_firewall/mokosuiteclient_firewall.xml
index 3241c149..ce9242b9 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.52.04
+ 02.52.13
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 6c0fc44b..28844381 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.52.04
+ 02.52.13
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 ac48824b..53527c6e 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.52.04
+ 02.52.13
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 6b755610..d3a4cf0c 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.52.04
+ 02.52.13
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 80ead0e2..5959515f 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.52.04
+ 02.52.13
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 fe497c7c..098b461d 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.52.04
+ * VERSION: 02.52.13
* 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 fb37c65e..80878b8e 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.52.04
+ 02.52.13
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 c141cbbf..4f1b9478 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.52.04
+ * VERSION: 02.52.13
* 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 194993a6..84a161f6 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.52.04
+ * VERSION: 02.52.13
* 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 9484f475..1786853b 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.52.04
+ 02.52.13
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 86be648f..5571e197 100644
--- a/source/pkg_mokosuiteclient.xml
+++ b/source/pkg_mokosuiteclient.xml
@@ -2,7 +2,7 @@
Package - MokoSuiteClient
mokosuiteclient
- 02.52.04
+ 02.52.13
2026-06-02
Moko Consulting
hello@mokoconsulting.tech
diff --git a/source/script.php b/source/script.php
index 35f28ec0..0ce971d0 100644
--- a/source/script.php
+++ b/source/script.php
@@ -818,152 +818,6 @@ class Pkg_MokosuiteclientInstallerScript
}
}
- /**
- * Rewrite all Moko Consulting update server URLs from the old
- * raw/branch/main pattern to the new clean /updates.xml pattern.
- *
- * Old: https://git.mokoconsulting.tech/MokoConsulting/{repo}/raw/branch/main/updates.xml
- * New: https://git.mokoconsulting.tech/MokoConsulting/{repo}/updates.xml
- */
- private function migrateUpdateServerUrls(): void
- {
- try
- {
- $db = Factory::getDbo();
-
- $db->setQuery(
- "UPDATE " . $db->quoteName('#__update_sites')
- . " SET " . $db->quoteName('location') . " = REPLACE("
- . $db->quoteName('location') . ", '/raw/branch/main/updates.xml', '/updates.xml')"
- . " WHERE " . $db->quoteName('location') . " LIKE " . $db->quote('%mokoconsulting.tech%/raw/branch/main/updates.xml')
- );
- $db->execute();
- $count = $db->getAffectedRows();
-
- if ($count > 0)
- {
- Factory::getApplication()->enqueueMessage(
- sprintf('Migrated %d Moko update server URL(s) to new format.', $count),
- 'message'
- );
- }
- }
- catch (\Throwable $e)
- {
- Log::add('Update server URL migration error: ' . $e->getMessage(), Log::WARNING, 'mokosuiteclient');
- }
- }
-
- /**
- * Remove stale and duplicate MokoSuiteClient update site entries.
- *
- * Keeps only the package-level update site pointing to the dynamic
- * MokoGitea endpoint. Removes plugin-level entries, old static URLs,
- * and orphaned #__updates rows tied to deleted update sites.
- *
- * @return void
- *
- * @since 02.31.00
- */
- private function fixUpdateRecords(): void
- {
- try
- {
- $db = Factory::getDbo();
-
- // Link orphaned #__updates records to the installed extension
- $db->setQuery(
- "UPDATE " . $db->quoteName('#__updates') . " u"
- . " JOIN " . $db->quoteName('#__extensions') . " e"
- . " ON u.element = e.element AND u.type = e.type"
- . " SET u.extension_id = e.extension_id"
- . " WHERE u.extension_id = 0"
- . " AND u.element LIKE " . $db->quote('%mokosuiteclient%')
- );
- $db->execute();
- }
- catch (\Throwable $e)
- {
- // Non-critical
- }
- }
-
- private function cleanupStaleUpdateSites(): void
- {
- try
- {
- $db = Factory::getDbo();
- $dynamicUrl = 'https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteClient/updates.xml';
-
- // Find MokoSuiteClient update sites (exclude MokoSuiteClientHQ and other Moko extensions)
- $query = $db->getQuery(true)
- ->select($db->quoteName(['update_site_id', 'location']))
- ->from($db->quoteName('#__update_sites'))
- ->where('(' . $db->quoteName('name') . ' LIKE ' . $db->quote('%MokoSuiteClient%')
- . ' OR ' . $db->quoteName('location') . ' LIKE ' . $db->quote('%MokoSuiteClient%') . ')')
- ->where($db->quoteName('name') . ' NOT LIKE ' . $db->quote('%MokoSuiteClientHQ%'))
- ->where($db->quoteName('location') . ' NOT LIKE ' . $db->quote('%MokoSuiteClientHQ%'));
- $db->setQuery($query);
- $sites = $db->loadObjectList();
-
- $keepId = null;
- $removeIds = [];
-
- foreach ($sites as $site)
- {
- if ($site->location === $dynamicUrl && $keepId === null)
- {
- $keepId = (int) $site->update_site_id;
- }
- else
- {
- $removeIds[] = (int) $site->update_site_id;
- }
- }
-
- if (empty($removeIds))
- {
- return;
- }
-
- $idList = implode(',', $removeIds);
-
- // Remove orphaned #__updates rows
- $db->setQuery(
- $db->getQuery(true)
- ->delete($db->quoteName('#__updates'))
- ->where($db->quoteName('update_site_id') . ' IN (' . $idList . ')')
- )->execute();
-
- // Remove link rows
- $db->setQuery(
- $db->getQuery(true)
- ->delete($db->quoteName('#__update_sites_extensions'))
- ->where($db->quoteName('update_site_id') . ' IN (' . $idList . ')')
- )->execute();
-
- // Remove stale update sites
- $db->setQuery(
- $db->getQuery(true)
- ->delete($db->quoteName('#__update_sites'))
- ->where($db->quoteName('update_site_id') . ' IN (' . $idList . ')')
- )->execute();
-
- $count = count($removeIds);
-
- if ($count > 0)
- {
- Factory::getApplication()->enqueueMessage(
- sprintf('Cleaned up %d stale MokoSuiteClient update site(s).', $count),
- 'message'
- );
- }
- }
- catch (\Throwable $e)
- {
- Log::add('Error cleaning up stale update sites: ' . $e->getMessage(), Log::WARNING, 'jerror');
- }
- }
/**
* Backup all non-empty extra_query values from update sites.
diff --git a/updates.xml b/updates.xml
new file mode 100644
index 00000000..15c911c4
--- /dev/null
+++ b/updates.xml
@@ -0,0 +1,20 @@
+
+
+
+ Package - MokoSuiteClient
+ pkg_mokosuiteclient
+ package
+ 02.52.04
+ https://mokoconsulting.tech/support/mokosuiteclient
+
+ https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteClient/releases/download/stable/pkg_mokosuiteclient-02.52.04.zip
+
+
+ stable
+
+
+ 8.2
+ site
+ MokoSuiteClient - Joomla client-facing tracker and identity layer for the MokoSuite platform.
+
+