Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5584e09ecd | |||
| 931d93e921 | |||
| dbcc02e1a4 | |||
| efeb996703 | |||
| 1002c55147 | |||
| d7f2baeb3e | |||
| 4d4a75cc52 | |||
| ce26dab8fd | |||
| d65d8faf65 | |||
| 6332405853 | |||
| 47f15e4dbb | |||
| a232f2d3b7 | |||
| e6fdda02da | |||
| 987e4e4662 | |||
| 173c20164a | |||
| 2a2240b2be | |||
| f7cd0851c8 | |||
| ea84e53d48 | |||
| 3196cae2e5 | |||
| 009bc3a8be | |||
| cae2831fb1 | |||
| cab1cd7ed8 | |||
| 1f73f70fc2 | |||
| 25baf6afd6 | |||
| 9148548c62 | |||
| 4731ef6100 | |||
| 32fa117569 | |||
| a8b9f7d165 | |||
| 0288af9421 | |||
| 5a16c563f6 | |||
| 92016a91e5 | |||
| 94a0bbb160 | |||
| 3673ca0525 | |||
| 6b6c963bb7 | |||
| 13ce8c6eeb | |||
| bf9c94bbf8 | |||
| 19d4b63ca6 | |||
| 95e0ff04a4 | |||
| 57748a2a23 | |||
| 3f4f2f2d43 | |||
| 7ac776ff28 | |||
| 89b71a5a65 | |||
| 0b3eb7c7aa | |||
| 4b809778f4 | |||
| 7ab1fe4cdd |
@@ -5,7 +5,7 @@
|
|||||||
# FILE INFORMATION
|
# FILE INFORMATION
|
||||||
# DEFGROUP: Gitea.Workflow
|
# DEFGROUP: Gitea.Workflow
|
||||||
# INGROUP: moko-platform.Automation
|
# INGROUP: moko-platform.Automation
|
||||||
# VERSION: 02.48.16
|
# VERSION: 02.48.50
|
||||||
# BRIEF: Auto-create feature branch when an issue is opened
|
# BRIEF: Auto-create feature branch when an issue is opened
|
||||||
|
|
||||||
name: "Universal: Issue Branch"
|
name: "Universal: Issue Branch"
|
||||||
|
|||||||
+6
-1
@@ -14,7 +14,7 @@
|
|||||||
INGROUP: MokoSuiteClient.Documentation
|
INGROUP: MokoSuiteClient.Documentation
|
||||||
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
||||||
PATH: ./CHANGELOG.md
|
PATH: ./CHANGELOG.md
|
||||||
VERSION: 02.48.16
|
VERSION: 02.48.50
|
||||||
BRIEF: Version history using `Keep a Changelog`
|
BRIEF: Version history using `Keep a Changelog`
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@@ -64,6 +64,11 @@
|
|||||||
- **Update server migration** — removed migrateUpdateServerUrls, cleanupStaleUpdateSites, fixUpdateRecords, enableUpdateServer calls
|
- **Update server migration** — removed migrateUpdateServerUrls, cleanupStaleUpdateSites, fixUpdateRecords, enableUpdateServer calls
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
- **Regular Labs import** — destination tables missing from SQL update files; sites that upgraded never got the tables, causing "No data found" on import
|
||||||
|
- **Regular Labs import banner** — detection now requires both source AND destination tables before showing the import button
|
||||||
|
- **DB-IP auto-enrichment** — all IPs in `<code>` tags in admin backend now show country flag emoji and geo tooltip on hover
|
||||||
|
- **MokoSuiteBackup quick action** — dashboard now includes MokoSuiteBackup button when component is installed
|
||||||
|
- **PIN copy** — fixed duplicate click handlers (4 toast messages), "Copied!" not reverting, added "Click to copy" hover tooltip
|
||||||
- Health endpoint cron check SQL error — orphan `setQuery(getQuery(true), 0, 5)` produced bare `LIMIT 5`, returning 503 for all health polls
|
- Health endpoint cron check SQL error — orphan `setQuery(getQuery(true), 0, 5)` produced bare `LIMIT 5`, returning 503 for all health polls
|
||||||
- License plugin missing `src/` and `language/` directories causing install failure
|
- License plugin missing `src/` and `language/` directories causing install failure
|
||||||
- PIN generation inconsistency — controller used `floor(now/TTL)` while display used `floor(requestedAt/TTL)`
|
- PIN generation inconsistency — controller used `floor(now/TTL)` while display used `floor(requestedAt/TTL)`
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@
|
|||||||
DEFGROUP: Joomla.Plugin
|
DEFGROUP: Joomla.Plugin
|
||||||
INGROUP: MokoSuiteClient.Documentation
|
INGROUP: MokoSuiteClient.Documentation
|
||||||
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
||||||
VERSION: 02.48.16
|
VERSION: 02.48.50
|
||||||
PATH: ./CODE_OF_CONDUCT.md
|
PATH: ./CODE_OF_CONDUCT.md
|
||||||
BRIEF: Reference + packaging repo for Moko Consulting Developer GPT Other Default
|
BRIEF: Reference + packaging repo for Moko Consulting Developer GPT Other Default
|
||||||
-->
|
-->
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@
|
|||||||
DEFGROUP: mokoconsulting-tech.MokoSuiteClientBrand
|
DEFGROUP: mokoconsulting-tech.MokoSuiteClientBrand
|
||||||
INGROUP: MokoStandards.Governance
|
INGROUP: MokoStandards.Governance
|
||||||
REPO: https://github.com/mokoconsulting-tech/MokoSuiteClientBrand
|
REPO: https://github.com/mokoconsulting-tech/MokoSuiteClientBrand
|
||||||
VERSION: 02.48.16
|
VERSION: 02.48.50
|
||||||
PATH: /GOVERNANCE.md
|
PATH: /GOVERNANCE.md
|
||||||
BRIEF: Project governance rules, roles, and decision process for MokoSuiteClientBrand
|
BRIEF: Project governance rules, roles, and decision process for MokoSuiteClientBrand
|
||||||
-->
|
-->
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@
|
|||||||
INGROUP: MokoSuiteClient.Documentation
|
INGROUP: MokoSuiteClient.Documentation
|
||||||
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
||||||
PATH: ./LICENSE.md
|
PATH: ./LICENSE.md
|
||||||
VERSION: 02.48.16
|
VERSION: 02.48.50
|
||||||
BRIEF: Project license (GPL-3.0-or-later)
|
BRIEF: Project license (GPL-3.0-or-later)
|
||||||
-->
|
-->
|
||||||
GNU GENERAL PUBLIC LICENSE
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
DEFGROUP: Joomla.Plugin
|
DEFGROUP: Joomla.Plugin
|
||||||
INGROUP: MokoSuiteClient
|
INGROUP: MokoSuiteClient
|
||||||
REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteClient
|
REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteClient
|
||||||
VERSION: 02.48.16
|
VERSION: 02.48.50
|
||||||
PATH: /README.md
|
PATH: /README.md
|
||||||
BRIEF: MokoSuiteClient platform plugin for Joomla
|
BRIEF: MokoSuiteClient platform plugin for Joomla
|
||||||
-->
|
-->
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ DEFGROUP: [PROJECT_NAME]
|
|||||||
INGROUP: [PROJECT_NAME].Documentation
|
INGROUP: [PROJECT_NAME].Documentation
|
||||||
REPO: [REPOSITORY_URL]
|
REPO: [REPOSITORY_URL]
|
||||||
PATH: /SECURITY.md
|
PATH: /SECURITY.md
|
||||||
VERSION: 02.48.16
|
VERSION: 02.48.50
|
||||||
BRIEF: Security vulnerability reporting and handling policy
|
BRIEF: Security vulnerability reporting and handling policy
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
|||||||
@@ -11,13 +11,13 @@
|
|||||||
INGROUP: MokoSuiteClient.Build
|
INGROUP: MokoSuiteClient.Build
|
||||||
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
||||||
FILE: build-guide.md
|
FILE: build-guide.md
|
||||||
VERSION: 02.48.16
|
VERSION: 02.48.50
|
||||||
PATH: /docs/guides/
|
PATH: /docs/guides/
|
||||||
BRIEF: Build and packaging guide for the MokoSuiteClient system plugin
|
BRIEF: Build and packaging guide for the MokoSuiteClient system plugin
|
||||||
NOTE: Defines environment setup, repository layout, packaging rules, and release preparation
|
NOTE: Defines environment setup, repository layout, packaging rules, and release preparation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
# MokoSuiteClient Build Guide (VERSION: 02.48.16)
|
# MokoSuiteClient Build Guide (VERSION: 02.48.50)
|
||||||
|
|
||||||
## 1. Purpose
|
## 1. Purpose
|
||||||
|
|
||||||
|
|||||||
@@ -10,13 +10,13 @@
|
|||||||
DEFGROUP: Joomla.Plugin
|
DEFGROUP: Joomla.Plugin
|
||||||
INGROUP: MokoSuiteClient.Guides
|
INGROUP: MokoSuiteClient.Guides
|
||||||
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
||||||
VERSION: 02.48.16
|
VERSION: 02.48.50
|
||||||
PATH: /docs/guides/configuration-guide.md
|
PATH: /docs/guides/configuration-guide.md
|
||||||
BRIEF: Configuration guide for the MokoSuiteClient system plugin
|
BRIEF: Configuration guide for the MokoSuiteClient system plugin
|
||||||
NOTE: Defines plugin parameters, expected behaviors, and recommended defaults
|
NOTE: Defines plugin parameters, expected behaviors, and recommended defaults
|
||||||
-->
|
-->
|
||||||
|
|
||||||
# MokoSuiteClient Configuration Guide (VERSION: 02.48.16)
|
# MokoSuiteClient Configuration Guide (VERSION: 02.48.50)
|
||||||
|
|
||||||
## 1. Objective
|
## 1. Objective
|
||||||
|
|
||||||
|
|||||||
@@ -10,13 +10,13 @@
|
|||||||
DEFGROUP: Joomla.Plugin
|
DEFGROUP: Joomla.Plugin
|
||||||
INGROUP: MokoSuiteClient.Guides
|
INGROUP: MokoSuiteClient.Guides
|
||||||
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
||||||
VERSION: 02.48.16
|
VERSION: 02.48.50
|
||||||
PATH: /docs/guides/installation-guide.md
|
PATH: /docs/guides/installation-guide.md
|
||||||
BRIEF: Installation guide for the MokoSuiteClient system plugin
|
BRIEF: Installation guide for the MokoSuiteClient system plugin
|
||||||
NOTE: First document in the guide set
|
NOTE: First document in the guide set
|
||||||
-->
|
-->
|
||||||
|
|
||||||
# MokoSuiteClient Installation Guide (VERSION: 02.48.16)
|
# MokoSuiteClient Installation Guide (VERSION: 02.48.50)
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
|
|||||||
@@ -10,13 +10,13 @@
|
|||||||
DEFGROUP: Joomla.Plugin
|
DEFGROUP: Joomla.Plugin
|
||||||
INGROUP: MokoSuiteClient.Guides
|
INGROUP: MokoSuiteClient.Guides
|
||||||
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
||||||
VERSION: 02.48.16
|
VERSION: 02.48.50
|
||||||
PATH: /docs/guides/operations-guide.md
|
PATH: /docs/guides/operations-guide.md
|
||||||
BRIEF: Operational guide for administering and managing the MokoSuiteClient system plugin
|
BRIEF: Operational guide for administering and managing the MokoSuiteClient system plugin
|
||||||
NOTE: Defines lifecycle, responsibilities, and operational behaviors
|
NOTE: Defines lifecycle, responsibilities, and operational behaviors
|
||||||
-->
|
-->
|
||||||
|
|
||||||
# MokoSuiteClient Operations Guide (VERSION: 02.48.16)
|
# MokoSuiteClient Operations Guide (VERSION: 02.48.50)
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
|
|||||||
@@ -10,13 +10,13 @@
|
|||||||
DEFGROUP: Joomla.Plugin
|
DEFGROUP: Joomla.Plugin
|
||||||
INGROUP: MokoSuiteClient.Guides
|
INGROUP: MokoSuiteClient.Guides
|
||||||
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
||||||
VERSION: 02.48.16
|
VERSION: 02.48.50
|
||||||
PATH: /docs/guides/rollback-and-recovery-guide.md
|
PATH: /docs/guides/rollback-and-recovery-guide.md
|
||||||
BRIEF: Rollback and recovery guide for restoring stable operation after plugin related incidents
|
BRIEF: Rollback and recovery guide for restoring stable operation after plugin related incidents
|
||||||
NOTE: Completes the core guide set for Suite plugin governance
|
NOTE: Completes the core guide set for Suite plugin governance
|
||||||
-->
|
-->
|
||||||
|
|
||||||
# MokoSuiteClient Rollback and Recovery Guide (VERSION: 02.48.16)
|
# MokoSuiteClient Rollback and Recovery Guide (VERSION: 02.48.50)
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
|
|||||||
@@ -7,13 +7,13 @@
|
|||||||
DEFGROUP: Joomla.Plugin
|
DEFGROUP: Joomla.Plugin
|
||||||
INGROUP: MokoSuiteClient.Guides
|
INGROUP: MokoSuiteClient.Guides
|
||||||
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
||||||
VERSION: 02.48.16
|
VERSION: 02.48.50
|
||||||
PATH: /docs/guides/testing-guide.md
|
PATH: /docs/guides/testing-guide.md
|
||||||
BRIEF: Testing guide for MokoSuiteClient v02.01.08
|
BRIEF: Testing guide for MokoSuiteClient v02.01.08
|
||||||
NOTE: Covers manual test procedures for language overrides, install/uninstall, and configuration
|
NOTE: Covers manual test procedures for language overrides, install/uninstall, and configuration
|
||||||
-->
|
-->
|
||||||
|
|
||||||
# MokoSuiteClient Testing Guide (VERSION: 02.48.16)
|
# MokoSuiteClient Testing Guide (VERSION: 02.48.50)
|
||||||
|
|
||||||
## 1. Prerequisites
|
## 1. Prerequisites
|
||||||
|
|
||||||
|
|||||||
@@ -10,13 +10,13 @@
|
|||||||
DEFGROUP: Joomla.Plugin
|
DEFGROUP: Joomla.Plugin
|
||||||
INGROUP: MokoSuiteClient.Guides
|
INGROUP: MokoSuiteClient.Guides
|
||||||
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
||||||
VERSION: 02.48.16
|
VERSION: 02.48.50
|
||||||
PATH: /docs/guides/troubleshooting-guide.md
|
PATH: /docs/guides/troubleshooting-guide.md
|
||||||
BRIEF: Troubleshooting guide for diagnosing and resolving issues related to the MokoSuiteClient plugin
|
BRIEF: Troubleshooting guide for diagnosing and resolving issues related to the MokoSuiteClient plugin
|
||||||
NOTE: Designed for administrators and Suite operations teams
|
NOTE: Designed for administrators and Suite operations teams
|
||||||
-->
|
-->
|
||||||
|
|
||||||
# MokoSuiteClient Troubleshooting Guide (VERSION: 02.48.16)
|
# MokoSuiteClient Troubleshooting Guide (VERSION: 02.48.50)
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
|
|||||||
@@ -10,13 +10,13 @@
|
|||||||
DEFGROUP: Joomla.Plugin
|
DEFGROUP: Joomla.Plugin
|
||||||
INGROUP: MokoSuiteClient.Guides
|
INGROUP: MokoSuiteClient.Guides
|
||||||
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
||||||
VERSION: 02.48.16
|
VERSION: 02.48.50
|
||||||
PATH: /docs/guides/upgrade-and-versioning-guide.md
|
PATH: /docs/guides/upgrade-and-versioning-guide.md
|
||||||
BRIEF: Guide for updating, versioning, and maintaining the MokoSuiteClient plugin
|
BRIEF: Guide for updating, versioning, and maintaining the MokoSuiteClient plugin
|
||||||
NOTE: Defines release flow, version rules, and upgrade validation
|
NOTE: Defines release flow, version rules, and upgrade validation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
# MokoSuiteClient Upgrade and Versioning Guide (VERSION: 02.48.16)
|
# MokoSuiteClient Upgrade and Versioning Guide (VERSION: 02.48.50)
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -10,13 +10,13 @@
|
|||||||
DEFGROUP: Joomla.Plugin
|
DEFGROUP: Joomla.Plugin
|
||||||
INGROUP: MokoSuiteClient.Documentation
|
INGROUP: MokoSuiteClient.Documentation
|
||||||
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
||||||
VERSION: 02.48.16
|
VERSION: 02.48.50
|
||||||
PATH: /docs/index.md
|
PATH: /docs/index.md
|
||||||
BRIEF: Master index of all documentation for the MokoSuiteClient plugin
|
BRIEF: Master index of all documentation for the MokoSuiteClient plugin
|
||||||
NOTE: Automatically maintained index for all guide canvases
|
NOTE: Automatically maintained index for all guide canvases
|
||||||
-->
|
-->
|
||||||
|
|
||||||
# MokoSuiteClient Documentation Index (VERSION: 02.48.16)
|
# MokoSuiteClient Documentation Index (VERSION: 02.48.50)
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
|
|||||||
@@ -11,12 +11,12 @@
|
|||||||
INGROUP: MokoSuiteClient
|
INGROUP: MokoSuiteClient
|
||||||
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
||||||
PATH: /docs/plugin-basic.md
|
PATH: /docs/plugin-basic.md
|
||||||
VERSION: 02.48.16
|
VERSION: 02.48.50
|
||||||
BRIEF: Baseline documentation for the MokoSuiteClient system plugin
|
BRIEF: Baseline documentation for the MokoSuiteClient system plugin
|
||||||
NOTE: Foundational reference for internal and external stakeholders
|
NOTE: Foundational reference for internal and external stakeholders
|
||||||
-->
|
-->
|
||||||
|
|
||||||
# MokoSuiteClient Plugin Overview (VERSION: 02.48.16)
|
# MokoSuiteClient Plugin Overview (VERSION: 02.48.50)
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ DEFGROUP: MokoSuiteClient.Documentation
|
|||||||
INGROUP: MokoStandards.Templates
|
INGROUP: MokoStandards.Templates
|
||||||
REPO: https://github.com/mokoconsulting-tech/MokoSuiteClient
|
REPO: https://github.com/mokoconsulting-tech/MokoSuiteClient
|
||||||
PATH: /docs/update-server.md
|
PATH: /docs/update-server.md
|
||||||
VERSION: 02.48.16
|
VERSION: 02.48.50
|
||||||
BRIEF: How this extension's Joomla update server file (update.xml) is managed
|
BRIEF: How this extension's Joomla update server file (update.xml) is managed
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
-- Regular Labs replacement tables (conditions, snippets, replacements, content templates)
|
||||||
|
-- These were in install.mysql.sql but missing from updates, so existing installs never got them.
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `#__mokosuiteclient_conditions` (
|
||||||
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`alias` VARCHAR(100) NOT NULL DEFAULT '',
|
||||||
|
`name` VARCHAR(100) NOT NULL DEFAULT '',
|
||||||
|
`description` TEXT NOT NULL,
|
||||||
|
`category` VARCHAR(50) NOT NULL DEFAULT '',
|
||||||
|
`color` VARCHAR(8) DEFAULT NULL,
|
||||||
|
`match_all` TINYINT(1) NOT NULL DEFAULT 1,
|
||||||
|
`published` TINYINT(1) NOT NULL DEFAULT 1,
|
||||||
|
`hash` VARCHAR(32) NOT NULL DEFAULT '',
|
||||||
|
`checked_out` INT UNSIGNED DEFAULT NULL,
|
||||||
|
`checked_out_time` DATETIME DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `idx_published` (`published`),
|
||||||
|
KEY `idx_alias` (`alias`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `#__mokosuiteclient_conditions_groups` (
|
||||||
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`condition_id` INT UNSIGNED NOT NULL,
|
||||||
|
`match_all` TINYINT(1) NOT NULL DEFAULT 1,
|
||||||
|
`ordering` INT UNSIGNED NOT NULL DEFAULT 0,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `idx_condition` (`condition_id`),
|
||||||
|
KEY `idx_ordering` (`condition_id`, `ordering`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `#__mokosuiteclient_conditions_rules` (
|
||||||
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`group_id` INT UNSIGNED NOT NULL,
|
||||||
|
`type` VARCHAR(50) NOT NULL DEFAULT '',
|
||||||
|
`exclude` TINYINT(1) NOT NULL DEFAULT 0,
|
||||||
|
`params` TEXT NOT NULL,
|
||||||
|
`ordering` INT UNSIGNED NOT NULL DEFAULT 0,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `idx_group` (`group_id`),
|
||||||
|
KEY `idx_type` (`type`),
|
||||||
|
KEY `idx_ordering` (`group_id`, `ordering`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `#__mokosuiteclient_conditions_map` (
|
||||||
|
`condition_id` INT UNSIGNED NOT NULL,
|
||||||
|
`extension` VARCHAR(50) NOT NULL DEFAULT '',
|
||||||
|
`item_id` INT UNSIGNED NOT NULL DEFAULT 0,
|
||||||
|
UNIQUE KEY `idx_unique` (`condition_id`, `item_id`, `extension`),
|
||||||
|
KEY `idx_ext_item` (`extension`, `item_id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `#__mokosuiteclient_snippets` (
|
||||||
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`alias` VARCHAR(100) NOT NULL DEFAULT '',
|
||||||
|
`name` VARCHAR(100) NOT NULL DEFAULT '',
|
||||||
|
`description` TEXT NOT NULL,
|
||||||
|
`category` VARCHAR(50) NOT NULL DEFAULT '',
|
||||||
|
`color` VARCHAR(8) DEFAULT NULL,
|
||||||
|
`content` MEDIUMTEXT NOT NULL,
|
||||||
|
`params` TEXT NOT NULL,
|
||||||
|
`published` TINYINT(1) NOT NULL DEFAULT 0,
|
||||||
|
`ordering` INT NOT NULL DEFAULT 0,
|
||||||
|
`checked_out` INT UNSIGNED DEFAULT NULL,
|
||||||
|
`checked_out_time` DATETIME DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `idx_alias` (`alias`),
|
||||||
|
KEY `idx_published` (`published`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `#__mokosuiteclient_replacements` (
|
||||||
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` VARCHAR(100) NOT NULL DEFAULT '',
|
||||||
|
`search` TEXT NOT NULL,
|
||||||
|
`replace_value` TEXT NOT NULL,
|
||||||
|
`area` VARCHAR(20) NOT NULL DEFAULT 'both',
|
||||||
|
`regex` TINYINT(1) NOT NULL DEFAULT 0,
|
||||||
|
`casesensitive` TINYINT(1) NOT NULL DEFAULT 0,
|
||||||
|
`category` VARCHAR(50) NOT NULL DEFAULT '',
|
||||||
|
`published` TINYINT(1) NOT NULL DEFAULT 0,
|
||||||
|
`description` TEXT NOT NULL,
|
||||||
|
`enable_in_admin` TINYINT(1) NOT NULL DEFAULT 0,
|
||||||
|
`color` VARCHAR(8) DEFAULT NULL,
|
||||||
|
`ordering` INT NOT NULL DEFAULT 0,
|
||||||
|
`checked_out` INT UNSIGNED DEFAULT NULL,
|
||||||
|
`checked_out_time` DATETIME DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `idx_published` (`published`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `#__mokosuiteclient_content_templates` (
|
||||||
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`alias` VARCHAR(100) NOT NULL DEFAULT '',
|
||||||
|
`name` VARCHAR(255) NOT NULL DEFAULT '',
|
||||||
|
`description` TEXT NOT NULL,
|
||||||
|
`category` VARCHAR(50) NOT NULL DEFAULT '',
|
||||||
|
`color` VARCHAR(8) DEFAULT NULL,
|
||||||
|
`template_data` MEDIUMTEXT NOT NULL,
|
||||||
|
`joomla_category_id` INT NOT NULL DEFAULT 0,
|
||||||
|
`access` INT UNSIGNED NOT NULL DEFAULT 1,
|
||||||
|
`published` TINYINT(1) NOT NULL DEFAULT 1,
|
||||||
|
`ordering` INT NOT NULL DEFAULT 0,
|
||||||
|
`checked_out` INT UNSIGNED DEFAULT NULL,
|
||||||
|
`checked_out_time` DATETIME DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `idx_published` (`published`),
|
||||||
|
KEY `idx_alias` (`alias`),
|
||||||
|
KEY `idx_category` (`joomla_category_id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
@@ -198,7 +198,7 @@ class SupportPinHelper
|
|||||||
navigator.clipboard.writeText(pin).then(function() {
|
navigator.clipboard.writeText(pin).then(function() {
|
||||||
if (textEl) {
|
if (textEl) {
|
||||||
textEl.textContent = 'Copied!';
|
textEl.textContent = 'Copied!';
|
||||||
setTimeout(function() { textEl.textContent = pin; }, 30000);
|
setTimeout(function() { textEl.textContent = pin; }, 5000);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,15 +44,16 @@ class HtmlView extends BaseHtmlView
|
|||||||
$this->supportPinAvailable = $pinState['available'];
|
$this->supportPinAvailable = $pinState['available'];
|
||||||
$this->supportPin = $pinState['pin'];
|
$this->supportPin = $pinState['pin'];
|
||||||
|
|
||||||
// Detect Regular Labs data for import
|
// Detect Regular Labs data for import (source table must exist AND our destination table)
|
||||||
try {
|
try {
|
||||||
$rlDb = \Joomla\CMS\Factory::getDbo();
|
$rlDb = \Joomla\CMS\Factory::getDbo();
|
||||||
$rlTables = $rlDb->getTableList();
|
$rlTables = $rlDb->getTableList();
|
||||||
$rlPrefix = $rlDb->getPrefix();
|
$rlPrefix = $rlDb->getPrefix();
|
||||||
$this->regularLabsAvailable = in_array($rlPrefix . 'conditions', $rlTables)
|
$this->regularLabsAvailable =
|
||||||
|| in_array($rlPrefix . 'snippets', $rlTables)
|
(in_array($rlPrefix . 'conditions', $rlTables) && in_array($rlPrefix . 'mokosuiteclient_conditions', $rlTables))
|
||||||
|| in_array($rlPrefix . 'rereplacer', $rlTables)
|
|| (in_array($rlPrefix . 'snippets', $rlTables) && in_array($rlPrefix . 'mokosuiteclient_snippets', $rlTables))
|
||||||
|| in_array($rlPrefix . 'contenttemplater', $rlTables);
|
|| (in_array($rlPrefix . 'rereplacer', $rlTables) && in_array($rlPrefix . 'mokosuiteclient_replacements', $rlTables))
|
||||||
|
|| (in_array($rlPrefix . 'contenttemplater', $rlTables) && in_array($rlPrefix . 'mokosuiteclient_content_templates', $rlTables));
|
||||||
} catch (\Throwable $e) {}
|
} catch (\Throwable $e) {}
|
||||||
|
|
||||||
$this->recentLogins = $model->getRecentLogins(10);
|
$this->recentLogins = $model->getRecentLogins(10);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<license>GPL-3.0-or-later</license>
|
<license>GPL-3.0-or-later</license>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||||
<version>02.48.16</version>
|
<version>02.48.50</version>
|
||||||
<description>MokoSuiteClient admin dashboard and REST API. Provides a control panel for managing MokoSuiteClient feature plugins, site health monitoring, and remote management endpoints.</description>
|
<description>MokoSuiteClient admin dashboard and REST API. Provides a control panel for managing MokoSuiteClient feature plugins, site health monitoring, and remote management endpoints.</description>
|
||||||
|
|
||||||
<namespace path="src">Moko\Component\MokoSuiteClient</namespace>
|
<namespace path="src">Moko\Component\MokoSuiteClient</namespace>
|
||||||
@@ -74,10 +74,6 @@
|
|||||||
<folder>tmpl</folder>
|
<folder>tmpl</folder>
|
||||||
</files>
|
</files>
|
||||||
|
|
||||||
<install>
|
|
||||||
<sql><file driver="mysql" charset="utf8">admin/sql/install.mysql.sql</file></sql>
|
|
||||||
</install>
|
|
||||||
|
|
||||||
<api>
|
<api>
|
||||||
<files folder="api">
|
<files folder="api">
|
||||||
<folder>src</folder>
|
<folder>src</folder>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<license>GPL-3.0-or-later</license>
|
<license>GPL-3.0-or-later</license>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||||
<version>02.48.16</version>
|
<version>02.48.50</version>
|
||||||
<description>MOD_MOKOSUITECLIENT_CACHE_DESC</description>
|
<description>MOD_MOKOSUITECLIENT_CACHE_DESC</description>
|
||||||
<namespace path="src">Moko\Module\MokoSuiteClientCache</namespace>
|
<namespace path="src">Moko\Module\MokoSuiteClientCache</namespace>
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* MokoSuiteClient Cache & Temp Cleaner — status bar split button
|
* MokoSuiteClient Cache & Temp Cleaner — status bar with Clean dropdown
|
||||||
*
|
*
|
||||||
* 4 buttons: Frontend link | Support PIN | Clear Cache | Clear Temp
|
* Buttons: Frontend link | Support PIN | Clean ▾ (Cache / Temp)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
defined('_JEXEC') or die;
|
defined('_JEXEC') or die;
|
||||||
@@ -34,12 +34,23 @@ $frontendUrl = $frontendUrl ?? '';
|
|||||||
}
|
}
|
||||||
echo $pinHtml;
|
echo $pinHtml;
|
||||||
endif; ?>
|
endif; ?>
|
||||||
<a href="#" class="btn btn-sm btn-outline-primary <?php echo ($pinAvailable || $frontendUrl) ? 'rounded-0 border-end-0' : 'rounded-0 rounded-start border-end-0'; ?> d-flex align-items-center gap-1 px-3 py-2" id="mokosuiteclient-clear-cache" title="Clear all Joomla cache" style="font-size:0.8rem;">
|
<div class="btn-group">
|
||||||
<span class="icon-bolt" aria-hidden="true" id="mokosuiteclient-cache-icon"></span> Cache
|
<button type="button" class="btn btn-sm btn-outline-secondary <?php echo ($pinAvailable || $frontendUrl) ? 'rounded-0 rounded-end' : 'rounded'; ?> d-flex align-items-center gap-1 px-3 py-2 dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false" style="font-size:0.8rem;" id="mokosuite-clean-dropdown">
|
||||||
</a>
|
<span class="icon-broom" aria-hidden="true"></span> Clean
|
||||||
<a href="#" class="btn btn-sm btn-outline-danger rounded-0 rounded-end d-flex align-items-center gap-1 px-3 py-2" id="mokosuiteclient-clear-temp" title="Clear temp directory" style="font-size:0.8rem;">
|
</button>
|
||||||
<span class="icon-trash" aria-hidden="true" id="mokosuiteclient-temp-icon"></span> Temp
|
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="mokosuite-clean-dropdown">
|
||||||
</a>
|
<li>
|
||||||
|
<a href="#" class="dropdown-item d-flex align-items-center gap-2" id="mokosuiteclient-clear-cache">
|
||||||
|
<span class="icon-bolt" aria-hidden="true" id="mokosuiteclient-cache-icon"></span> Clear Cache
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#" class="dropdown-item d-flex align-items-center gap-2" id="mokosuiteclient-clear-temp">
|
||||||
|
<span class="icon-trash" aria-hidden="true" id="mokosuiteclient-temp-icon"></span> Clear Temp
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -94,7 +105,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
|
|
||||||
setupCleaner('mokosuiteclient-clear-cache', 'mokosuiteclient-cache-icon', '<?php echo $cacheUrl; ?>', '<?php echo $token; ?>');
|
setupCleaner('mokosuiteclient-clear-cache', 'mokosuiteclient-cache-icon', '<?php echo $cacheUrl; ?>', '<?php echo $token; ?>');
|
||||||
setupCleaner('mokosuiteclient-clear-temp', 'mokosuiteclient-temp-icon', '<?php echo $tempUrl; ?>', '<?php echo $token; ?>');
|
setupCleaner('mokosuiteclient-clear-temp', 'mokosuiteclient-temp-icon', '<?php echo $tempUrl; ?>', '<?php echo $token; ?>');
|
||||||
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<?php echo \Moko\Component\MokoSuiteClient\Administrator\Helper\SupportPinHelper::renderScript(); ?>
|
<?php echo \Moko\Component\MokoSuiteClient\Administrator\Helper\SupportPinHelper::renderScript(); ?>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<license>GPL-3.0-or-later</license>
|
<license>GPL-3.0-or-later</license>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||||
<version>02.48.16</version>
|
<version>02.48.50</version>
|
||||||
<description>MOD_MOKOSUITECLIENT_CATEGORIES_DESC</description>
|
<description>MOD_MOKOSUITECLIENT_CATEGORIES_DESC</description>
|
||||||
<namespace path="src">Moko\Module\MokoSuiteClientCategories</namespace>
|
<namespace path="src">Moko\Module\MokoSuiteClientCategories</namespace>
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<license>GPL-3.0-or-later</license>
|
<license>GPL-3.0-or-later</license>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||||
<version>02.48.16</version>
|
<version>02.48.50</version>
|
||||||
<description>MOD_MOKOSUITECLIENT_CPANEL_DESC</description>
|
<description>MOD_MOKOSUITECLIENT_CPANEL_DESC</description>
|
||||||
<namespace path="src">Moko\Module\MokoSuiteClientCpanel</namespace>
|
<namespace path="src">Moko\Module\MokoSuiteClientCpanel</namespace>
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* @package MokoSuiteClient
|
* MokoSuiteClient Cpanel — slim bar with dropdown detail panel
|
||||||
* @subpackage mod_mokosuiteclient_cpanel
|
|
||||||
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
|
||||||
* @license GNU General Public License version 3 or later; see LICENSE
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
defined('_JEXEC') or die;
|
defined('_JEXEC') or die;
|
||||||
@@ -13,35 +10,21 @@ use Joomla\CMS\Language\Text;
|
|||||||
use Joomla\CMS\Router\Route;
|
use Joomla\CMS\Router\Route;
|
||||||
use Joomla\CMS\Session\Session;
|
use Joomla\CMS\Session\Session;
|
||||||
|
|
||||||
// Hidden when on MokoSuiteClient dashboard (redundant info)
|
|
||||||
if (!empty($hidden)) return;
|
if (!empty($hidden)) return;
|
||||||
|
|
||||||
|
|
||||||
$siteInfo = $siteInfo ?? (object) [];
|
$siteInfo = $siteInfo ?? (object) [];
|
||||||
$plugins = $plugins ?? [];
|
$plugins = $plugins ?? [];
|
||||||
$healthOk = $healthOk ?? true;
|
$healthOk = $healthOk ?? true;
|
||||||
$counts = $counts ?? (object) ['articles' => 0, 'users' => 0, 'extensions' => 0, 'updates' => 0];
|
$counts = $counts ?? (object) ['articles' => 0, 'users' => 0, 'extensions' => 0, 'updates' => 0];
|
||||||
$disk = $disk ?? (object) ['free_mb' => null, 'total_mb' => null];
|
$disk = $disk ?? (object) ['free_mb' => null, 'total_mb' => null];
|
||||||
$currentIp = $currentIp ?? '';
|
$currentIp = $currentIp ?? '';
|
||||||
$collapsed = true;
|
$token = Session::getFormToken();
|
||||||
$showHealth = $params->get('show_health', 1);
|
$showPlugins = $params->get('show_plugins', 1);
|
||||||
$showStats = $params->get('show_stats', 1);
|
|
||||||
$showDisk = $params->get('show_disk', 1);
|
|
||||||
$showIp = $params->get('show_ip', 1);
|
|
||||||
$showPlugins = $params->get('show_plugins', 1);
|
|
||||||
$showActions = $params->get('show_actions', 1);
|
|
||||||
$showVersions = $params->get('show_versions', 1);
|
|
||||||
$token = Session::getFormToken();
|
|
||||||
|
|
||||||
$enabledCount = 0;
|
$enabledCount = 0;
|
||||||
$totalCount = count($plugins);
|
$totalCount = count($plugins);
|
||||||
|
foreach ($plugins as $p) {
|
||||||
foreach ($plugins as $p)
|
if ($p->enabled) $enabledCount++;
|
||||||
{
|
|
||||||
if ($p->enabled)
|
|
||||||
{
|
|
||||||
$enabledCount++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$labels = [
|
$labels = [
|
||||||
@@ -52,41 +35,106 @@ $labels = [
|
|||||||
'mokosuiteclient_offline' => 'Offline Bypass',
|
'mokosuiteclient_offline' => 'Offline Bypass',
|
||||||
'mokosuiteclient_dbip' => 'GeoIP Lookup',
|
'mokosuiteclient_dbip' => 'GeoIP Lookup',
|
||||||
'mokosuiteclient_license' => 'License Manager',
|
'mokosuiteclient_license' => 'License Manager',
|
||||||
|
'mokosuiteclient_backup' => 'Backup Bridge',
|
||||||
];
|
];
|
||||||
|
|
||||||
$diskPct = ($disk->total_mb && $disk->total_mb > 0)
|
$diskPct = ($disk->total_mb && $disk->total_mb > 0)
|
||||||
? round((($disk->total_mb - ($disk->free_mb ?? 0)) / $disk->total_mb) * 100)
|
? round((($disk->total_mb - ($disk->free_mb ?? 0)) / $disk->total_mb) * 100) : null;
|
||||||
: null;
|
$diskColor = ($diskPct !== null && $diskPct > 90) ? 'danger' : (($diskPct !== null && $diskPct > 75) ? 'warning' : 'success');
|
||||||
$diskColor = ($diskPct !== null && $diskPct > 90) ? 'bg-danger' : (($diskPct !== null && $diskPct > 75) ? 'bg-warning' : 'bg-success');
|
|
||||||
|
$canDashboard = Factory::getApplication()->getIdentity()->authorise('core.manage', 'com_mokosuiteclient');
|
||||||
|
$siteName = htmlspecialchars($siteInfo->sitename ?? '', ENT_QUOTES, 'UTF-8');
|
||||||
|
$mokoVer = htmlspecialchars($siteInfo->mokosuiteclient_version ?? '', ENT_QUOTES, 'UTF-8');
|
||||||
|
$joomlaVer = htmlspecialchars($siteInfo->joomla_version ?? '', ENT_QUOTES, 'UTF-8');
|
||||||
|
$phpVer = htmlspecialchars($siteInfo->php_version ?? '', ENT_QUOTES, 'UTF-8');
|
||||||
|
$dbType = htmlspecialchars($siteInfo->db_type ?? '', ENT_QUOTES, 'UTF-8');
|
||||||
|
$ipEscaped = htmlspecialchars($currentIp, ENT_QUOTES, 'UTF-8');
|
||||||
|
|
||||||
|
$statusDots = [];
|
||||||
|
if (!empty($siteInfo->debug)) $statusDots[] = '<span class="badge bg-warning text-dark" style="font-size:0.7rem">Debug</span>';
|
||||||
|
if (!empty($siteInfo->offline)) $statusDots[] = '<span class="badge bg-danger" style="font-size:0.7rem">Offline</span>';
|
||||||
|
if (($counts->updates ?? 0) > 0) $statusDots[] = '<span class="badge bg-info" style="font-size:0.7rem">' . (int)$counts->updates . ' updates</span>';
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="mod-mokosuiteclient-cpanel card p-3 mb-4">
|
<div class="mod-mokosuiteclient-cpanel mb-2" style="font-size:0.82rem;">
|
||||||
<div class="d-flex flex-wrap align-items-center gap-2" style="font-size:0.85rem;">
|
<div class="d-flex align-items-center gap-2 px-3 py-1 rounded" style="background:linear-gradient(135deg,#f8f9fa 0%,#e9ecef 100%);border:1px solid #dee2e6;">
|
||||||
<?php $canDashboard = Factory::getApplication()->getIdentity()->authorise('core.manage', 'com_mokosuiteclient'); ?>
|
|
||||||
<?php if ($canDashboard): ?>
|
<?php if ($canDashboard): ?>
|
||||||
<a href="<?php echo Route::_('index.php?option=com_mokosuiteclient'); ?>" style="color:#1a2744;text-decoration:none;" title="MokoSuite Dashboard"><span class="icon-shield-alt" aria-hidden="true" style="font-size:1.1rem"></span></a>
|
<a href="<?php echo Route::_('index.php?option=com_mokosuiteclient'); ?>" style="color:#1a2744;text-decoration:none;" title="MokoSuite Dashboard">
|
||||||
|
<span class="icon-shield-alt" aria-hidden="true" style="font-size:1rem"></span>
|
||||||
|
</a>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<span class="icon-shield-alt" aria-hidden="true" style="font-size:1.1rem;color:#1a2744"></span>
|
<span class="icon-shield-alt" aria-hidden="true" style="font-size:1rem;color:#1a2744"></span>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<span class="fw-bold"><?php echo htmlspecialchars($siteInfo->sitename ?? ''); ?></span>
|
|
||||||
<span class="badge bg-primary">MokoSuite <?php echo htmlspecialchars($siteInfo->mokosuiteclient_version ?? ''); ?></span>
|
<span class="fw-semibold"><?php echo $siteName; ?></span>
|
||||||
|
<span class="text-muted" style="font-size:0.75rem">v<?php echo $mokoVer; ?></span>
|
||||||
|
|
||||||
|
<?php echo implode(' ', $statusDots); ?>
|
||||||
|
|
||||||
<?php echo \Moko\Component\MokoSuiteClient\Administrator\Helper\SupportPinHelper::renderBadge(
|
<?php echo \Moko\Component\MokoSuiteClient\Administrator\Helper\SupportPinHelper::renderBadge(
|
||||||
['available' => !empty($supportPinAvailable), 'pin' => $supportPin ?? ''],
|
['available' => !empty($supportPinAvailable), 'pin' => $supportPin ?? ''],
|
||||||
$token, 'cpanel'
|
$token, 'cpanel'
|
||||||
); ?>
|
); ?>
|
||||||
<span class="badge bg-secondary">Joomla <?php echo htmlspecialchars($siteInfo->joomla_version ?? ''); ?></span>
|
|
||||||
<span class="badge bg-secondary">PHP <?php echo htmlspecialchars($siteInfo->php_version ?? ''); ?></span>
|
|
||||||
<span class="badge bg-secondary"><?php echo htmlspecialchars($siteInfo->db_type ?? ''); ?></span>
|
|
||||||
<?php if (!empty($siteInfo->debug)): ?>
|
|
||||||
<span class="badge bg-warning text-dark">Debug ON</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if (!empty($siteInfo->offline)): ?>
|
|
||||||
<span class="badge bg-danger">Offline</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
<span class="ms-auto d-flex align-items-center gap-2">
|
<span class="ms-auto d-flex align-items-center gap-2">
|
||||||
<span class="icon-globe" aria-hidden="true"></span>
|
<span class="text-muted" style="font-size:0.75rem">
|
||||||
<code><?php echo htmlspecialchars($currentIp); ?></code>
|
<span class="icon-globe" aria-hidden="true"></span> <code style="font-size:0.75rem"><?php echo $ipEscaped; ?></code>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<button class="btn btn-sm btn-link text-muted p-0 ms-1" type="button" data-bs-toggle="collapse" data-bs-target="#mokosuite-cpanel-detail" aria-expanded="false" aria-controls="mokosuite-cpanel-detail" title="Show details" style="font-size:0.85rem;text-decoration:none;">
|
||||||
|
<span class="icon-chevron-down mokosuite-cpanel-chevron" aria-hidden="true" style="transition:transform 0.2s"></span>
|
||||||
|
</button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="collapse" id="mokosuite-cpanel-detail">
|
||||||
|
<div class="card card-body mt-1 p-3" style="font-size:0.82rem;border-color:#dee2e6;">
|
||||||
|
<div class="row g-3">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<h6 class="text-muted mb-2" style="font-size:0.75rem;text-transform:uppercase;letter-spacing:0.05em">Environment</h6>
|
||||||
|
<div class="d-flex flex-wrap gap-1">
|
||||||
|
<span class="badge bg-primary">MokoSuite <?php echo $mokoVer; ?></span>
|
||||||
|
<span class="badge bg-secondary">Joomla <?php echo $joomlaVer; ?></span>
|
||||||
|
<span class="badge bg-secondary">PHP <?php echo $phpVer; ?></span>
|
||||||
|
<span class="badge bg-secondary"><?php echo $dbType; ?></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<h6 class="text-muted mb-2" style="font-size:0.75rem;text-transform:uppercase;letter-spacing:0.05em">Stats</h6>
|
||||||
|
<div class="d-flex flex-wrap gap-2" style="font-size:0.8rem">
|
||||||
|
<span><span class="icon-file-alt" aria-hidden="true"></span> <?php echo (int)($counts->articles ?? 0); ?> articles</span>
|
||||||
|
<span><span class="icon-users" aria-hidden="true"></span> <?php echo (int)($counts->users ?? 0); ?> users</span>
|
||||||
|
<span><span class="icon-puzzle-piece" aria-hidden="true"></span> <?php echo (int)($counts->extensions ?? 0); ?> extensions</span>
|
||||||
|
</div>
|
||||||
|
<?php if ($diskPct !== null): ?>
|
||||||
|
<div class="mt-1">
|
||||||
|
<div class="progress" style="height:4px">
|
||||||
|
<div class="progress-bar bg-<?php echo $diskColor; ?>" style="width:<?php echo $diskPct; ?>%"></div>
|
||||||
|
</div>
|
||||||
|
<small class="text-muted">Disk <?php echo $diskPct; ?>% (<?php echo number_format(($disk->free_mb ?? 0) / 1024, 1); ?> GB free)</small>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<?php if ($showPlugins && $totalCount > 0): ?>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<h6 class="text-muted mb-2" style="font-size:0.75rem;text-transform:uppercase;letter-spacing:0.05em">Plugins (<?php echo $enabledCount; ?>/<?php echo $totalCount; ?>)</h6>
|
||||||
|
<div class="d-flex flex-wrap gap-1">
|
||||||
|
<?php foreach ($plugins as $p):
|
||||||
|
$el = str_replace('plg_system_', '', $p->element);
|
||||||
|
$label = $labels[$el] ?? ucfirst(str_replace('mokosuiteclient_', '', $el));
|
||||||
|
$color = $p->enabled ? 'success' : 'secondary';
|
||||||
|
?>
|
||||||
|
<span class="badge bg-<?php echo $color; ?>" style="font-size:0.7rem"><?php echo htmlspecialchars($label); ?></span>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
[aria-expanded="true"] .mokosuite-cpanel-chevron { transform: rotate(180deg); }
|
||||||
|
</style>
|
||||||
<?php echo \Moko\Component\MokoSuiteClient\Administrator\Helper\SupportPinHelper::renderScript(); ?>
|
<?php echo \Moko\Component\MokoSuiteClient\Administrator\Helper\SupportPinHelper::renderScript(); ?>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<license>GPL-3.0-or-later</license>
|
<license>GPL-3.0-or-later</license>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||||
<version>02.48.16</version>
|
<version>02.48.50</version>
|
||||||
<description>MokoSuiteClient admin sidebar menu — renders a dedicated MokoSuiteClient section in the admin menu before Joomla's default menu.</description>
|
<description>MokoSuiteClient admin sidebar menu — renders a dedicated MokoSuiteClient section in the admin menu before Joomla's default menu.</description>
|
||||||
<namespace path="src">Moko\Module\MokoSuiteClientMenu</namespace>
|
<namespace path="src">Moko\Module\MokoSuiteClientMenu</namespace>
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,8 @@
|
|||||||
/**
|
/**
|
||||||
* MokoSuiteClient Admin Sidebar Menu
|
* MokoSuiteClient Admin Sidebar Menu
|
||||||
*
|
*
|
||||||
* Each installed Moko component gets its own top-level collapsible section.
|
* Single "MokoSuite" top-level item with all Moko ecosystem components
|
||||||
* com_mokosuitehq is always pinned first. com_mokosuiteclient uses static views
|
* as collapsible children underneath.
|
||||||
* as children. All other components auto-discover their submenu items.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
defined('_JEXEC') or die;
|
defined('_JEXEC') or die;
|
||||||
@@ -38,6 +37,72 @@ $mokosuiteclientStaticViews = array_filter($allViews, function ($v) use ($user,
|
|||||||
return $isSuper || $user->authorise($v['acl'], 'com_mokosuiteclient');
|
return $isSuper || $user->authorise($v['acl'], 'com_mokosuiteclient');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ── Icon overrides (canonical icons per component) ───────────────────
|
||||||
|
$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_mokosuiteshop' => 'icon-shopping-cart',
|
||||||
|
'com_mokosuitepos' => 'icon-calculator',
|
||||||
|
'com_mokosuitemrp' => 'icon-cogs',
|
||||||
|
'com_mokosuitehrm' => 'icon-id-badge',
|
||||||
|
'com_mokosuiterestaurant' => 'icon-utensils',
|
||||||
|
'com_mokosuitechild' => 'icon-child',
|
||||||
|
'com_mokosuitenpo' => 'icon-heart',
|
||||||
|
'com_mokosuitefield' => 'icon-wrench',
|
||||||
|
'com_mokosuitecreate' => 'icon-paint-brush',
|
||||||
|
'com_mokosuiteforms' => 'icon-list-alt',
|
||||||
|
'com_mokosuitecommunity' => 'icon-comments',
|
||||||
|
'com_mokosuitecross' => 'icon-share-alt',
|
||||||
|
'com_mokosuiteopengraph' => 'icon-globe',
|
||||||
|
'com_mokosuitestorelocator' => 'icon-map-marker-alt',
|
||||||
|
];
|
||||||
|
|
||||||
|
$childIconMap = [
|
||||||
|
'dashboard' => 'icon-tachometer-alt',
|
||||||
|
'contacts' => 'icon-address-book',
|
||||||
|
'deals' => 'icon-handshake',
|
||||||
|
'activities' => 'icon-clock',
|
||||||
|
'tickets' => 'icon-life-ring',
|
||||||
|
'helpdesk' => 'icon-life-ring',
|
||||||
|
'products' => 'icon-box',
|
||||||
|
'orders' => 'icon-shopping-cart',
|
||||||
|
'invoices' => 'icon-file-invoice',
|
||||||
|
'inventory' => 'icon-warehouse',
|
||||||
|
'settings' => 'icon-cog',
|
||||||
|
'config' => 'icon-cog',
|
||||||
|
'options' => 'icon-sliders-h',
|
||||||
|
'reports' => 'icon-chart-bar',
|
||||||
|
'analytics' => 'icon-chart-line',
|
||||||
|
'locations' => 'icon-map-marker-alt',
|
||||||
|
'stores' => 'icon-store',
|
||||||
|
'categories' => 'icon-folder',
|
||||||
|
'forms' => 'icon-list-alt',
|
||||||
|
'submissions' => 'icon-inbox',
|
||||||
|
'emails' => 'icon-envelope',
|
||||||
|
'campaigns' => 'icon-bullhorn',
|
||||||
|
'users' => 'icon-users',
|
||||||
|
'members' => 'icon-id-card',
|
||||||
|
'employees' => 'icon-id-badge',
|
||||||
|
'donors' => 'icon-hand-holding-heart',
|
||||||
|
'donations' => 'icon-donate',
|
||||||
|
'events' => 'icon-calendar',
|
||||||
|
'tasks' => 'icon-tasks',
|
||||||
|
'projects' => 'icon-project-diagram',
|
||||||
|
'templates' => 'icon-file-alt',
|
||||||
|
'announcements'=> 'icon-bullhorn',
|
||||||
|
'plugins' => 'icon-plug',
|
||||||
|
'import' => 'icon-upload',
|
||||||
|
'export' => 'icon-download',
|
||||||
|
'log' => 'icon-list',
|
||||||
|
'backup' => 'icon-archive',
|
||||||
|
'channels' => 'icon-share-alt',
|
||||||
|
'posts' => 'icon-paper-plane',
|
||||||
|
'schedule' => 'icon-calendar-alt',
|
||||||
|
];
|
||||||
|
|
||||||
// ── Auto-discover all Moko components from #__menu ──────────────────
|
// ── Auto-discover all Moko components from #__menu ──────────────────
|
||||||
$mokoComponents = [];
|
$mokoComponents = [];
|
||||||
|
|
||||||
@@ -56,7 +121,6 @@ try
|
|||||||
);
|
);
|
||||||
$menuItems = $db->loadObjectList() ?: [];
|
$menuItems = $db->loadObjectList() ?: [];
|
||||||
|
|
||||||
// Load language files for discovered components
|
|
||||||
$lang = Factory::getLanguage();
|
$lang = Factory::getLanguage();
|
||||||
$loadedLangs = [];
|
$loadedLangs = [];
|
||||||
foreach ($menuItems as $m)
|
foreach ($menuItems as $m)
|
||||||
@@ -65,47 +129,50 @@ try
|
|||||||
{
|
{
|
||||||
$lang->load($m->element . '.sys', JPATH_ADMINISTRATOR);
|
$lang->load($m->element . '.sys', JPATH_ADMINISTRATOR);
|
||||||
$lang->load($m->element, JPATH_ADMINISTRATOR);
|
$lang->load($m->element, JPATH_ADMINISTRATOR);
|
||||||
|
|
||||||
// Also try component-local language path (Joomla 5/6 pattern)
|
|
||||||
$compLangPath = JPATH_ADMINISTRATOR . '/components/' . $m->element;
|
$compLangPath = JPATH_ADMINISTRATOR . '/components/' . $m->element;
|
||||||
if (is_dir($compLangPath . '/language'))
|
if (is_dir($compLangPath . '/language'))
|
||||||
{
|
{
|
||||||
$lang->load($m->element . '.sys', $compLangPath);
|
$lang->load($m->element . '.sys', $compLangPath);
|
||||||
$lang->load($m->element, $compLangPath);
|
$lang->load($m->element, $compLangPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
$loadedLangs[$m->element] = true;
|
$loadedLangs[$m->element] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Group: level 1 = component parent, level 2 = children
|
|
||||||
foreach ($menuItems as $m)
|
foreach ($menuItems as $m)
|
||||||
{
|
{
|
||||||
if ((int) $m->level === 1)
|
if ((int) $m->level === 1)
|
||||||
{
|
{
|
||||||
|
$icon = $iconOverrides[$m->element]
|
||||||
|
?? str_replace('class:', 'icon-', $m->img ?: 'class:puzzle-piece');
|
||||||
$mokoComponents[$m->element] = [
|
$mokoComponents[$m->element] = [
|
||||||
'id' => $m->id,
|
'id' => $m->id,
|
||||||
'title' => Text::_($m->title),
|
'title' => Text::_($m->title),
|
||||||
'link' => $m->link,
|
'link' => $m->link,
|
||||||
'icon' => str_replace('class:', 'icon-', $m->img ?: 'class:puzzle-piece'),
|
'icon' => $icon,
|
||||||
'element' => $m->element,
|
'element' => $m->element,
|
||||||
'children' => [],
|
'children' => [],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
elseif ((int) $m->level === 2 && isset($mokoComponents[$m->element]))
|
elseif ((int) $m->level === 2 && isset($mokoComponents[$m->element]))
|
||||||
{
|
{
|
||||||
|
$childIcon = str_replace('class:', 'icon-', $m->img ?: '');
|
||||||
|
if ($childIcon === '' || $childIcon === 'icon-cog' || $childIcon === 'icon-cogs')
|
||||||
|
{
|
||||||
|
$parsed = [];
|
||||||
|
parse_str(parse_url($m->link, PHP_URL_QUERY) ?? '', $parsed);
|
||||||
|
$viewKey = strtolower($parsed['view'] ?? '');
|
||||||
|
$childIcon = $childIconMap[$viewKey] ?? '';
|
||||||
|
}
|
||||||
$mokoComponents[$m->element]['children'][] = [
|
$mokoComponents[$m->element]['children'][] = [
|
||||||
'title' => Text::_($m->title),
|
'title' => Text::_($m->title),
|
||||||
'link' => $m->link,
|
'link' => $m->link,
|
||||||
'icon' => str_replace('class:', 'icon-', $m->img ?: 'class:cog'),
|
'icon' => $childIcon ?: 'icon-angle-right',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (\Throwable $e)
|
catch (\Throwable $e) {}
|
||||||
{
|
|
||||||
// Silent — menu works without auto-discovered components
|
|
||||||
}
|
|
||||||
|
|
||||||
// Override com_mokosuiteclient children with static views
|
// Override com_mokosuiteclient children with static views
|
||||||
if (isset($mokoComponents['com_mokosuiteclient']))
|
if (isset($mokoComponents['com_mokosuiteclient']))
|
||||||
@@ -115,7 +182,6 @@ if (isset($mokoComponents['com_mokosuiteclient']))
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// com_mokosuiteclient not in admin menu — add it manually
|
|
||||||
$mokoComponents['com_mokosuiteclient'] = [
|
$mokoComponents['com_mokosuiteclient'] = [
|
||||||
'id' => 0,
|
'id' => 0,
|
||||||
'title' => 'MokoSuite',
|
'title' => 'MokoSuite',
|
||||||
@@ -133,9 +199,6 @@ $rest = [];
|
|||||||
|
|
||||||
foreach ($mokoComponents as $key => $comp)
|
foreach ($mokoComponents as $key => $comp)
|
||||||
{
|
{
|
||||||
// Shorten display titles:
|
|
||||||
// MokoSuiteClient → MokoSuite, MokoSuiteHQ → MokoHQ
|
|
||||||
// Everything else: MokoSuiteBackup → Backup, MokoSuiteOpenGraph → OpenGraph
|
|
||||||
if ($key === 'com_mokosuiteclient')
|
if ($key === 'com_mokosuiteclient')
|
||||||
{
|
{
|
||||||
$comp['title'] = 'MokoSuite';
|
$comp['title'] = 'MokoSuite';
|
||||||
@@ -149,35 +212,29 @@ foreach ($mokoComponents as $key => $comp)
|
|||||||
$comp['title'] = preg_replace('/^MokoSuite\s*/i', '', $comp['title']);
|
$comp['title'] = preg_replace('/^MokoSuite\s*/i', '', $comp['title']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($key === 'com_mokosuitehq')
|
if ($key === 'com_mokosuitehq') { $hq = $comp; }
|
||||||
{
|
elseif ($key === 'com_mokosuiteclient') { $client = $comp; }
|
||||||
$hq = $comp;
|
else { $rest[$key] = $comp; }
|
||||||
}
|
|
||||||
elseif ($key === 'com_mokosuiteclient')
|
|
||||||
{
|
|
||||||
$client = $comp;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$rest[$key] = $comp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
usort($rest, fn($a, $b) => strcasecmp($a['title'], $b['title']));
|
usort($rest, fn($a, $b) => strcasecmp($a['title'], $b['title']));
|
||||||
|
|
||||||
$sorted = [];
|
$sorted = [];
|
||||||
if ($hq !== null)
|
if ($hq !== null) $sorted[] = $hq;
|
||||||
|
if ($client !== null) $sorted[] = $client;
|
||||||
|
foreach ($rest as $comp) $sorted[] = $comp;
|
||||||
|
|
||||||
|
// Is ANY Moko component active?
|
||||||
|
$anyActive = false;
|
||||||
|
foreach ($sorted as $comp)
|
||||||
{
|
{
|
||||||
$sorted[] = $hq;
|
$p = [];
|
||||||
}
|
parse_str(parse_url($comp['link'], PHP_URL_QUERY) ?? '', $p);
|
||||||
if ($client !== null)
|
if (($p['option'] ?? '') === $currentOption) { $anyActive = true; break; }
|
||||||
{
|
|
||||||
$sorted[] = $client;
|
|
||||||
}
|
|
||||||
foreach ($rest as $comp)
|
|
||||||
{
|
|
||||||
$sorted[] = $comp;
|
|
||||||
}
|
}
|
||||||
|
if ($currentOption === 'com_plugins') $anyActive = true;
|
||||||
|
|
||||||
|
$iconStyle = 'display:inline-block!important;width:1.25em;text-align:center;margin-inline-end:0.4em;';
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -185,58 +242,64 @@ foreach ($rest as $comp)
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<ul class="nav flex-column main-nav">
|
<ul class="nav flex-column main-nav">
|
||||||
<?php foreach ($sorted as $comp): ?>
|
<li class="item parent item-level-1 mokosuiteclient-ext-item<?php echo $anyActive ? ' mm-active' : ''; ?>">
|
||||||
<?php
|
<a class="has-arrow<?php echo $anyActive ? ' mm-active' : ''; ?>" href="#">
|
||||||
$compParsed = [];
|
<span class="icon-shield-alt" aria-hidden="true" style="<?php echo $iconStyle; ?>"></span>
|
||||||
parse_str(parse_url($comp['link'], PHP_URL_QUERY) ?? '', $compParsed);
|
<span class="sidebar-item-title">MokoSuite</span>
|
||||||
$compOption = $compParsed['option'] ?? '';
|
|
||||||
$compActive = ($compOption === $currentOption);
|
|
||||||
|
|
||||||
// For com_mokosuiteclient static children, also check the plugins filter link
|
|
||||||
if (!$compActive && $comp['element'] === 'com_mokosuiteclient' && $currentOption === 'com_plugins')
|
|
||||||
{
|
|
||||||
$compActive = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$hasChildren = !empty($comp['children']);
|
|
||||||
$liClass = 'item mokosuiteclient-ext-item' . ($hasChildren ? ' parent item-level-1' : '') . ($compActive ? ' mm-active' : '');
|
|
||||||
$aClass = ($hasChildren ? 'has-arrow' : 'no-dropdown') . ($compActive ? ' mm-active' : '');
|
|
||||||
$childCollapse = 'collapse-level-1 mm-collapse' . ($compActive ? ' mm-show' : '');
|
|
||||||
?>
|
|
||||||
<li class="<?php echo $liClass; ?>">
|
|
||||||
<a class="<?php echo $aClass; ?>" href="<?php echo $hasChildren ? '#' : Route::_($comp['link']); ?>"<?php echo ($compActive && !$hasChildren) ? ' aria-current="page"' : ''; ?>>
|
|
||||||
<span class="<?php echo $comp['icon']; ?>" aria-hidden="true" style="display:inline-block!important;width:1.25em;text-align:center;margin-inline-end:0.4em;"></span>
|
|
||||||
<span class="sidebar-item-title"><?php echo $comp['title']; ?></span>
|
|
||||||
</a>
|
</a>
|
||||||
<?php if ($hasChildren): ?>
|
<ul class="collapse-level-1 mm-collapse<?php echo $anyActive ? ' mm-show' : ''; ?>" style="padding-inline-start:0.5rem;">
|
||||||
<ul class="<?php echo $childCollapse; ?>" style="padding-inline-start:0.5rem;">
|
<?php foreach ($sorted as $comp): ?>
|
||||||
<?php foreach ($comp['children'] as $child): ?>
|
|
||||||
<?php
|
<?php
|
||||||
$childParsed = [];
|
$compParsed = [];
|
||||||
parse_str(parse_url($child['link'], PHP_URL_QUERY) ?? '', $childParsed);
|
parse_str(parse_url($comp['link'], PHP_URL_QUERY) ?? '', $compParsed);
|
||||||
$childOption = $childParsed['option'] ?? '';
|
$compOption = $compParsed['option'] ?? '';
|
||||||
$childView = $childParsed['view'] ?? '';
|
$compActive = ($compOption === $currentOption);
|
||||||
|
if (!$compActive && $comp['element'] === 'com_mokosuiteclient' && $currentOption === 'com_plugins')
|
||||||
$childActive = false;
|
|
||||||
if ($childOption === $currentOption)
|
|
||||||
{
|
{
|
||||||
$childActive = empty($childView)
|
$compActive = true;
|
||||||
? ($currentView === '' || $currentView === 'dashboard')
|
|
||||||
: ($currentView === $childView);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$childLiClass = 'item mokosuiteclient-ext-child' . ($childActive ? ' mm-active' : '');
|
$hasChildren = !empty($comp['children']);
|
||||||
$childAClass = 'no-dropdown' . ($childActive ? ' mm-active' : '');
|
|
||||||
?>
|
?>
|
||||||
<li class="<?php echo $childLiClass; ?>">
|
<?php if ($hasChildren): ?>
|
||||||
<a class="<?php echo $childAClass; ?>" href="<?php echo Route::_($child['link']); ?>"<?php echo $childActive ? ' aria-current="page"' : ''; ?>>
|
<li class="item parent item-level-2 mokosuiteclient-ext-item<?php echo $compActive ? ' mm-active' : ''; ?>">
|
||||||
<span class="<?php echo $child['icon']; ?>" aria-hidden="true" style="display:inline-block!important;width:1.25em;text-align:center;margin-inline-end:0.4em;"></span>
|
<a class="has-arrow<?php echo $compActive ? ' mm-active' : ''; ?>" href="#">
|
||||||
<span class="sidebar-item-title"><?php echo $child['title']; ?></span>
|
<span class="<?php echo $comp['icon']; ?>" aria-hidden="true" style="<?php echo $iconStyle; ?>"></span>
|
||||||
|
<span class="sidebar-item-title"><?php echo $comp['title']; ?></span>
|
||||||
|
</a>
|
||||||
|
<ul class="collapse-level-2 mm-collapse<?php echo $compActive ? ' mm-show' : ''; ?>" style="padding-inline-start:0.5rem;">
|
||||||
|
<?php foreach ($comp['children'] as $child): ?>
|
||||||
|
<?php
|
||||||
|
$childParsed = [];
|
||||||
|
parse_str(parse_url($child['link'], PHP_URL_QUERY) ?? '', $childParsed);
|
||||||
|
$childOption = $childParsed['option'] ?? '';
|
||||||
|
$childView = $childParsed['view'] ?? '';
|
||||||
|
$childActive = false;
|
||||||
|
if ($childOption === $currentOption)
|
||||||
|
{
|
||||||
|
$childActive = empty($childView)
|
||||||
|
? ($currentView === '' || $currentView === 'dashboard')
|
||||||
|
: ($currentView === $childView);
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<li class="item mokosuiteclient-ext-child<?php echo $childActive ? ' mm-active' : ''; ?>">
|
||||||
|
<a class="no-dropdown<?php echo $childActive ? ' mm-active' : ''; ?>" href="<?php echo Route::_($child['link']); ?>"<?php echo $childActive ? ' aria-current="page"' : ''; ?>>
|
||||||
|
<span class="<?php echo $child['icon']; ?>" aria-hidden="true" style="<?php echo $iconStyle; ?>"></span>
|
||||||
|
<span class="sidebar-item-title"><?php echo $child['title']; ?></span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<?php else: ?>
|
||||||
|
<li class="item mokosuiteclient-ext-item<?php echo $compActive ? ' mm-active' : ''; ?>">
|
||||||
|
<a class="no-dropdown<?php echo $compActive ? ' mm-active' : ''; ?>" href="<?php echo Route::_($comp['link']); ?>"<?php echo $compActive ? ' aria-current="page"' : ''; ?>>
|
||||||
|
<span class="<?php echo $comp['icon']; ?>" aria-hidden="true" style="<?php echo $iconStyle; ?>"></span>
|
||||||
|
<span class="sidebar-item-title"><?php echo $comp['title']; ?></span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<?php endif; ?>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</ul>
|
</ul>
|
||||||
<?php endif; ?>
|
|
||||||
</li>
|
</li>
|
||||||
<?php endforeach; ?>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
* DEFGROUP: Joomla.Plugin
|
* DEFGROUP: Joomla.Plugin
|
||||||
* INGROUP: MokoSuiteClient
|
* INGROUP: MokoSuiteClient
|
||||||
* REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
* REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
||||||
* VERSION: 02.48.16
|
* VERSION: 02.48.50
|
||||||
* PATH: /src/Extension/MokoSuiteClient.php
|
* PATH: /src/Extension/MokoSuiteClient.php
|
||||||
* NOTE: Core system plugin for MokoSuiteClient admin tools suite
|
* NOTE: Core system plugin for MokoSuiteClient admin tools suite
|
||||||
*/
|
*/
|
||||||
@@ -384,14 +384,20 @@ class MokoSuiteClient extends CMSPlugin implements BootableExtensionInterface
|
|||||||
document.querySelectorAll('a[href*=\"help.joomla.org\"], a[href*=\"docs.joomla.org\"]').forEach(function(link) {
|
document.querySelectorAll('a[href*=\"help.joomla.org\"], a[href*=\"docs.joomla.org\"]').forEach(function(link) {
|
||||||
link.href = url;
|
link.href = url;
|
||||||
link.target = '_blank';
|
link.target = '_blank';
|
||||||
|
link.rel = 'noopener noreferrer';
|
||||||
|
var extIcon = link.querySelector('.icon-external-link-alt, .icon-external-link, .fa-external-link-alt, .fa-up-right-from-square');
|
||||||
|
if (extIcon) extIcon.remove();
|
||||||
});
|
});
|
||||||
document.querySelectorAll('a[href*=\"dashboard=help\"]').forEach(function(link) {
|
document.querySelectorAll('a[href*=\"dashboard=help\"]').forEach(function(link) {
|
||||||
link.href = url;
|
link.href = url;
|
||||||
link.target = '_blank';
|
link.target = '_blank';
|
||||||
link.rel = 'noopener noreferrer';
|
link.rel = 'noopener noreferrer';
|
||||||
|
var extIcon = link.querySelector('.icon-external-link-alt, .icon-external-link, .fa-external-link-alt, .fa-up-right-from-square');
|
||||||
|
if (extIcon) extIcon.remove();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
");
|
");
|
||||||
|
$doc->addStyleDeclaration('a[href=\"' . $supportUrl . '\"] .icon-external-link-alt, a[href=\"' . $supportUrl . '\"] .fa-up-right-from-square { display: none !important; }');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
* FILE INFORMATION
|
* FILE INFORMATION
|
||||||
* DEFGROUP: Joomla.Plugin
|
* DEFGROUP: Joomla.Plugin
|
||||||
* INGROUP: MokoSuiteClient
|
* INGROUP: MokoSuiteClient
|
||||||
* VERSION: 02.48.16
|
* VERSION: 02.48.50
|
||||||
* PATH: /src/Field/ArticlesField.php
|
* PATH: /src/Field/ArticlesField.php
|
||||||
* BRIEF: List field that populates with published Joomla articles
|
* BRIEF: List field that populates with published Joomla articles
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
* FILE INFORMATION
|
* FILE INFORMATION
|
||||||
* DEFGROUP: Joomla.Plugin
|
* DEFGROUP: Joomla.Plugin
|
||||||
* INGROUP: MokoSuiteClient
|
* INGROUP: MokoSuiteClient
|
||||||
* VERSION: 02.48.16
|
* VERSION: 02.48.50
|
||||||
* PATH: /src/Field/CopyableTokenField.php
|
* PATH: /src/Field/CopyableTokenField.php
|
||||||
* BRIEF: Read-only token field with a copy-to-clipboard button
|
* BRIEF: Read-only token field with a copy-to-clipboard button
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
<license>GNU General Public License version 3 or later; see LICENSE.md</license>
|
<license>GNU General Public License version 3 or later; see LICENSE.md</license>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||||
<version>02.48.16</version>
|
<version>02.48.50</version>
|
||||||
<description>MokoSuiteClient core system plugin — coordinates feature plugins, heartbeat, health checks, and admin customizations.</description>
|
<description>MokoSuiteClient core system plugin — coordinates feature plugins, heartbeat, health checks, and admin customizations.</description>
|
||||||
<namespace path=".">Moko\Plugin\System\MokoSuiteClient</namespace>
|
<namespace path=".">Moko\Plugin\System\MokoSuiteClient</namespace>
|
||||||
<scriptfile>script.php</scriptfile>
|
<scriptfile>script.php</scriptfile>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
* DEFGROUP: Joomla.Plugin
|
* DEFGROUP: Joomla.Plugin
|
||||||
* INGROUP: MokoSuiteClient
|
* INGROUP: MokoSuiteClient
|
||||||
* REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
* REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
||||||
* VERSION: 02.48.16
|
* VERSION: 02.48.50
|
||||||
* PATH: /src/script.php
|
* PATH: /src/script.php
|
||||||
* BRIEF: Installation script for MokoSuiteClient plugin
|
* BRIEF: Installation script for MokoSuiteClient plugin
|
||||||
* NOTE: Handles installation, update, and uninstallation tasks including language override deployment
|
* NOTE: Handles installation, update, and uninstallation tasks including language override deployment
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
* DEFGROUP: Joomla.Plugin
|
* DEFGROUP: Joomla.Plugin
|
||||||
* INGROUP: MokoSuiteClient
|
* INGROUP: MokoSuiteClient
|
||||||
* REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
* REPO: https://github.com/mokoconsulting-tech/mokosuiteclient
|
||||||
* VERSION: 02.48.16
|
* VERSION: 02.48.50
|
||||||
* PATH: /src/services/provider.php
|
* PATH: /src/services/provider.php
|
||||||
* BRIEF: Service provider for dependency injection in Joomla 5.x
|
* BRIEF: Service provider for dependency injection in Joomla 5.x
|
||||||
* NOTE: Registers the plugin with Joomla's DI container
|
* NOTE: Registers the plugin with Joomla's DI container
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<license>GPL-3.0-or-later</license>
|
<license>GPL-3.0-or-later</license>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||||
<version>02.48.16</version>
|
<version>02.48.50</version>
|
||||||
<description>PLG_SYSTEM_MOKOSUITECLIENT_BACKUP_DESC</description>
|
<description>PLG_SYSTEM_MOKOSUITECLIENT_BACKUP_DESC</description>
|
||||||
<namespace path="src">Moko\Plugin\System\MokoSuiteClientBackup</namespace>
|
<namespace path="src">Moko\Plugin\System\MokoSuiteClientBackup</namespace>
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<license>GPL-3.0-or-later</license>
|
<license>GPL-3.0-or-later</license>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||||
<version>02.48.16</version>
|
<version>02.48.50</version>
|
||||||
<description>PLG_SYSTEM_MOKOSUITECLIENT_DBIP_DESC</description>
|
<description>PLG_SYSTEM_MOKOSUITECLIENT_DBIP_DESC</description>
|
||||||
<namespace path="src">Moko\Plugin\System\MokoSuiteClientDBIP</namespace>
|
<namespace path="src">Moko\Plugin\System\MokoSuiteClientDBIP</namespace>
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class DBIP extends CMSPlugin implements SubscriberInterface
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'onAfterInitialise' => 'onAfterInitialise',
|
'onAfterInitialise' => 'onAfterInitialise',
|
||||||
|
'onAfterRender' => 'onAfterRender',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,4 +81,92 @@ class DBIP extends CMSPlugin implements SubscriberInterface
|
|||||||
|
|
||||||
DBIPHelper::downloadCityDb($url);
|
DBIPHelper::downloadCityDb($url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scan rendered admin HTML for IP addresses and enrich with geo flags + tooltips.
|
||||||
|
*/
|
||||||
|
public function onAfterRender(): void
|
||||||
|
{
|
||||||
|
$app = $this->getApplication();
|
||||||
|
|
||||||
|
if (!$app->isClient('administrator'))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($app->getDocument()->getType() !== 'html')
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$body = $app->getBody();
|
||||||
|
|
||||||
|
if (empty($body))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ipv4 = '(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)';
|
||||||
|
$ipv6 = '(?:[0-9a-fA-F]{1,4}:){2,7}[0-9a-fA-F]{1,4}(?::(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))?';
|
||||||
|
$pattern = '#<code(?:\s[^>]*)?>(' . $ipv4 . '|' . $ipv6 . ')</code>#';
|
||||||
|
|
||||||
|
$cache = [];
|
||||||
|
|
||||||
|
$newBody = preg_replace_callback($pattern, function ($m) use (&$cache) {
|
||||||
|
$fullMatch = $m[0];
|
||||||
|
$ip = $m[1];
|
||||||
|
|
||||||
|
// Skip private/loopback
|
||||||
|
if (filter_var($ip, \FILTER_VALIDATE_IP, \FILTER_FLAG_NO_PRIV_RANGE | \FILTER_FLAG_NO_RES_RANGE) === false)
|
||||||
|
{
|
||||||
|
return $fullMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Already enriched (has a title attribute)
|
||||||
|
if (strpos($fullMatch, 'title=') !== false)
|
||||||
|
{
|
||||||
|
return $fullMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($cache[$ip]))
|
||||||
|
{
|
||||||
|
$cache[$ip] = DBIPHelper::lookup($ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
$geo = $cache[$ip];
|
||||||
|
|
||||||
|
if ($geo === null || empty($geo['country_code']))
|
||||||
|
{
|
||||||
|
return $fullMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cc = strtoupper($geo['country_code']);
|
||||||
|
$flag = self::countryFlag($cc);
|
||||||
|
|
||||||
|
$parts = array_filter([$geo['city'], $geo['region'], $geo['country_name']]);
|
||||||
|
$tooltip = htmlspecialchars(implode(', ', $parts), \ENT_QUOTES, 'UTF-8');
|
||||||
|
$escaped = htmlspecialchars($ip, \ENT_QUOTES, 'UTF-8');
|
||||||
|
|
||||||
|
return $flag . ' <code title="' . $tooltip . '" style="cursor:help;">' . $escaped . '</code>';
|
||||||
|
}, $body);
|
||||||
|
|
||||||
|
if ($newBody !== null && $newBody !== $body)
|
||||||
|
{
|
||||||
|
$app->setBody($newBody);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function countryFlag(string $cc): string
|
||||||
|
{
|
||||||
|
if (\strlen($cc) !== 2)
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$cc = strtoupper($cc);
|
||||||
|
$first = mb_chr(0x1F1E6 + \ord($cc[0]) - \ord('A'));
|
||||||
|
$second = mb_chr(0x1F1E6 + \ord($cc[1]) - \ord('A'));
|
||||||
|
|
||||||
|
return $first . $second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<license>GPL-3.0-or-later</license>
|
<license>GPL-3.0-or-later</license>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||||
<version>02.48.16</version>
|
<version>02.48.50</version>
|
||||||
<description>PLG_SYSTEM_MOKOSUITECLIENT_DEVTOOLS_DESC</description>
|
<description>PLG_SYSTEM_MOKOSUITECLIENT_DEVTOOLS_DESC</description>
|
||||||
<namespace path="src">Moko\Plugin\System\MokoSuiteClientDevTools</namespace>
|
<namespace path="src">Moko\Plugin\System\MokoSuiteClientDevTools</namespace>
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<license>GPL-3.0-or-later</license>
|
<license>GPL-3.0-or-later</license>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||||
<version>02.48.16</version>
|
<version>02.48.50</version>
|
||||||
<description>PLG_SYSTEM_MOKOSUITECLIENT_FIREWALL_DESC</description>
|
<description>PLG_SYSTEM_MOKOSUITECLIENT_FIREWALL_DESC</description>
|
||||||
<namespace path="src">Moko\Plugin\System\MokoSuiteClientFirewall</namespace>
|
<namespace path="src">Moko\Plugin\System\MokoSuiteClientFirewall</namespace>
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<license>GPL-3.0-or-later</license>
|
<license>GPL-3.0-or-later</license>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||||
<version>02.48.16</version>
|
<version>02.48.50</version>
|
||||||
<description>PLG_SYSTEM_MOKOSUITECLIENT_LICENSE_DESC</description>
|
<description>PLG_SYSTEM_MOKOSUITECLIENT_LICENSE_DESC</description>
|
||||||
<namespace path="src">Moko\Plugin\System\MokoSuiteClientLicense</namespace>
|
<namespace path="src">Moko\Plugin\System\MokoSuiteClientLicense</namespace>
|
||||||
<files><folder>src</folder><folder>services</folder><folder>language</folder></files>
|
<files><folder>src</folder><folder>services</folder><folder>language</folder></files>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<license>GPL-3.0-or-later</license>
|
<license>GPL-3.0-or-later</license>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||||
<version>02.48.16</version>
|
<version>02.48.50</version>
|
||||||
<description>PLG_SYSTEM_MOKOSUITECLIENT_OFFLINE_DESC</description>
|
<description>PLG_SYSTEM_MOKOSUITECLIENT_OFFLINE_DESC</description>
|
||||||
<namespace path="src">Moko\Plugin\System\MokoSuiteClientOffline</namespace>
|
<namespace path="src">Moko\Plugin\System\MokoSuiteClientOffline</namespace>
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<license>GPL-3.0-or-later</license>
|
<license>GPL-3.0-or-later</license>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||||
<version>02.48.16</version>
|
<version>02.48.50</version>
|
||||||
<description>PLG_SYSTEM_MOKOSUITECLIENT_TENANT_DESC</description>
|
<description>PLG_SYSTEM_MOKOSUITECLIENT_TENANT_DESC</description>
|
||||||
<namespace path="src">Moko\Plugin\System\MokoSuiteClientTenant</namespace>
|
<namespace path="src">Moko\Plugin\System\MokoSuiteClientTenant</namespace>
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<license>GNU General Public License version 3 or later; see LICENSE</license>
|
<license>GNU General Public License version 3 or later; see LICENSE</license>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||||
<version>02.48.16</version>
|
<version>02.48.50</version>
|
||||||
<description>PLG_TASK_MOKOSUITECLIENTDEMO_DESC</description>
|
<description>PLG_TASK_MOKOSUITECLIENTDEMO_DESC</description>
|
||||||
<namespace path="src">Moko\Plugin\Task\MokoSuiteClientDemo</namespace>
|
<namespace path="src">Moko\Plugin\Task\MokoSuiteClientDemo</namespace>
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
* INGROUP: MokoSuiteClient
|
* INGROUP: MokoSuiteClient
|
||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteClient
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteClient
|
||||||
* PATH: /src/packages/plg_system_mokosuiteclient/Service/DemoResetService.php
|
* PATH: /src/packages/plg_system_mokosuiteclient/Service/DemoResetService.php
|
||||||
* VERSION: 02.48.16
|
* VERSION: 02.48.50
|
||||||
* BRIEF: Content-only snapshot/restore for demo site reset
|
* BRIEF: Content-only snapshot/restore for demo site reset
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<license>GNU General Public License version 3 or later; see LICENSE</license>
|
<license>GNU General Public License version 3 or later; see LICENSE</license>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||||
<version>02.48.16</version>
|
<version>02.48.50</version>
|
||||||
<description>PLG_TASK_MOKOSUITECLIENTSYNC_DESC</description>
|
<description>PLG_TASK_MOKOSUITECLIENTSYNC_DESC</description>
|
||||||
<namespace path="src">Moko\Plugin\Task\MokoSuiteClientSync</namespace>
|
<namespace path="src">Moko\Plugin\Task\MokoSuiteClientSync</namespace>
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
* INGROUP: MokoSuiteClient
|
* INGROUP: MokoSuiteClient
|
||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteClient
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteClient
|
||||||
* PATH: /src/packages/plg_system_mokosuiteclient/Service/ContentSyncReceiver.php
|
* PATH: /src/packages/plg_system_mokosuiteclient/Service/ContentSyncReceiver.php
|
||||||
* VERSION: 02.48.16
|
* VERSION: 02.48.50
|
||||||
* BRIEF: Receiver-side content sync — applies incoming payload to local DB
|
* BRIEF: Receiver-side content sync — applies incoming payload to local DB
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
* INGROUP: MokoSuiteClient
|
* INGROUP: MokoSuiteClient
|
||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteClient
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteClient
|
||||||
* PATH: /src/packages/plg_system_mokosuiteclient/Service/ContentSyncService.php
|
* PATH: /src/packages/plg_system_mokosuiteclient/Service/ContentSyncService.php
|
||||||
* VERSION: 02.48.16
|
* VERSION: 02.48.50
|
||||||
* BRIEF: Sender-side content sync — builds payload and pushes to remote sites
|
* BRIEF: Sender-side content sync — builds payload and pushes to remote sites
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<license>GPL-3.0-or-later</license>
|
<license>GPL-3.0-or-later</license>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||||
<version>02.48.16</version>
|
<version>02.48.50</version>
|
||||||
<description>Joomla Web Services API routes for MokoSuiteClient site management — health checks, cache, updates, backups, and site info.</description>
|
<description>Joomla Web Services API routes for MokoSuiteClient site management — health checks, cache, updates, backups, and site info.</description>
|
||||||
<namespace path="src">Moko\Plugin\WebServices\MokoSuiteClient</namespace>
|
<namespace path="src">Moko\Plugin\WebServices\MokoSuiteClient</namespace>
|
||||||
<files>
|
<files>
|
||||||
|
|||||||
@@ -2,14 +2,14 @@
|
|||||||
<extension type="package" method="upgrade">
|
<extension type="package" method="upgrade">
|
||||||
<name>Package - MokoSuiteClient</name>
|
<name>Package - MokoSuiteClient</name>
|
||||||
<packagename>mokosuiteclient</packagename>
|
<packagename>mokosuiteclient</packagename>
|
||||||
<version>02.48.16</version>
|
<version>02.48.50</version>
|
||||||
<creationDate>2026-06-02</creationDate>
|
<creationDate>2026-06-02</creationDate>
|
||||||
<author>Moko Consulting</author>
|
<author>Moko Consulting</author>
|
||||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||||
<copyright>Copyright (C) 2026 Moko Consulting. All rights reserved.</copyright>
|
<copyright>Copyright (C) 2026 Moko Consulting. All rights reserved.</copyright>
|
||||||
<license>GNU General Public License version 3 or later; see LICENSE</license>
|
<license>GNU General Public License version 3 or later; see LICENSE</license>
|
||||||
<description>MokoSuiteClient site management suite — admin dashboard, security firewall, tenant restrictions, health monitoring, developer tools, and REST API.</description>
|
<description>MokoSuiteClient site management suite: admin dashboard, security firewall, tenant restrictions, health monitoring, developer tools, and REST API.</description>
|
||||||
<dlid prefix="dlid=" suffix=""/>
|
<dlid prefix="dlid=" suffix=""/>
|
||||||
<blockChildUninstall>true</blockChildUninstall>
|
<blockChildUninstall>true</blockChildUninstall>
|
||||||
<scriptfile>script.php</scriptfile>
|
<scriptfile>script.php</scriptfile>
|
||||||
|
|||||||
Reference in New Issue
Block a user