From 1cdbfd035d09a701450f7edff52b1583918e75dc Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Tue, 2 Jun 2026 14:52:06 -0500 Subject: [PATCH] feat: integrate MokoJoomTOS as Offline Bypass feature plugin + add OpenGraph to catalog New plugin: plg_system_mokowaas_tos (Offline Bypass) - Keeps configured pages accessible during offline mode - SEF path matching + Itemid fallback - Custom MenuslugField for multi-select menu items - Include children option for parent menu matching - Renamed from MokoJoomTOS to MokoWaaS Offline Bypass Also: - Added MokoJoomOpenGraph to extension manager catalog - Added to package manifest, script.php, dashboard, cascade list Authored-by: Moko Consulting Co-Authored-By: Claude Opus 4.6 (1M context) --- .../admin/src/Model/DashboardModel.php | 8 + .../admin/src/Model/ExtensionsModel.php | 10 + .../Extension/MokoWaaS.php | 1 + .../en-GB/plg_system_mokowaas_tos.ini | 13 ++ .../en-GB/plg_system_mokowaas_tos.sys.ini | 3 + .../plg_system_mokowaas_tos/mokowaas_tos.xml | 44 +++++ .../services/provider.php | 34 ++++ .../src/Extension/Tos.php | 172 ++++++++++++++++++ .../src/Field/MenuslugField.php | 81 +++++++++ src/pkg_mokowaas.xml | 1 + src/script.php | 2 + 11 files changed, 369 insertions(+) create mode 100644 src/packages/plg_system_mokowaas_tos/language/en-GB/plg_system_mokowaas_tos.ini create mode 100644 src/packages/plg_system_mokowaas_tos/language/en-GB/plg_system_mokowaas_tos.sys.ini create mode 100644 src/packages/plg_system_mokowaas_tos/mokowaas_tos.xml create mode 100644 src/packages/plg_system_mokowaas_tos/services/provider.php create mode 100644 src/packages/plg_system_mokowaas_tos/src/Extension/Tos.php create mode 100644 src/packages/plg_system_mokowaas_tos/src/Field/MenuslugField.php diff --git a/src/packages/com_mokowaas/admin/src/Model/DashboardModel.php b/src/packages/com_mokowaas/admin/src/Model/DashboardModel.php index b0706f4f..fbc9ab57 100644 --- a/src/packages/com_mokowaas/admin/src/Model/DashboardModel.php +++ b/src/packages/com_mokowaas/admin/src/Model/DashboardModel.php @@ -45,6 +45,14 @@ class DashboardModel extends BaseDatabaseModel 'protected' => false, 'configure_only' => false, ], + 'mokowaas_tos' => [ + 'icon' => 'icon-globe', + 'category' => 'security', + 'label' => 'Offline Bypass', + 'description' => 'Keep selected pages (TOS, Privacy Policy) accessible during offline mode.', + 'protected' => false, + 'configure_only' => true, + ], 'mokowaas_devtools' => [ 'icon' => 'icon-wrench', 'category' => 'tools', diff --git a/src/packages/com_mokowaas/admin/src/Model/ExtensionsModel.php b/src/packages/com_mokowaas/admin/src/Model/ExtensionsModel.php index e8402f12..76e3f6fa 100644 --- a/src/packages/com_mokowaas/admin/src/Model/ExtensionsModel.php +++ b/src/packages/com_mokowaas/admin/src/Model/ExtensionsModel.php @@ -96,6 +96,16 @@ class ExtensionsModel extends BaseDatabaseModel 'article' => 'https://mokoconsulting.tech/kb/mokogallerycalendar', 'protected' => false, ], + 'MokoJoomOpenGraph' => [ + 'label' => 'MokoJoomOpenGraph', + 'description' => 'Open Graph meta tags for articles, categories, and pages. Controls Facebook, Twitter, and LinkedIn link previews.', + 'element' => 'pkg_mokoog', + 'type' => 'package', + 'icon' => 'icon-share-alt', + 'category' => 'Components', + 'article' => 'https://mokoconsulting.tech/kb/mokojoomopengraph', + 'protected' => false, + ], ]; private const GITEA_URL = 'https://git.mokoconsulting.tech'; diff --git a/src/packages/plg_system_mokowaas/Extension/MokoWaaS.php b/src/packages/plg_system_mokowaas/Extension/MokoWaaS.php index eeb32781..506b3c04 100644 --- a/src/packages/plg_system_mokowaas/Extension/MokoWaaS.php +++ b/src/packages/plg_system_mokowaas/Extension/MokoWaaS.php @@ -1424,6 +1424,7 @@ class MokoWaaS extends CMSPlugin implements BootableExtensionInterface $db->quote('mokowaas_firewall'), $db->quote('mokowaas_tenant'), $db->quote('mokowaas_devtools'), + $db->quote('mokowaas_tos'), $db->quote('mod_mokowaas_cpanel'), ]; diff --git a/src/packages/plg_system_mokowaas_tos/language/en-GB/plg_system_mokowaas_tos.ini b/src/packages/plg_system_mokowaas_tos/language/en-GB/plg_system_mokowaas_tos.ini new file mode 100644 index 00000000..7b75c1e1 --- /dev/null +++ b/src/packages/plg_system_mokowaas_tos/language/en-GB/plg_system_mokowaas_tos.ini @@ -0,0 +1,13 @@ +; MokoWaaS Terms of Service Plugin +; Copyright (C) 2026 Moko Consulting. All rights reserved. +; License: GPL-3.0-or-later + +PLG_SYSTEM_MOKOWAAS_TOS="System - MokoWaaS Offline Bypass" +PLG_SYSTEM_MOKOWAAS_TOS_DESC="Keep selected pages (Terms of Service, Privacy Policy, etc.) accessible when the site is in offline mode." + +PLG_SYSTEM_MOKOWAAS_TOS_FIELDSET_BASIC="Offline-Accessible Pages" +PLG_SYSTEM_MOKOWAAS_TOS_SLUG_LABEL="Menu Items to Keep Online" +PLG_SYSTEM_MOKOWAAS_TOS_SLUG_DESC="Select menu items that remain accessible during offline mode. Hold Ctrl/Cmd for multiple." +PLG_SYSTEM_MOKOWAAS_TOS_CHILDREN_LABEL="Include Child Menu Items" +PLG_SYSTEM_MOKOWAAS_TOS_CHILDREN_DESC="Also allow access to child pages under the selected items." +PLG_SYSTEM_MOKOWAAS_TOS_SEF_WARNING="SEF URLs are disabled - path matching requires SEF. Itemid fallback is active." diff --git a/src/packages/plg_system_mokowaas_tos/language/en-GB/plg_system_mokowaas_tos.sys.ini b/src/packages/plg_system_mokowaas_tos/language/en-GB/plg_system_mokowaas_tos.sys.ini new file mode 100644 index 00000000..cf84d46a --- /dev/null +++ b/src/packages/plg_system_mokowaas_tos/language/en-GB/plg_system_mokowaas_tos.sys.ini @@ -0,0 +1,3 @@ +; MokoWaaS Terms of Service Plugin - System strings +PLG_SYSTEM_MOKOWAAS_TOS="System - MokoWaaS Offline Bypass" +PLG_SYSTEM_MOKOWAAS_TOS_DESC="Keep selected pages (Terms of Service, Privacy Policy, etc.) accessible when the site is in offline mode." diff --git a/src/packages/plg_system_mokowaas_tos/mokowaas_tos.xml b/src/packages/plg_system_mokowaas_tos/mokowaas_tos.xml new file mode 100644 index 00000000..57ad3388 --- /dev/null +++ b/src/packages/plg_system_mokowaas_tos/mokowaas_tos.xml @@ -0,0 +1,44 @@ + + + System - MokoWaaS Offline Bypass + mokowaas_tos + Moko Consulting + 2026-06-02 + Copyright (C) 2026 Moko Consulting. All rights reserved. + GPL-3.0-or-later + hello@mokoconsulting.tech + https://mokoconsulting.tech + 02.32.00 + PLG_SYSTEM_MOKOWAAS_TOS_DESC + Moko\Plugin\System\MokoWaaSTos + + + src + services + language + + + + en-GB/plg_system_mokowaas_tos.ini + en-GB/plg_system_mokowaas_tos.sys.ini + + + + +
+ + + + + + +
+
+
+
diff --git a/src/packages/plg_system_mokowaas_tos/services/provider.php b/src/packages/plg_system_mokowaas_tos/services/provider.php new file mode 100644 index 00000000..8a7f163e --- /dev/null +++ b/src/packages/plg_system_mokowaas_tos/services/provider.php @@ -0,0 +1,34 @@ +set( + PluginInterface::class, + function (Container $container) { + $dispatcher = $container->get(DispatcherInterface::class); + $plugin = new Tos($dispatcher, (array) PluginHelper::getPlugin('system', 'mokowaas_tos')); + $plugin->setApplication(Factory::getApplication()); + + return $plugin; + } + ); + } +}; diff --git a/src/packages/plg_system_mokowaas_tos/src/Extension/Tos.php b/src/packages/plg_system_mokowaas_tos/src/Extension/Tos.php new file mode 100644 index 00000000..8ef01ed0 --- /dev/null +++ b/src/packages/plg_system_mokowaas_tos/src/Extension/Tos.php @@ -0,0 +1,172 @@ + 'onAfterRoute', + ]; + } + + public function onAfterRoute(): void + { + $app = $this->getApplication(); + + if (!$app->isClient('site')) + { + return; + } + + $config = $app->getConfig(); + + if (!$config->get('offline')) + { + return; + } + + $slugs = $this->params->get('tos_slug', []); + + if (\is_string($slugs)) + { + $slugs = array_filter([trim($slugs)]); + } + else + { + $slugs = (array) $slugs; + } + + if (empty($slugs)) + { + return; + } + + $includeChildren = (int) $this->params->get('include_children', 1); + + if ($this->matchByPath($slugs, $config, $app, $includeChildren)) + { + return; + } + + $this->matchByItemId($slugs, $config, $app, $includeChildren); + } + + private function matchByPath(array $slugs, $config, $app, int $includeChildren = 1): bool + { + $uri = Uri::getInstance(); + $path = urldecode(trim($uri->getPath(), '/')); + + $base = trim(Uri::base(true), '/'); + + if (!empty($base) && strpos($path, $base) === 0) + { + $path = trim(substr($path, \strlen($base)), '/'); + } + + if (empty($path) || $path === 'index.php') + { + return false; + } + + foreach ($slugs as $slug) + { + $slug = trim((string) $slug); + + if (empty($slug)) + { + continue; + } + + if ($path === $slug || ($includeChildren && strpos($path, $slug . '/') === 0)) + { + $this->bypassOffline($config, $app); + + return true; + } + } + + return false; + } + + private function matchByItemId(array $slugs, $config, $app, int $includeChildren = 1): bool + { + $itemId = (int) $app->getInput()->getInt('Itemid', 0); + + if (!$itemId) + { + return false; + } + + try + { + $db = Factory::getDbo(); + $query = $db->getQuery(true) + ->select($db->quoteName('path')) + ->from($db->quoteName('#__menu')) + ->where($db->quoteName('id') . ' = ' . $itemId) + ->where($db->quoteName('published') . ' = 1') + ->where($db->quoteName('client_id') . ' = 0'); + $db->setQuery($query); + $menuPath = trim((string) $db->loadResult(), '/'); + + if (empty($menuPath)) + { + return false; + } + + foreach ($slugs as $slug) + { + $slug = trim((string) $slug); + + if (empty($slug)) + { + continue; + } + + if ($menuPath === $slug || ($includeChildren && strpos($menuPath, $slug . '/') === 0)) + { + $this->bypassOffline($config, $app); + + return true; + } + } + } + catch (\Throwable $e) + { + // Silent + } + + return false; + } + + private function bypassOffline($config, $app): void + { + $config->set('offline', 0); + $app->getInput()->set('tmpl', 'component'); + } +} diff --git a/src/packages/plg_system_mokowaas_tos/src/Field/MenuslugField.php b/src/packages/plg_system_mokowaas_tos/src/Field/MenuslugField.php new file mode 100644 index 00000000..c9dd7ede --- /dev/null +++ b/src/packages/plg_system_mokowaas_tos/src/Field/MenuslugField.php @@ -0,0 +1,81 @@ +get('sef', true); + + if (!$sef) + { + $options[] = (object) [ + 'value' => '', + 'text' => Text::_('PLG_SYSTEM_MOKOWAAS_TOS_SEF_WARNING'), + 'disabled' => true, + ]; + } + } + catch (\Throwable $e) + { + // Ignore + } + + try + { + $db = Factory::getDbo(); + $query = $db->getQuery(true) + ->select($db->quoteName(['path', 'alias', 'title', 'menutype'])) + ->from($db->quoteName('#__menu')) + ->where($db->quoteName('published') . ' = 1') + ->where($db->quoteName('client_id') . ' = 0') + ->where($db->quoteName('alias') . ' != ' . $db->quote('')) + ->order($db->quoteName('menutype') . ', ' . $db->quoteName('title')); + $db->setQuery($query); + $menuItems = $db->loadObjectList(); + + $lastMenuType = ''; + + foreach ($menuItems ?: [] as $item) + { + if ($item->menutype !== $lastMenuType) + { + if ($lastMenuType !== '') + { + $options[] = (object) ['value' => '', 'text' => '──────────────', 'disabled' => true]; + } + + $lastMenuType = $item->menutype; + } + + $label = $item->title !== '' ? $item->title : ucwords(str_replace(['-', '_'], ' ', $item->alias)); + $options[] = (object) ['value' => $item->path, 'text' => $label . ' (/' . $item->path . ')']; + } + } + catch (\Throwable $e) + { + // Silent + } + + return $options; + } +} diff --git a/src/pkg_mokowaas.xml b/src/pkg_mokowaas.xml index 5e7f2cb5..9ee89893 100644 --- a/src/pkg_mokowaas.xml +++ b/src/pkg_mokowaas.xml @@ -17,6 +17,7 @@ plg_system_mokowaas_firewall.zip plg_system_mokowaas_tenant.zip plg_system_mokowaas_devtools.zip + plg_system_mokowaas_tos.zip com_mokowaas.zip mod_mokowaas_cpanel.zip plg_webservices_mokowaas.zip diff --git a/src/script.php b/src/script.php index 481deb61..7bf3d369 100644 --- a/src/script.php +++ b/src/script.php @@ -42,6 +42,7 @@ class Pkg_MokowaasInstallerScript $this->enablePlugin('system', 'mokowaas_firewall'); $this->enablePlugin('system', 'mokowaas_tenant'); $this->enablePlugin('system', 'mokowaas_devtools'); + $this->enablePlugin('system', 'mokowaas_tos'); $this->enablePlugin('webservices', 'mokowaas'); $this->enablePlugin('task', 'mokowaasdemo'); $this->enablePlugin('task', 'mokowaassync'); @@ -289,6 +290,7 @@ class Pkg_MokowaasInstallerScript $db->quote('mokowaas_firewall'), $db->quote('mokowaas_tenant'), $db->quote('mokowaas_devtools'), + $db->quote('mokowaas_tos'), $db->quote('com_mokowaas'), $db->quote('mod_mokowaas_cpanel'), $db->quote('mokowaasdemo'),