diff --git a/.mokogitea/manifest.xml b/.mokogitea/manifest.xml index 6ffd483..f05211e 100644 --- a/.mokogitea/manifest.xml +++ b/.mokogitea/manifest.xml @@ -8,7 +8,7 @@ Package - MokoWaaS MokoConsulting White-label identity, security hardening, and tenant restriction layer for WaaS-managed Joomla environments - 02.25.00 + 02.25.03 GNU General Public License v3 diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 67b257b..49fdc16 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: moko-platform.Automation -# VERSION: 02.25.00 +# VERSION: 02.25.03 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f48d95..ec4516c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,14 +14,12 @@ INGROUP: MokoWaaS.Documentation REPO: https://github.com/mokoconsulting-tech/mokowaas PATH: ./CHANGELOG.md - VERSION: 02.25.00 + VERSION: 02.25.03 BRIEF: Version history using `Keep a Changelog` --> # Changelog ## [Unreleased] - -## [02.25.00] --- 2026-05-30 ### Added - API endpoint `POST /api/index.php/v1/mokowaas/install` — install extensions from a remote ZIP URL - Demo Mode with configurable warning banner on frontend when enabled @@ -51,3 +49,30 @@ All notable changes to the MokoWaaS plugin will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [02.17.00] --- 2026-05-28 + +### Changed +- Migrated all workflow and template paths from `.github/` to `.mokogitea/` +- Template source paths updated: `templates/gitea/` to `templates/mokogitea/` +- HCL definition files removed -- Template repos are now the canonical source + +### Added +- `branch-cleanup.yml`: auto-delete merged feature branches after PR merge +- `plg_webservices_perfectpublisher`: REST API for Perfect Publisher (com_autotweet) — channels, posts, requests, rules, feeds, and stats + +### Planned +- License/subscription check +- System email template branding (DB approach) + +### Added +- Trusted IPs: configurable repeatable rows of IP addresses, CIDR ranges, and wildcards that bypass admin session timeout +- Supports exact IPs (192.168.1.100), CIDR (10.0.0.0/24), and wildcards (192.168.1.*) +- Each entry has a label and enabled toggle for easy management +- Current IP display above trusted IPs table so admins can easily add their own IP + +### Fixed +- Trusted IP session bypass: moved from `onAfterInitialise` to `boot()` so Joomla's session lifetime is extended before the session handler validates it (was too late, Joomla expired the session first) +- updates.xml: removed stale pre-release entries pointing to non-existent dev artifacts, legacy plugin update entry that caused stable sites to attempt dev downloads +- Removed duplicate `` from inner plugin manifest — only the package-level manifest should register the update server +- Auto-cleanup of stale plugin-level update site entries on install/update (cleans `#__update_sites` and `#__update_sites_extensions`) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index b9ff4d6..2caaced 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -14,7 +14,7 @@ DEFGROUP: Joomla.Plugin INGROUP: MokoWaaS.Documentation REPO: https://github.com/mokoconsulting-tech/mokowaas - VERSION: 02.25.00 + VERSION: 02.25.03 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 be68960..86bf09c 100644 --- a/GOVERNANCE.md +++ b/GOVERNANCE.md @@ -19,7 +19,7 @@ DEFGROUP: mokoconsulting-tech.MokoWaaSBrand INGROUP: MokoStandards.Governance REPO: https://github.com/mokoconsulting-tech/MokoWaaSBrand - VERSION: 02.25.00 + VERSION: 02.25.03 PATH: /GOVERNANCE.md BRIEF: Project governance rules, roles, and decision process for MokoWaaSBrand --> diff --git a/LICENSE.md b/LICENSE.md index 1676e8a..023be5d 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -15,7 +15,7 @@ INGROUP: MokoWaaS.Documentation REPO: https://github.com/mokoconsulting-tech/mokowaas PATH: ./LICENSE.md - VERSION: 02.25.00 + VERSION: 02.25.03 BRIEF: Project license (GPL-3.0-or-later) --> GNU GENERAL PUBLIC LICENSE diff --git a/README.md b/README.md index 9dafcaf..fb8e990 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ DEFGROUP: Joomla.Plugin INGROUP: MokoWaaS REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS - VERSION: 02.25.00 + VERSION: 02.25.03 PATH: /README.md BRIEF: MokoWaaS platform plugin for Joomla --> diff --git a/SECURITY.md b/SECURITY.md index 8e2af08..6f01a3b 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.25.00 +VERSION: 02.25.03 BRIEF: Security vulnerability reporting and handling policy --> diff --git a/docs/guides/build-guide.md b/docs/guides/build-guide.md index 282fdc1..dd64c04 100644 --- a/docs/guides/build-guide.md +++ b/docs/guides/build-guide.md @@ -11,13 +11,13 @@ INGROUP: MokoWaaS.Build REPO: https://github.com/mokoconsulting-tech/mokowaas FILE: build-guide.md - VERSION: 02.25.00 + VERSION: 02.25.03 PATH: /docs/guides/ BRIEF: Build and packaging guide for the MokoWaaS system plugin NOTE: Defines environment setup, repository layout, packaging rules, and release preparation --> -# MokoWaaS Build Guide (VERSION: 02.25.00) +# MokoWaaS Build Guide (VERSION: 02.25.03) ## 1. Purpose diff --git a/docs/guides/configuration-guide.md b/docs/guides/configuration-guide.md index d6c6ec5..3df63e2 100644 --- a/docs/guides/configuration-guide.md +++ b/docs/guides/configuration-guide.md @@ -10,13 +10,13 @@ DEFGROUP: Joomla.Plugin INGROUP: MokoWaaS.Guides REPO: https://github.com/mokoconsulting-tech/mokowaas - VERSION: 02.25.00 + VERSION: 02.25.03 PATH: /docs/guides/configuration-guide.md BRIEF: Configuration guide for the MokoWaaS system plugin NOTE: Defines plugin parameters, expected behaviors, and recommended defaults --> -# MokoWaaS Configuration Guide (VERSION: 02.25.00) +# MokoWaaS Configuration Guide (VERSION: 02.25.03) ## 1. Objective diff --git a/docs/guides/installation-guide.md b/docs/guides/installation-guide.md index 597651f..a6f0cd7 100644 --- a/docs/guides/installation-guide.md +++ b/docs/guides/installation-guide.md @@ -10,13 +10,13 @@ DEFGROUP: Joomla.Plugin INGROUP: MokoWaaS.Guides REPO: https://github.com/mokoconsulting-tech/mokowaas - VERSION: 02.25.00 + VERSION: 02.25.03 PATH: /docs/guides/installation-guide.md BRIEF: Installation guide for the MokoWaaS system plugin NOTE: First document in the guide set --> -# MokoWaaS Installation Guide (VERSION: 02.25.00) +# MokoWaaS Installation Guide (VERSION: 02.25.03) ## Introduction diff --git a/docs/guides/operations-guide.md b/docs/guides/operations-guide.md index 4e52b7c..803380a 100644 --- a/docs/guides/operations-guide.md +++ b/docs/guides/operations-guide.md @@ -10,13 +10,13 @@ DEFGROUP: Joomla.Plugin INGROUP: MokoWaaS.Guides REPO: https://github.com/mokoconsulting-tech/mokowaas - VERSION: 02.25.00 + VERSION: 02.25.03 PATH: /docs/guides/operations-guide.md BRIEF: Operational guide for administering and managing the MokoWaaS system plugin NOTE: Defines lifecycle, responsibilities, and operational behaviors --> -# MokoWaaS Operations Guide (VERSION: 02.25.00) +# MokoWaaS Operations Guide (VERSION: 02.25.03) ## Introduction diff --git a/docs/guides/rollback-and-recovery-guide.md b/docs/guides/rollback-and-recovery-guide.md index 6b52b2e..9bb4ec3 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: MokoWaaS.Guides REPO: https://github.com/mokoconsulting-tech/mokowaas - VERSION: 02.25.00 + VERSION: 02.25.03 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 WaaS plugin governance --> -# MokoWaaS Rollback and Recovery Guide (VERSION: 02.25.00) +# MokoWaaS Rollback and Recovery Guide (VERSION: 02.25.03) ## Introduction diff --git a/docs/guides/testing-guide.md b/docs/guides/testing-guide.md index b3b5f93..c2c7ad7 100644 --- a/docs/guides/testing-guide.md +++ b/docs/guides/testing-guide.md @@ -7,13 +7,13 @@ DEFGROUP: Joomla.Plugin INGROUP: MokoWaaS.Guides REPO: https://github.com/mokoconsulting-tech/mokowaas - VERSION: 02.25.00 + VERSION: 02.25.03 PATH: /docs/guides/testing-guide.md BRIEF: Testing guide for MokoWaaS v02.01.08 NOTE: Covers manual test procedures for language overrides, install/uninstall, and configuration --> -# MokoWaaS Testing Guide (VERSION: 02.25.00) +# MokoWaaS Testing Guide (VERSION: 02.25.03) ## 1. Prerequisites diff --git a/docs/guides/troubleshooting-guide.md b/docs/guides/troubleshooting-guide.md index 082e9d0..bd86bc3 100644 --- a/docs/guides/troubleshooting-guide.md +++ b/docs/guides/troubleshooting-guide.md @@ -10,13 +10,13 @@ DEFGROUP: Joomla.Plugin INGROUP: MokoWaaS.Guides REPO: https://github.com/mokoconsulting-tech/mokowaas - VERSION: 02.25.00 + VERSION: 02.25.03 PATH: /docs/guides/troubleshooting-guide.md BRIEF: Troubleshooting guide for diagnosing and resolving issues related to the MokoWaaS plugin NOTE: Designed for administrators and WaaS operations teams --> -# MokoWaaS Troubleshooting Guide (VERSION: 02.25.00) +# MokoWaaS Troubleshooting Guide (VERSION: 02.25.03) ## Introduction diff --git a/docs/guides/upgrade-and-versioning-guide.md b/docs/guides/upgrade-and-versioning-guide.md index 7cd694b..62d414e 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: MokoWaaS.Guides REPO: https://github.com/mokoconsulting-tech/mokowaas - VERSION: 02.25.00 + VERSION: 02.25.03 PATH: /docs/guides/upgrade-and-versioning-guide.md BRIEF: Guide for updating, versioning, and maintaining the MokoWaaS plugin NOTE: Defines release flow, version rules, and upgrade validation --> -# MokoWaaS Upgrade and Versioning Guide (VERSION: 02.25.00) +# MokoWaaS Upgrade and Versioning Guide (VERSION: 02.25.03) ## Introduction diff --git a/docs/index.md b/docs/index.md index 4694783..86ff52b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -10,13 +10,13 @@ DEFGROUP: Joomla.Plugin INGROUP: MokoWaaS.Documentation REPO: https://github.com/mokoconsulting-tech/mokowaas - VERSION: 02.25.00 + VERSION: 02.25.03 PATH: /docs/index.md BRIEF: Master index of all documentation for the MokoWaaS plugin NOTE: Automatically maintained index for all guide canvases --> -# MokoWaaS Documentation Index (VERSION: 02.25.00) +# MokoWaaS Documentation Index (VERSION: 02.25.03) ## Introduction diff --git a/docs/plugin-basic.md b/docs/plugin-basic.md index 10fdb3d..559c61c 100644 --- a/docs/plugin-basic.md +++ b/docs/plugin-basic.md @@ -11,12 +11,12 @@ INGROUP: MokoWaaS REPO: https://github.com/mokoconsulting-tech/mokowaas PATH: /docs/plugin-basic.md - VERSION: 02.25.00 + VERSION: 02.25.03 BRIEF: Baseline documentation for the MokoWaaS system plugin NOTE: Foundational reference for internal and external stakeholders --> -# MokoWaaS Plugin Overview (VERSION: 02.25.00) +# MokoWaaS Plugin Overview (VERSION: 02.25.03) ## Introduction diff --git a/docs/update-server.md b/docs/update-server.md index 008f927..f885389 100644 --- a/docs/update-server.md +++ b/docs/update-server.md @@ -10,7 +10,7 @@ DEFGROUP: MokoWaaS.Documentation INGROUP: MokoStandards.Templates REPO: https://github.com/mokoconsulting-tech/MokoWaaS PATH: /docs/update-server.md -VERSION: 02.25.00 +VERSION: 02.25.03 BRIEF: How this extension's Joomla update server file (update.xml) is managed --> diff --git a/src/packages/com_mokowaas/api/src/Controller/ResetController.php b/src/packages/com_mokowaas/api/src/Controller/ResetController.php index 671332f..7d88c7d 100644 --- a/src/packages/com_mokowaas/api/src/Controller/ResetController.php +++ b/src/packages/com_mokowaas/api/src/Controller/ResetController.php @@ -103,11 +103,13 @@ class ResetController extends BaseController require_once $serviceFile; - $tablesRaw = $params->get('demo_snapshot_tables', ''); - $tables = array_filter(array_map('trim', explode("\n", $tablesRaw))); - $media = (bool) $params->get('demo_snapshot_include_media', 1); + $tablesParam = $params->get('demo_snapshot_tables', ''); + $tables = is_array($tablesParam) ? array_filter($tablesParam) : array_filter(array_map('trim', explode("\n", $tablesParam))); + $media = $params->get('demo_snapshot_include_media', ['images']); + if ($media === '1' || $media === true) $media = ['images']; + if ($media === '0' || $media === false) $media = []; - return new \Moko\Plugin\System\MokoWaaS\Service\DemoResetService($tables, $media); + return new \Moko\Plugin\System\MokoWaaS\Service\DemoResetService($tables, (array) $media); } /** diff --git a/src/packages/com_mokowaas/api/src/Controller/SnapshotController.php b/src/packages/com_mokowaas/api/src/Controller/SnapshotController.php index 2577cb7..b6cf8b4 100644 --- a/src/packages/com_mokowaas/api/src/Controller/SnapshotController.php +++ b/src/packages/com_mokowaas/api/src/Controller/SnapshotController.php @@ -130,11 +130,13 @@ class SnapshotController extends BaseController $plugin = PluginHelper::getPlugin('system', 'mokowaas'); $params = $plugin ? new Registry($plugin->params) : new Registry; - $tablesRaw = $params->get('demo_snapshot_tables', ''); - $tables = array_filter(array_map('trim', explode("\n", $tablesRaw))); - $media = (bool) $params->get('demo_snapshot_include_media', 1); + $tablesParam = $params->get('demo_snapshot_tables', ''); + $tables = is_array($tablesParam) ? array_filter($tablesParam) : array_filter(array_map('trim', explode("\n", $tablesParam))); + $media = $params->get('demo_snapshot_include_media', ['images']); + if ($media === '1' || $media === true) $media = ['images']; + if ($media === '0' || $media === false) $media = []; - return new \Moko\Plugin\System\MokoWaaS\Service\DemoResetService($tables, $media); + return new \Moko\Plugin\System\MokoWaaS\Service\DemoResetService($tables, (array) $media); } /** diff --git a/src/packages/com_mokowaas/mokowaas.xml b/src/packages/com_mokowaas/mokowaas.xml index 1a6520e..00ab55f 100644 --- a/src/packages/com_mokowaas/mokowaas.xml +++ b/src/packages/com_mokowaas/mokowaas.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 02.25.00 + 02.25.03-dev Minimal API-only component for MokoWaaS. Provides REST endpoints for site health, cache, updates, and backups. Moko\Component\MokoWaaS\Api diff --git a/src/packages/plg_system_mokowaas/Extension/MokoWaaS.php b/src/packages/plg_system_mokowaas/Extension/MokoWaaS.php index 7ce7c08..a7183e3 100644 --- a/src/packages/plg_system_mokowaas/Extension/MokoWaaS.php +++ b/src/packages/plg_system_mokowaas/Extension/MokoWaaS.php @@ -22,7 +22,7 @@ * DEFGROUP: Joomla.Plugin * INGROUP: MokoWaaS * REPO: https://github.com/mokoconsulting-tech/mokowaas - * VERSION: 02.25.00 + * VERSION: 02.25.03 * PATH: /src/Extension/MokoWaaS.php * NOTE: Handles Joomla system events for rebranding functionality */ @@ -1104,13 +1104,38 @@ class MokoWaaS extends CMSPlugin implements BootableExtensionInterface $bgColor = htmlspecialchars($this->params->get('demo_banner_color', '#d9534f'), ENT_QUOTES, 'UTF-8'); $showCountdown = (int) $this->params->get('demo_banner_show_countdown', 0); - // Use stored next-reset timestamp (calculated from cron schedule on save) + // Use stored next-reset timestamp, or calculate on the fly from cron schedule $nextReset = $this->params->get('demo_next_reset', ''); $resetAtMs = 0; - if ($showCountdown && !empty($nextReset)) + if ($showCountdown) { - $resetAtMs = strtotime($nextReset) * 1000; + if (!empty($nextReset)) + { + $ts = strtotime($nextReset); + + // If stored timestamp is in the past, recalculate + if ($ts > time()) + { + $resetAtMs = $ts * 1000; + } + } + + // Calculate on the fly if no valid stored timestamp + if ($resetAtMs === 0) + { + $schedule = $this->params->get('demo_reset_schedule', '0 0 * * *'); + $cron = ($schedule === 'custom') + ? $this->params->get('demo_reset_cron', '0 0 * * *') + : $schedule; + + $calculated = $this->calculateNextCronRun($cron); + + if ($calculated) + { + $resetAtMs = strtotime($calculated) * 1000; + } + } } $countdownJs = ''; @@ -1709,16 +1734,33 @@ class MokoWaaS extends CMSPlugin implements BootableExtensionInterface { require_once __DIR__ . '/../Service/DemoResetService.php'; - $tablesRaw = $this->params->get('demo_snapshot_tables', ''); - $tables = array_filter( - array_map('trim', explode("\n", $tablesRaw)) - ); + $tablesParam = $this->params->get('demo_snapshot_tables', ''); - $includeMedia = (bool) $this->params->get('demo_snapshot_include_media', 1); + // Handle both checkbox array and legacy newline-separated textarea + if (is_array($tablesParam)) + { + $tables = array_filter($tablesParam); + } + else + { + $tables = array_filter(array_map('trim', explode("\n", $tablesParam))); + } + + $mediaDirs = $this->params->get('demo_snapshot_include_media', ['images']); + + // Handle legacy boolean value + if ($mediaDirs === '1' || $mediaDirs === true) + { + $mediaDirs = ['images']; + } + elseif ($mediaDirs === '0' || $mediaDirs === false) + { + $mediaDirs = []; + } return new \Moko\Plugin\System\MokoWaaS\Service\DemoResetService( $tables, - $includeMedia + (array) $mediaDirs ); } diff --git a/src/packages/plg_system_mokowaas/Field/AllowedIpsField.php b/src/packages/plg_system_mokowaas/Field/AllowedIpsField.php index c08f41f..b9a83ac 100644 --- a/src/packages/plg_system_mokowaas/Field/AllowedIpsField.php +++ b/src/packages/plg_system_mokowaas/Field/AllowedIpsField.php @@ -7,7 +7,7 @@ * FILE INFORMATION * DEFGROUP: Joomla.Plugin * INGROUP: MokoWaaS - * VERSION: 02.25.00 + * VERSION: 02.25.03 * PATH: /src/Field/AllowedIpsField.php * BRIEF: Custom form field that displays the current IP whitelist */ diff --git a/src/packages/plg_system_mokowaas/Field/CopyableTokenField.php b/src/packages/plg_system_mokowaas/Field/CopyableTokenField.php new file mode 100644 index 0000000..f035205 --- /dev/null +++ b/src/packages/plg_system_mokowaas/Field/CopyableTokenField.php @@ -0,0 +1,63 @@ +value ?? '', ENT_QUOTES, 'UTF-8'); + $id = $this->id; + + if (empty($this->value)) + { + return '
Token will be generated automatically on first save.
'; + } + + return << + + + +HTML; + } +} diff --git a/src/packages/plg_system_mokowaas/Field/CurrentIpField.php b/src/packages/plg_system_mokowaas/Field/CurrentIpField.php index 022b8b4..3f96e91 100644 --- a/src/packages/plg_system_mokowaas/Field/CurrentIpField.php +++ b/src/packages/plg_system_mokowaas/Field/CurrentIpField.php @@ -7,7 +7,7 @@ * FILE INFORMATION * DEFGROUP: Joomla.Plugin * INGROUP: MokoWaaS - * VERSION: 02.25.00 + * VERSION: 02.25.03 * PATH: /src/Field/CurrentIpField.php * BRIEF: Read-only field that displays the current user's IP address */ diff --git a/src/packages/plg_system_mokowaas/Field/SnapshotTablesField.php b/src/packages/plg_system_mokowaas/Field/SnapshotTablesField.php new file mode 100644 index 0000000..7a4e891 --- /dev/null +++ b/src/packages/plg_system_mokowaas/Field/SnapshotTablesField.php @@ -0,0 +1,157 @@ + ['content', 'categories', 'fields', 'tags', 'contentitem_tag_map', 'ucm_content', 'ucm_history'], + 'users' => ['users', 'user_usergroup_map', 'user_profiles', 'usergroups', 'user_keys', 'user_mfa'], + 'menus' => ['menu', 'menu_types'], + 'modules' => ['modules', 'modules_menu'], + 'assets' => ['assets'], + ]; + + protected function getOptions() + { + $db = Factory::getDbo(); + $prefix = $db->getPrefix(); + $tables = $db->getTableList(); + + $options = []; + + foreach ($tables as $table) + { + // Only show tables with the site's prefix + if (strpos($table, $prefix) !== 0) + { + continue; + } + + // Convert real table name to #__ notation + $logical = '#__' . substr($table, strlen($prefix)); + + // Determine group for display ordering + $group = 'Other'; + + foreach (self::TABLE_GROUPS as $groupName => $patterns) + { + $suffix = substr($table, strlen($prefix)); + + foreach ($patterns as $pattern) + { + if ($suffix === $pattern) + { + $group = ucfirst($groupName); + break 2; + } + } + } + + $obj = (object) [ + 'value' => $logical, + 'text' => $logical, + 'disable' => false, + 'class' => '', + 'onclick' => '', + ]; + + $options[$group][] = $obj; + } + + // Flatten with group headers: content tables first, then alphabetical + $priority = ['Content', 'Users', 'Menus', 'Modules', 'Assets']; + $sorted = []; + + foreach ($priority as $g) + { + if (isset($options[$g])) + { + $sorted = array_merge($sorted, $options[$g]); + unset($options[$g]); + } + } + + // Remaining tables (Other) + if (isset($options['Other'])) + { + sort($options['Other']); + $sorted = array_merge($sorted, $options['Other']); + } + + return $sorted; + } + + protected function getInput() + { + // If no value stored yet, use defaults + if ($this->value === null || $this->value === '') + { + $this->value = self::DEFAULT_TABLES; + } + elseif (is_string($this->value)) + { + // Handle legacy textarea format (newline-separated) + $this->value = array_filter(array_map('trim', explode("\n", $this->value))); + } + + return parent::getInput(); + } +} diff --git a/src/packages/plg_system_mokowaas/Service/ContentSyncReceiver.php b/src/packages/plg_system_mokowaas/Service/ContentSyncReceiver.php index b8cd1af..03f7016 100644 --- a/src/packages/plg_system_mokowaas/Service/ContentSyncReceiver.php +++ b/src/packages/plg_system_mokowaas/Service/ContentSyncReceiver.php @@ -10,7 +10,7 @@ * INGROUP: MokoWaaS * REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS * PATH: /src/packages/plg_system_mokowaas/Service/ContentSyncReceiver.php - * VERSION: 02.25.00 + * VERSION: 02.25.03 * BRIEF: Receiver-side content sync — applies incoming payload to local DB */ diff --git a/src/packages/plg_system_mokowaas/Service/ContentSyncService.php b/src/packages/plg_system_mokowaas/Service/ContentSyncService.php index f91afc3..1c25565 100644 --- a/src/packages/plg_system_mokowaas/Service/ContentSyncService.php +++ b/src/packages/plg_system_mokowaas/Service/ContentSyncService.php @@ -10,7 +10,7 @@ * INGROUP: MokoWaaS * REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS * PATH: /src/packages/plg_system_mokowaas/Service/ContentSyncService.php - * VERSION: 02.25.00 + * VERSION: 02.25.03 * BRIEF: Sender-side content sync — builds payload and pushes to remote sites */ diff --git a/src/packages/plg_system_mokowaas/Service/DemoResetService.php b/src/packages/plg_system_mokowaas/Service/DemoResetService.php index cd3cea1..89ff461 100644 --- a/src/packages/plg_system_mokowaas/Service/DemoResetService.php +++ b/src/packages/plg_system_mokowaas/Service/DemoResetService.php @@ -10,7 +10,7 @@ * INGROUP: MokoWaaS * REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS * PATH: /src/packages/plg_system_mokowaas/Service/DemoResetService.php - * VERSION: 02.25.00 + * VERSION: 02.25.03 * BRIEF: Core snapshot/restore service for demo site reset */ @@ -91,27 +91,39 @@ class DemoResetService private array $tables; /** - * Whether to include media files in snapshots. + * Directories to include in media snapshot (e.g. ['images', 'media']). * - * @var bool - * @since 02.21.00 + * @var array + * @since 02.25.00 */ - private bool $includeMedia; + private array $mediaDirs; /** * Constructor. * - * @param array $tables Table names with #__ prefix - * @param bool $includeMedia Include /images/ directory in snapshot - * @param string $baseDir Override snapshot root (for testing) + * @param array $tables Table names with #__ prefix + * @param array|bool $mediaDirs Dirs to snapshot: ['images','media'], true (= images), false/[] (= none) + * @param string $baseDir Override snapshot root (for testing) * * @since 02.21.00 */ - public function __construct(array $tables = [], bool $includeMedia = true, string $baseDir = '') + public function __construct(array $tables = [], $mediaDirs = ['images'], string $baseDir = '') { - $this->tables = !empty($tables) ? $tables : self::DEFAULT_TABLES; - $this->includeMedia = $includeMedia; - $this->snapshotDir = $baseDir ?: JPATH_ROOT . '/mokowaas-snapshots'; + $this->tables = !empty($tables) ? $tables : self::DEFAULT_TABLES; + $this->snapshotDir = $baseDir ?: JPATH_ROOT . '/mokowaas-snapshots'; + + if ($mediaDirs === true) + { + $this->mediaDirs = ['images']; + } + elseif ($mediaDirs === false || empty($mediaDirs)) + { + $this->mediaDirs = []; + } + else + { + $this->mediaDirs = (array) $mediaDirs; + } } /** @@ -193,12 +205,22 @@ class DemoResetService $dumped++; } - // Media snapshot - $hasMedia = false; + // Media snapshot — one ZIP per directory + $mediaDirs = []; - if ($this->includeMedia) + foreach ($this->mediaDirs as $dir) { - $hasMedia = $this->snapshotMedia($path); + $fullPath = JPATH_ROOT . '/' . $dir; + + if (is_dir($fullPath)) + { + $zipName = 'media_' . $dir . '.zip'; + + if ($this->snapshotDirectory($fullPath, $path . '/' . $zipName)) + { + $mediaDirs[] = $dir; + } + } } // Write manifest @@ -207,7 +229,8 @@ class DemoResetService 'created_at' => gmdate('Y-m-d\TH:i:s\Z'), 'tables' => $dumped, 'table_list' => $this->tables, - 'has_media' => $hasMedia, + 'has_media' => !empty($mediaDirs), + 'media_dirs' => $mediaDirs, 'joomla_version' => JVERSION, ]; @@ -308,12 +331,41 @@ class DemoResetService } } - // Restore media + // Restore media directories $mediaRestored = false; + $restoredDirs = $manifest['media_dirs'] ?? []; - if ($manifest['has_media'] ?? false) + // Legacy support: old manifests used has_media=true with a single media.zip for /images/ + if (empty($restoredDirs) && ($manifest['has_media'] ?? false)) { - $mediaRestored = $this->restoreMedia($path); + $restoredDirs = ['images']; + } + + foreach ($restoredDirs as $dir) + { + $zipName = 'media_' . $dir . '.zip'; + $zipPath = $path . '/' . $zipName; + + // Legacy fallback: old snapshots used media.zip for images + if (!file_exists($zipPath) && $dir === 'images' && file_exists($path . '/media.zip')) + { + $zipPath = $path . '/media.zip'; + } + + if (file_exists($zipPath)) + { + $targetDir = JPATH_ROOT . '/' . $dir; + $this->clearDirectory($targetDir); + + $zip = new \ZipArchive(); + + if ($zip->open($zipPath) === true) + { + $zip->extractTo($targetDir); + $zip->close(); + $mediaRestored = true; + } + } } Log::add( @@ -495,25 +547,23 @@ class DemoResetService } /** - * Create a ZIP archive of the /images/ directory. + * Create a ZIP archive of a directory. * - * @param string $snapshotDir Snapshot directory path + * @param string $sourceDir Full path to the directory to archive + * @param string $zipPath Full path for the output ZIP file * - * @return bool True if media was archived + * @return bool True if archived successfully * - * @since 02.21.00 + * @since 02.25.00 */ - private function snapshotMedia(string $snapshotDir): bool + private function snapshotDirectory(string $sourceDir, string $zipPath): bool { - $imagesDir = JPATH_ROOT . '/images'; - - if (!is_dir($imagesDir)) + if (!is_dir($sourceDir)) { return false; } - $zipPath = $snapshotDir . '/media.zip'; - $zip = new \ZipArchive(); + $zip = new \ZipArchive(); if ($zip->open($zipPath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE) !== true) { @@ -521,13 +571,13 @@ class DemoResetService } $iterator = new \RecursiveIteratorIterator( - new \RecursiveDirectoryIterator($imagesDir, \RecursiveDirectoryIterator::SKIP_DOTS), + new \RecursiveDirectoryIterator($sourceDir, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST ); foreach ($iterator as $item) { - $relativePath = substr($item->getPathname(), strlen($imagesDir) + 1); + $relativePath = substr($item->getPathname(), strlen($sourceDir) + 1); $relativePath = str_replace('\\', '/', $relativePath); if ($item->isDir()) @@ -545,41 +595,6 @@ class DemoResetService return true; } - /** - * Restore media files from a snapshot ZIP. - * - * @param string $snapshotDir Snapshot directory path - * - * @return bool True if media was restored - * - * @since 02.21.00 - */ - private function restoreMedia(string $snapshotDir): bool - { - $zipPath = $snapshotDir . '/media.zip'; - $imagesDir = JPATH_ROOT . '/images'; - - if (!file_exists($zipPath)) - { - return false; - } - - // Clear existing images directory contents (keep the directory itself) - $this->clearDirectory($imagesDir); - - $zip = new \ZipArchive(); - - if ($zip->open($zipPath) !== true) - { - return false; - } - - $zip->extractTo($imagesDir); - $zip->close(); - - return true; - } - /** * Ensure the snapshot root directory exists with .htaccess protection. * diff --git a/src/packages/plg_system_mokowaas/language/en-GB/plg_system_mokowaas.ini b/src/packages/plg_system_mokowaas/language/en-GB/plg_system_mokowaas.ini index 8bd0219..e9fc2f3 100644 --- a/src/packages/plg_system_mokowaas/language/en-GB/plg_system_mokowaas.ini +++ b/src/packages/plg_system_mokowaas/language/en-GB/plg_system_mokowaas.ini @@ -171,8 +171,8 @@ PLG_SYSTEM_MOKOWAAS_DEMO_NEXT_RESET_LABEL="Next Scheduled Reset" PLG_SYSTEM_MOKOWAAS_DEMO_NEXT_RESET_DESC="Calculated automatically from the reset schedule. The banner countdown uses this timestamp." PLG_SYSTEM_MOKOWAAS_DEMO_TABLES_LABEL="Snapshot Tables" PLG_SYSTEM_MOKOWAAS_DEMO_TABLES_DESC="Database tables to include in snapshots. One per line, using #__ prefix. These tables will be truncated and restored during a reset." -PLG_SYSTEM_MOKOWAAS_DEMO_MEDIA_LABEL="Include Media Files" -PLG_SYSTEM_MOKOWAAS_DEMO_MEDIA_DESC="Include the /images/ directory in snapshots. Disabling this speeds up snapshot/restore for sites with large media libraries." +PLG_SYSTEM_MOKOWAAS_DEMO_MEDIA_LABEL="Include Directories" +PLG_SYSTEM_MOKOWAAS_DEMO_MEDIA_DESC="Select which directories to include in the snapshot. Images contains uploaded media, Media contains extension assets." PLG_SYSTEM_MOKOWAAS_DEMO_ACTIVE_BASELINE_LABEL="Active Baseline Name" PLG_SYSTEM_MOKOWAAS_DEMO_ACTIVE_BASELINE_DESC="Name of the baseline snapshot used by admin toggles and scheduled tasks. Alphanumeric, hyphens, and underscores only." PLG_SYSTEM_MOKOWAAS_DEMO_TAKE_SNAPSHOT_LABEL="Take Snapshot Now" diff --git a/src/packages/plg_system_mokowaas/language/en-US/plg_system_mokowaas.ini b/src/packages/plg_system_mokowaas/language/en-US/plg_system_mokowaas.ini index 8bd0219..e9fc2f3 100644 --- a/src/packages/plg_system_mokowaas/language/en-US/plg_system_mokowaas.ini +++ b/src/packages/plg_system_mokowaas/language/en-US/plg_system_mokowaas.ini @@ -171,8 +171,8 @@ PLG_SYSTEM_MOKOWAAS_DEMO_NEXT_RESET_LABEL="Next Scheduled Reset" PLG_SYSTEM_MOKOWAAS_DEMO_NEXT_RESET_DESC="Calculated automatically from the reset schedule. The banner countdown uses this timestamp." PLG_SYSTEM_MOKOWAAS_DEMO_TABLES_LABEL="Snapshot Tables" PLG_SYSTEM_MOKOWAAS_DEMO_TABLES_DESC="Database tables to include in snapshots. One per line, using #__ prefix. These tables will be truncated and restored during a reset." -PLG_SYSTEM_MOKOWAAS_DEMO_MEDIA_LABEL="Include Media Files" -PLG_SYSTEM_MOKOWAAS_DEMO_MEDIA_DESC="Include the /images/ directory in snapshots. Disabling this speeds up snapshot/restore for sites with large media libraries." +PLG_SYSTEM_MOKOWAAS_DEMO_MEDIA_LABEL="Include Directories" +PLG_SYSTEM_MOKOWAAS_DEMO_MEDIA_DESC="Select which directories to include in the snapshot. Images contains uploaded media, Media contains extension assets." PLG_SYSTEM_MOKOWAAS_DEMO_ACTIVE_BASELINE_LABEL="Active Baseline Name" PLG_SYSTEM_MOKOWAAS_DEMO_ACTIVE_BASELINE_DESC="Name of the baseline snapshot used by admin toggles and scheduled tasks. Alphanumeric, hyphens, and underscores only." PLG_SYSTEM_MOKOWAAS_DEMO_TAKE_SNAPSHOT_LABEL="Take Snapshot Now" diff --git a/src/packages/plg_system_mokowaas/mokowaas.xml b/src/packages/plg_system_mokowaas/mokowaas.xml index 606a136..2dcecb8 100644 --- a/src/packages/plg_system_mokowaas/mokowaas.xml +++ b/src/packages/plg_system_mokowaas/mokowaas.xml @@ -30,7 +30,7 @@ GNU General Public License version 3 or later; see LICENSE.md hello@mokoconsulting.tech https://mokoconsulting.tech - 02.25.00 + 02.25.03-dev This plugin rebrands the Joomla system interface with MokoWaaS identity. It applies language overrides and ensures consistent branding across the platform. Moko\Plugin\System\MokoWaaS script.php @@ -268,6 +268,7 @@
+ + + @@ -314,17 +318,15 @@ label="PLG_SYSTEM_MOKOWAAS_DEMO_NEXT_RESET_LABEL" description="PLG_SYSTEM_MOKOWAAS_DEMO_NEXT_RESET_DESC" readonly="true" default="" /> - - + - - + description="PLG_SYSTEM_MOKOWAAS_DEMO_MEDIA_DESC"> + + GNU General Public License version 3 or later; see LICENSE hello@mokoconsulting.tech https://mokoconsulting.tech - 02.25.00 + 02.25.03-dev PLG_TASK_MOKOWAASDEMO_DESC Moko\Plugin\Task\MokoWaaSDemo diff --git a/src/packages/plg_task_mokowaasdemo/src/Extension/DemoReset.php b/src/packages/plg_task_mokowaasdemo/src/Extension/DemoReset.php index 24d2f2f..27de707 100644 --- a/src/packages/plg_task_mokowaasdemo/src/Extension/DemoReset.php +++ b/src/packages/plg_task_mokowaasdemo/src/Extension/DemoReset.php @@ -97,11 +97,13 @@ final class DemoReset extends CMSPlugin implements SubscriberInterface require_once $serviceFile; - $tablesRaw = $sysParams->get('demo_snapshot_tables', ''); - $tables = array_filter(array_map('trim', explode("\n", $tablesRaw))); - $media = (bool) $sysParams->get('demo_snapshot_include_media', 1); + $tablesParam = $sysParams->get('demo_snapshot_tables', ''); + $tables = is_array($tablesParam) ? array_filter($tablesParam) : array_filter(array_map('trim', explode("\n", $tablesParam))); + $media = $sysParams->get('demo_snapshot_include_media', ['images']); + if ($media === '1' || $media === true) $media = ['images']; + if ($media === '0' || $media === false) $media = []; - $service = new \Moko\Plugin\System\MokoWaaS\Service\DemoResetService($tables, $media); + $service = new \Moko\Plugin\System\MokoWaaS\Service\DemoResetService($tables, (array) $media); try { diff --git a/src/packages/plg_webservices_mokowaas/mokowaas.xml b/src/packages/plg_webservices_mokowaas/mokowaas.xml index b82fe31..ea28726 100644 --- a/src/packages/plg_webservices_mokowaas/mokowaas.xml +++ b/src/packages/plg_webservices_mokowaas/mokowaas.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 02.25.00 + 02.25.03-dev Joomla Web Services API routes for MokoWaaS site management — health checks, cache, updates, backups, and site info. Moko\Plugin\WebServices\MokoWaaS diff --git a/src/packages/plg_webservices_perfectpublisher/perfectpublisher.xml b/src/packages/plg_webservices_perfectpublisher/perfectpublisher.xml index fcc9eb2..64f93fe 100644 --- a/src/packages/plg_webservices_perfectpublisher/perfectpublisher.xml +++ b/src/packages/plg_webservices_perfectpublisher/perfectpublisher.xml @@ -7,7 +7,7 @@ GPL-3.0-or-later hello@mokoconsulting.tech https://mokoconsulting.tech - 02.25.00 + 02.25.03-dev Joomla Web Services API routes for Perfect Publisher (com_autotweet) — channels, posts, requests, rules, and feeds. Moko\Plugin\WebServices\PerfectPublisher diff --git a/src/packages/plg_webservices_perfectpublisher/services/provider.php b/src/packages/plg_webservices_perfectpublisher/services/provider.php index cb84b01..fb2f0d8 100644 --- a/src/packages/plg_webservices_perfectpublisher/services/provider.php +++ b/src/packages/plg_webservices_perfectpublisher/services/provider.php @@ -8,7 +8,7 @@ * INGROUP: MokoWaaS * REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS * PATH: /src/packages/plg_webservices_perfectpublisher/services/provider.php - * VERSION: 02.25.00 + * VERSION: 02.25.03 * BRIEF: DI service provider for Perfect Publisher Web Services plugin */ diff --git a/src/packages/plg_webservices_perfectpublisher/src/Extension/PerfectPublisherApi.php b/src/packages/plg_webservices_perfectpublisher/src/Extension/PerfectPublisherApi.php index ad251bc..505ceb4 100644 --- a/src/packages/plg_webservices_perfectpublisher/src/Extension/PerfectPublisherApi.php +++ b/src/packages/plg_webservices_perfectpublisher/src/Extension/PerfectPublisherApi.php @@ -8,7 +8,7 @@ * INGROUP: MokoWaaS * REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS * PATH: /src/packages/plg_webservices_perfectpublisher/src/Extension/PerfectPublisherApi.php - * VERSION: 02.25.00 + * VERSION: 02.25.03 * BRIEF: Web Services API plugin for Perfect Publisher (com_autotweet) */ diff --git a/src/pkg_mokowaas.xml b/src/pkg_mokowaas.xml index 4d10433..03ac2df 100644 --- a/src/pkg_mokowaas.xml +++ b/src/pkg_mokowaas.xml @@ -2,7 +2,7 @@ Package - MokoWaaS mokowaas - 02.25.00 + 02.25.03-dev 2026-05-23 Moko Consulting hello@mokoconsulting.tech diff --git a/updates.xml b/updates.xml index d0ff713..0bbfce2 100644 --- a/updates.xml +++ b/updates.xml @@ -1,67 +1,10 @@ - - Package - MokoWaaS - Package - MokoWaaS alpha build. - pkg_mokowaas - package - site - 02.25.00-alpha - 2026-05-30 - https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/alpha - - https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/alpha/pkg_mokowaas-02.25.00-alpha.zip - - 67f7f86d822d8dc6f450c1d0b68fbaca886ccb42046bcb3c04da909789f95c28 - alpha - https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/raw/branch/main/CHANGELOG.md - Moko Consulting - https://mokoconsulting.tech - - - - Package - MokoWaaS - Package - MokoWaaS beta build. - pkg_mokowaas - package - site - 02.25.00-beta - 2026-05-30 - https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/beta - - https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/beta/pkg_mokowaas-02.25.00-beta.zip - - 67f7f86d822d8dc6f450c1d0b68fbaca886ccb42046bcb3c04da909789f95c28 - beta - https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/raw/branch/main/CHANGELOG.md - Moko Consulting - https://mokoconsulting.tech - - - - Package - MokoWaaS - Package - MokoWaaS rc build. - pkg_mokowaas - package - site - 02.25.00-rc - 2026-05-30 - https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/release-candidate - - https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/release-candidate/pkg_mokowaas-02.25.00-rc.zip - - 67f7f86d822d8dc6f450c1d0b68fbaca886ccb42046bcb3c04da909789f95c28 - rc - https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/raw/branch/main/CHANGELOG.md - Moko Consulting - https://mokoconsulting.tech - - Package - MokoWaaS Package - MokoWaaS stable build. @@ -83,21 +26,78 @@ Package - MokoWaaS - Package - MokoWaaS development build. + Package - MokoWaaS dev build. pkg_mokowaas package site - 02.25.03-dev + 02.26.00-dev 2026-05-30 - https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/development + https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/development - https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/development/pkg_mokowaas-02.25.03-dev.zip + https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/development/pkg_mokowaas-02.26.00-dev.zip - 6719c979e91444c217183f896c598d2701d7b810c6f416d5bad170ba8f4a07eb + 22f4def98469d371d673cde0c740a9b54a5e71d2eeb15c4506aed159541daae8 dev https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/raw/branch/main/CHANGELOG.md Moko Consulting https://mokoconsulting.tech + + + + Package - MokoWaaS + Package - MokoWaaS alpha build. + pkg_mokowaas + package + site + 02.26.00-alpha + 2026-05-30 + https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/alpha + + https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/alpha/pkg_mokowaas-02.26.00-alpha.zip + + 22f4def98469d371d673cde0c740a9b54a5e71d2eeb15c4506aed159541daae8 + alpha + https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/raw/branch/main/CHANGELOG.md + Moko Consulting + https://mokoconsulting.tech + + + + Package - MokoWaaS + Package - MokoWaaS beta build. + pkg_mokowaas + package + site + 02.26.00-beta + 2026-05-30 + https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/beta + + https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/beta/pkg_mokowaas-02.26.00-beta.zip + + 22f4def98469d371d673cde0c740a9b54a5e71d2eeb15c4506aed159541daae8 + beta + https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/raw/branch/main/CHANGELOG.md + Moko Consulting + https://mokoconsulting.tech + + + + Package - MokoWaaS + Package - MokoWaaS rc build. + pkg_mokowaas + package + site + 02.26.00-rc + 2026-05-30 + https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/release-candidate + + https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/release-candidate/pkg_mokowaas-02.26.00-rc.zip + + 22f4def98469d371d673cde0c740a9b54a5e71d2eeb15c4506aed159541daae8 + rc + https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/raw/branch/main/CHANGELOG.md + Moko Consulting + https://mokoconsulting.tech