feat: convert to package with webservices API + heartbeat fix #31

Merged
jmiller merged 13 commits from dev into main 2026-05-24 04:10:09 +00:00
43 changed files with 1772 additions and 1176 deletions
+2 -2
View File
@@ -15,7 +15,7 @@
DEFGROUP: Joomla.Plugin
INGROUP: MokoWaaS
REPO: https://github.com/mokoconsulting-tech/mokowaas
VERSION: 02.01.43
VERSION: 02.03.02
PATH: /README.md
BRIEF: Rebranding plugin for MokoWaaS platform
NOTE: Internal WaaS identity abstraction layer
@@ -23,7 +23,7 @@
# MokoWaaS Plugin
[![Version](https://img.shields.io/badge/version-02.01.43-blue.svg?logo=v&logoColor=white)](https://github.com/mokoconsulting-tech/MokoWaaS/releases/tag/v02)
[![Version](https://img.shields.io/badge/version-02.03.00-blue.svg?logo=v&logoColor=white)](https://github.com/mokoconsulting-tech/MokoWaaS/releases/tag/v02)
[![License](https://img.shields.io/badge/license-GPL--3.0--or--later-green.svg?logo=gnu&logoColor=white)](LICENSE)
[![Joomla](https://img.shields.io/badge/Joomla-5.x%20%7C%206.x-red.svg?logo=joomla&logoColor=white)](https://www.joomla.org)
[![PHP](https://img.shields.io/badge/PHP-8.1%2B-777BB4.svg?logo=php&logoColor=white)](https://www.php.net)
@@ -0,0 +1,38 @@
<?php
/**
* @package MokoWaaS
* @subpackage com_mokowaas
* @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\Dispatcher\ComponentDispatcherFactoryInterface;
use Joomla\CMS\Extension\ComponentInterface;
use Joomla\CMS\Extension\Service\Provider\ComponentDispatcherFactory;
use Joomla\CMS\Extension\Service\Provider\MVCFactory;
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
return new class implements ServiceProviderInterface
{
public function register(Container $container): void
{
$container->registerServiceProvider(new MVCFactory('\\Moko\\Component\\MokoWaaS'));
$container->registerServiceProvider(new ComponentDispatcherFactory('\\Moko\\Component\\MokoWaaS'));
$container->set(
ComponentInterface::class,
function (Container $container) {
$component = new \Joomla\CMS\Extension\MVCComponent(
$container->get(ComponentDispatcherFactoryInterface::class)
);
$component->setMVCFactory($container->get(MVCFactoryInterface::class));
return $component;
}
);
}
};
@@ -0,0 +1,89 @@
<?php
/**
* @package MokoWaaS
* @subpackage com_mokowaas
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
* @license GNU General Public License version 3 or later; see LICENSE
*/
namespace Moko\Component\MokoWaaS\Api\Controller;
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\MVC\Controller\BaseController;
/**
* Cache management API controller.
*
* POST /api/index.php/v1/mokowaas/cache
*
* @since 1.0.0
*/
class CacheController extends BaseController
{
/**
* Clear all Joomla caches.
*
* @return void
*
* @since 1.0.0
*/
public function execute(): void
{
$app = Factory::getApplication();
if ($app->input->getMethod() !== 'POST')
{
$this->sendJson(405, ['error' => 'POST required']);
return;
}
$user = $app->getIdentity();
if (!$user->authorise('core.manage', 'com_plugins'))
{
$this->sendJson(403, ['error' => 'Not authorized']);
return;
}
try
{
$cache = Factory::getCache('');
$cache->clean('');
$adminCache = Factory::getCache('', 'callback', 'administrator');
$adminCache->clean('');
if (function_exists('opcache_reset'))
{
opcache_reset();
}
$this->sendJson(200, [
'status' => 'ok',
'message' => 'Cache cleared',
]);
}
catch (\Throwable $e)
{
$this->sendJson(500, [
'error' => 'Cache clear failed',
'message' => $e->getMessage(),
]);
}
}
/**
* @param int $code HTTP status code
* @param array $payload Response data
* @return void
*/
private function sendJson(int $code, array $payload): void
{
$app = Factory::getApplication();
$app->setHeader('Content-Type', 'application/json', true);
$app->setHeader('Status', (string) $code, true);
echo json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
$app->close();
}
}
@@ -0,0 +1,139 @@
<?php
/**
* @package MokoWaaS
* @subpackage com_mokowaas
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
* @license GNU General Public License version 3 or later; see LICENSE
*/
namespace Moko\Component\MokoWaaS\Api\Controller;
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\MVC\Controller\BaseController;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\Uri\Uri;
use Joomla\Registry\Registry;
/**
* Health check API controller.
*
* GET /api/index.php/v1/mokowaas/health
*
* Returns full health diagnostics from the MokoWaaS system plugin.
* Requires a Joomla API token with core.manage permissions.
*
* @since 1.0.0
*/
class HealthController extends BaseController
{
/**
* Return full health check data.
*
* @return void
*
* @since 1.0.0
*/
public function displayList(): void
{
$app = Factory::getApplication();
$user = $app->getIdentity();
if (!$user->authorise('core.manage', 'com_plugins'))
{
$this->sendJson(403, ['error' => 'Not authorized']);
return;
}
$plugin = PluginHelper::getPlugin('system', 'mokowaas');
if (!$plugin)
{
$this->sendJson(503, ['error' => 'MokoWaaS system plugin not enabled']);
return;
}
$params = new Registry($plugin->params);
$config = Factory::getConfig();
$db = Factory::getDbo();
// Collect basic health data
$payload = [
'status' => 'ok',
'timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
'site' => [
'name' => $config->get('sitename', ''),
'url' => rtrim(Uri::root(), '/'),
'joomla_version' => JVERSION,
'php_version' => PHP_VERSION,
'db_type' => $db->getName(),
'offline' => (bool) $config->get('offline', 0),
'debug' => (bool) $config->get('debug', 0),
'sef' => (bool) $config->get('sef', 0),
'caching' => (bool) $config->get('caching', 0),
],
'plugin' => [
'brand' => $params->get('brand_name', 'MokoWaaS'),
'company' => $params->get('company_name', 'Moko Consulting'),
],
];
// Database check
try
{
$db->setQuery('SELECT 1');
$db->loadResult();
$payload['checks']['database'] = ['status' => 'ok'];
}
catch (\Throwable $e)
{
$payload['status'] = 'error';
$payload['checks']['database'] = ['status' => 'error', 'message' => $e->getMessage()];
}
// Disk space
$free = @disk_free_space(JPATH_ROOT);
$total = @disk_total_space(JPATH_ROOT);
if ($free !== false && $total !== false)
{
$freeMb = round($free / 1048576);
$payload['checks']['filesystem'] = [
'status' => $freeMb < 100 ? 'degraded' : 'ok',
'free_disk_mb' => $freeMb,
'total_disk_mb' => round($total / 1048576),
];
}
// Content counts
$db->setQuery($db->getQuery(true)->select('COUNT(*)')->from($db->quoteName('#__content')));
$payload['counts']['articles'] = (int) $db->loadResult();
$db->setQuery($db->getQuery(true)->select('COUNT(*)')->from($db->quoteName('#__users')));
$payload['counts']['users'] = (int) $db->loadResult();
$db->setQuery($db->getQuery(true)->select('COUNT(*)')->from($db->quoteName('#__extensions'))->where($db->quoteName('enabled') . ' = 1'));
$payload['counts']['extensions'] = (int) $db->loadResult();
$this->sendJson(200, $payload);
}
/**
* Send a JSON response and close.
*
* @param int $code HTTP status code
* @param array $payload Response data
*
* @return void
*
* @since 1.0.0
*/
private function sendJson(int $code, array $payload): void
{
$app = Factory::getApplication();
$app->setHeader('Content-Type', 'application/json', true);
$app->setHeader('Status', (string) $code, true);
echo json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
$app->close();
}
}
@@ -0,0 +1,94 @@
<?php
/**
* @package MokoWaaS
* @subpackage com_mokowaas
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
* @license GNU General Public License version 3 or later; see LICENSE
*/
namespace Moko\Component\MokoWaaS\Api\Controller;
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\MVC\Controller\BaseController;
/**
* Update check API controller.
*
* POST /api/index.php/v1/mokowaas/update
*
* @since 1.0.0
*/
class UpdateController extends BaseController
{
/**
* Trigger Joomla update finder and return count of available updates.
*
* @return void
*
* @since 1.0.0
*/
public function execute(): void
{
$app = Factory::getApplication();
if ($app->input->getMethod() !== 'POST')
{
$this->sendJson(405, ['error' => 'POST required']);
return;
}
$user = $app->getIdentity();
if (!$user->authorise('core.manage', 'com_installer'))
{
$this->sendJson(403, ['error' => 'Not authorized']);
return;
}
try
{
$db = Factory::getDbo();
$db->setQuery($db->getQuery(true)->delete($db->quoteName('#__updates')));
$db->execute();
\Joomla\CMS\Updater\Updater::getInstance()->findUpdates();
$db->setQuery(
$db->getQuery(true)
->select('COUNT(*)')
->from($db->quoteName('#__updates'))
->where($db->quoteName('extension_id') . ' != 0')
);
$count = (int) $db->loadResult();
$this->sendJson(200, [
'status' => 'ok',
'updates_found' => $count,
'message' => $count . ' update(s) available',
]);
}
catch (\Throwable $e)
{
$this->sendJson(500, [
'error' => 'Update check failed',
'message' => $e->getMessage(),
]);
}
}
/**
* @param int $code HTTP status code
* @param array $payload Response data
* @return void
*/
private function sendJson(int $code, array $payload): void
{
$app = Factory::getApplication();
$app->setHeader('Content-Type', 'application/json', true);
$app->setHeader('Status', (string) $code, true);
echo json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
$app->close();
}
}
+23
View File
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<extension type="component" method="upgrade">
<name>MokoWaaS API</name>
<author>Moko Consulting</author>
<creationDate>2026-05-23</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>01.00.00</version>
<description>Minimal API-only component for MokoWaaS. Provides REST endpoints for site health, cache, updates, and backups.</description>
<namespace path="api/src">Moko\Component\MokoWaaS\Api</namespace>
<administration>
<files folder="admin">
<folder>services</folder>
</files>
</administration>
<api>
<files folder="api">
<folder>src</folder>
</files>
</api>
</extension>

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before

Width:  |  Height:  |  Size: 137 KiB

After

Width:  |  Height:  |  Size: 137 KiB

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 KiB

@@ -30,7 +30,7 @@
<license>GNU General Public License version 3 or later; see LICENSE.md</license>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
<authorUrl>https://mokoconsulting.tech</authorUrl>
<version>02.01.43</version>
<version>02.03.00</version>
<description>This plugin rebrands the Joomla system interface with MokoWaaS identity. It applies language overrides and ensures consistent branding across the platform.</description>
<namespace path=".">Moko\Plugin\System\MokoWaaS</namespace>
<scriptfile>script.php</scriptfile>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<extension type="plugin" group="webservices" method="upgrade">
<name>Web Services - MokoWaaS</name>
<author>Moko Consulting</author>
<creationDate>2026-05-23</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>01.00.00</version>
<description>Joomla Web Services API routes for MokoWaaS site management — health checks, cache, updates, backups, and site info.</description>
<namespace path="src">Moko\Plugin\WebServices\MokoWaaS</namespace>
<files>
<folder plugin="mokowaas">services</folder>
<folder>src</folder>
</files>
</extension>
@@ -0,0 +1,36 @@
<?php
/**
* @package MokoWaaS
* @subpackage plg_webservices_mokowaas
* @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\WebServices\MokoWaaS\Extension\MokoWaaSApi;
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 MokoWaaSApi(
$dispatcher,
(array) PluginHelper::getPlugin('webservices', 'mokowaas')
);
$plugin->setApplication(Factory::getApplication());
return $plugin;
}
);
}
};
@@ -0,0 +1,65 @@
<?php
/**
* @package MokoWaaS
* @subpackage plg_webservices_mokowaas
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
* @license GNU General Public License version 3 or later; see LICENSE
*/
namespace Moko\Plugin\WebServices\MokoWaaS\Extension;
defined('_JEXEC') or die;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Router\ApiRouter;
use Joomla\Event\SubscriberInterface;
/**
* MokoWaaS Web Services API Plugin
*
* Registers REST API routes for MokoWaaS site management endpoints.
*
* @since 1.0.0
*/
final class MokoWaaSApi extends CMSPlugin implements SubscriberInterface
{
/**
* @return array
*/
public static function getSubscribedEvents(): array
{
return [
'onBeforeApiRoute' => 'onBeforeApiRoute',
];
}
/**
* Register API routes for MokoWaaS.
*
* @param ApiRouter $router The API router
*
* @return void
*
* @since 1.0.0
*/
public function onBeforeApiRoute(&$router): void
{
$router->createCRUDRoutes(
'v1/mokowaas/health',
'health',
['component' => 'com_mokowaas']
);
$router->createCRUDRoutes(
'v1/mokowaas/cache',
'cache',
['component' => 'com_mokowaas']
);
$router->createCRUDRoutes(
'v1/mokowaas/update',
'update',
['component' => 'com_mokowaas']
);
}
}
Binary file not shown.
+24
View File
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<extension type="package" method="upgrade">
<name>MokoWaaS</name>
<packagename>mokowaas</packagename>
<version>02.03.02</version>
<creationDate>2026-05-23</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
<authorUrl>https://mokoconsulting.tech</authorUrl>
<copyright>Copyright (C) 2026 Moko Consulting. All rights reserved.</copyright>
<license>GNU General Public License version 3 or later; see LICENSE</license>
<description>MokoWaaS site management suite — branding, health monitoring, tenant restrictions, and REST API.</description>
<scriptfile>script.php</scriptfile>
<files>
<file type="plugin" id="plg_system_mokowaas" group="system">plg_system_mokowaas.zip</file>
<file type="component" id="com_mokowaas">com_mokowaas.zip</file>
<file type="plugin" id="plg_webservices_mokowaas" group="webservices">plg_webservices_mokowaas.zip</file>
</files>
<updateservers>
<server type="extension" priority="1" name="MokoWaaS Update Server">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/raw/branch/main/updates.xml</server>
</updateservers>
</extension>
+42 -1161
View File
File diff suppressed because it is too large Load Diff
+11 -12
View File
@@ -23,21 +23,20 @@
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
</update>
<update>
<name>System - MokoWaaS</name>
<description>System - MokoWaaS update (development)</description>
<element>mokowaas</element>
<type>plugin</type>
<version>02.01.44-dev</version>
<client>site</client>
<folder>system</folder>
<tags><tag>development</tag></tags>
<infourl title="System - MokoWaaS">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/development</infourl>
<name>MokoWaaS</name>
<description>MokoWaaS development build.</description>
<element>pkg_mokowaas</element>
<type>package</type>
<version>02.01.46</version>
<creationDate>2026-05-24</creationDate>
<infourl title='MokoWaaS'>https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/development</infourl>
<downloads>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/development/plg_system_mokowaas-02.01.44-dev.zip</downloadurl>
<downloadurl type='full' format='zip'>https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/development/pkg_mokowaas-02.01.46-dev.zip</downloadurl>
</downloads>
<sha256>134158cce6b179a68477f35400f54e21f336bceae7b4a6197af3cb80db458a5a</sha256>
<targetplatform name="joomla" version="((5.[0-9])|(6.[0-9]))" />
<sha256>2b0f59fa377f1563a54b2fbb389cee50225865541b0d3afecb565032f2afcb3c</sha256>
<tags><tag>development</tag></tags>
<maintainer>Moko Consulting</maintainer>
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
<targetplatform name='joomla' version='(5|6).*'/>
</update>
</updates>