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) <noreply@anthropic.com>
This commit is contained in:
@@ -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',
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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'),
|
||||
];
|
||||
|
||||
|
||||
@@ -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."
|
||||
@@ -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."
|
||||
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<extension type="plugin" group="system" method="upgrade">
|
||||
<name>System - MokoWaaS Offline Bypass</name>
|
||||
<element>mokowaas_tos</element>
|
||||
<author>Moko Consulting</author>
|
||||
<creationDate>2026-06-02</creationDate>
|
||||
<copyright>Copyright (C) 2026 Moko Consulting. All rights reserved.</copyright>
|
||||
<license>GPL-3.0-or-later</license>
|
||||
<authorEmail>hello@mokoconsulting.tech</authorEmail>
|
||||
<authorUrl>https://mokoconsulting.tech</authorUrl>
|
||||
<version>02.32.00</version>
|
||||
<description>PLG_SYSTEM_MOKOWAAS_TOS_DESC</description>
|
||||
<namespace path="src">Moko\Plugin\System\MokoWaaSTos</namespace>
|
||||
|
||||
<files>
|
||||
<folder>src</folder>
|
||||
<folder>services</folder>
|
||||
<folder>language</folder>
|
||||
</files>
|
||||
|
||||
<languages folder="language">
|
||||
<language tag="en-GB">en-GB/plg_system_mokowaas_tos.ini</language>
|
||||
<language tag="en-GB">en-GB/plg_system_mokowaas_tos.sys.ini</language>
|
||||
</languages>
|
||||
|
||||
<config>
|
||||
<fields name="params" addfieldprefix="Moko\Plugin\System\MokoWaaSTos\Field">
|
||||
<fieldset name="basic" label="PLG_SYSTEM_MOKOWAAS_TOS_FIELDSET_BASIC">
|
||||
<field name="tos_slug" type="menuslug"
|
||||
label="PLG_SYSTEM_MOKOWAAS_TOS_SLUG_LABEL"
|
||||
description="PLG_SYSTEM_MOKOWAAS_TOS_SLUG_DESC"
|
||||
multiple="true" />
|
||||
|
||||
<field name="include_children" type="radio" default="1"
|
||||
label="PLG_SYSTEM_MOKOWAAS_TOS_CHILDREN_LABEL"
|
||||
description="PLG_SYSTEM_MOKOWAAS_TOS_CHILDREN_DESC"
|
||||
class="btn-group btn-group-yesno">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
</fieldset>
|
||||
</fields>
|
||||
</config>
|
||||
</extension>
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
* @package MokoWaaS
|
||||
* @subpackage plg_system_mokowaas_tos
|
||||
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
* @license GNU General Public License version 3 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Extension\PluginInterface;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
use Joomla\Event\DispatcherInterface;
|
||||
use Moko\Plugin\System\MokoWaaSTos\Extension\Tos;
|
||||
|
||||
return new class implements ServiceProviderInterface
|
||||
{
|
||||
public function register(Container $container): void
|
||||
{
|
||||
$container->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;
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,172 @@
|
||||
<?php
|
||||
/**
|
||||
* @package MokoWaaS
|
||||
* @subpackage plg_system_mokowaas_tos
|
||||
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
* @license GNU General Public License version 3 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Moko\Plugin\System\MokoWaaSTos\Extension;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Plugin\CMSPlugin;
|
||||
use Joomla\CMS\Uri\Uri;
|
||||
use Joomla\Event\SubscriberInterface;
|
||||
|
||||
/**
|
||||
* MokoWaaS Terms of Service Plugin
|
||||
*
|
||||
* Allows configured menu items (Terms of Service, Privacy Policy, etc.)
|
||||
* to remain accessible when the site is in offline mode.
|
||||
*
|
||||
* @since 02.32.00
|
||||
*/
|
||||
final class Tos extends CMSPlugin implements SubscriberInterface
|
||||
{
|
||||
protected $autoloadLanguage = true;
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'onAfterRoute' => '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');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* @package MokoWaaS
|
||||
* @subpackage plg_system_mokowaas_tos
|
||||
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
||||
* @license GNU General Public License version 3 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Moko\Plugin\System\MokoWaaSTos\Field;
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Field\ListField;
|
||||
use Joomla\CMS\Language\Text;
|
||||
|
||||
class MenuslugField extends ListField
|
||||
{
|
||||
protected $type = 'Menuslug';
|
||||
|
||||
protected function getOptions()
|
||||
{
|
||||
$options = parent::getOptions();
|
||||
|
||||
try
|
||||
{
|
||||
$sef = Factory::getApplication()->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;
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
<file type="plugin" id="plg_system_mokowaas_firewall" group="system">plg_system_mokowaas_firewall.zip</file>
|
||||
<file type="plugin" id="plg_system_mokowaas_tenant" group="system">plg_system_mokowaas_tenant.zip</file>
|
||||
<file type="plugin" id="plg_system_mokowaas_devtools" group="system">plg_system_mokowaas_devtools.zip</file>
|
||||
<file type="plugin" id="plg_system_mokowaas_tos" group="system">plg_system_mokowaas_tos.zip</file>
|
||||
<file type="component" id="com_mokowaas">com_mokowaas.zip</file>
|
||||
<file type="module" id="mod_mokowaas_cpanel" client="administrator">mod_mokowaas_cpanel.zip</file>
|
||||
<file type="plugin" id="plg_webservices_mokowaas" group="webservices">plg_webservices_mokowaas.zip</file>
|
||||
|
||||
@@ -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'),
|
||||
|
||||
Reference in New Issue
Block a user