00d44256b4
Rebrand all 17 sub-extensions from mokowaas to mokosuite naming, including component, plugins, modules, task plugins, and webservices. Updates package manifest, workflows, docs, wiki, and issue templates. Adds new plg_system_mokosuite_license extension.
188 lines
5.0 KiB
PHP
188 lines
5.0 KiB
PHP
<?php
|
|
/**
|
|
* @package MokoSuite
|
|
* @subpackage com_mokosuite
|
|
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
|
* @license GNU General Public License version 3 or later; see LICENSE
|
|
*/
|
|
|
|
namespace Moko\Component\MokoSuite\Api\Controller;
|
|
|
|
defined('_JEXEC') or die;
|
|
|
|
use Joomla\CMS\Factory;
|
|
use Joomla\CMS\MVC\Controller\BaseController;
|
|
|
|
/**
|
|
* Extensions list API controller.
|
|
*
|
|
* GET /api/index.php/v1/mokosuite/extensions
|
|
*
|
|
* Returns all installed extensions with type, element, folder, version,
|
|
* enabled/protected/locked status, and update server info.
|
|
*
|
|
* Optional filters via query params:
|
|
* ?type=plugin — filter by extension type
|
|
* ?search=moko — search name or element
|
|
* ?enabled=1 — only enabled/disabled
|
|
*
|
|
* @since 02.21.00
|
|
*/
|
|
class ExtensionsController extends BaseController
|
|
{
|
|
/**
|
|
* List installed extensions.
|
|
*
|
|
* @return void
|
|
*
|
|
* @since 02.21.00
|
|
*/
|
|
public function displayList(): void
|
|
{
|
|
$app = Factory::getApplication();
|
|
$user = $app->getIdentity();
|
|
|
|
if (!$user->authorise('core.manage', 'com_installer'))
|
|
{
|
|
$this->sendJson(403, ['error' => 'Not authorized — requires core.manage on com_installer']);
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
$db = Factory::getDbo();
|
|
$query = $db->getQuery(true)
|
|
->select([
|
|
$db->quoteName('e.extension_id'),
|
|
$db->quoteName('e.name'),
|
|
$db->quoteName('e.type'),
|
|
$db->quoteName('e.element'),
|
|
$db->quoteName('e.folder'),
|
|
$db->quoteName('e.client_id'),
|
|
$db->quoteName('e.enabled'),
|
|
$db->quoteName('e.protected'),
|
|
$db->quoteName('e.locked'),
|
|
$db->quoteName('e.manifest_cache'),
|
|
])
|
|
->from($db->quoteName('#__extensions', 'e'))
|
|
->order($db->quoteName('e.type') . ' ASC, ' . $db->quoteName('e.name') . ' ASC');
|
|
|
|
// Filter by type
|
|
$typeFilter = $app->input->get('type', '', 'CMD');
|
|
|
|
if ($typeFilter !== '')
|
|
{
|
|
$query->where($db->quoteName('e.type') . ' = ' . $db->quote($typeFilter));
|
|
}
|
|
|
|
// Filter by enabled
|
|
$enabledFilter = $app->input->get('enabled', '', 'CMD');
|
|
|
|
if ($enabledFilter !== '')
|
|
{
|
|
$query->where($db->quoteName('e.enabled') . ' = ' . (int) $enabledFilter);
|
|
}
|
|
|
|
// Search name or element
|
|
$search = $app->input->get('search', '', 'STRING');
|
|
|
|
if ($search !== '')
|
|
{
|
|
$searchQuoted = $db->quote('%' . $db->escape($search, true) . '%');
|
|
$query->where(
|
|
'(' . $db->quoteName('e.name') . ' LIKE ' . $searchQuoted
|
|
. ' OR ' . $db->quoteName('e.element') . ' LIKE ' . $searchQuoted . ')'
|
|
);
|
|
}
|
|
|
|
$db->setQuery($query);
|
|
$rows = $db->loadAssocList();
|
|
|
|
// Get update sites for cross-reference
|
|
$usQuery = $db->getQuery(true)
|
|
->select([
|
|
$db->quoteName('us.update_site_id'),
|
|
$db->quoteName('us.name', 'site_name'),
|
|
$db->quoteName('us.location'),
|
|
$db->quoteName('us.enabled', 'site_enabled'),
|
|
$db->quoteName('usm.extension_id'),
|
|
])
|
|
->from($db->quoteName('#__update_sites', 'us'))
|
|
->innerJoin(
|
|
$db->quoteName('#__update_sites_extensions', 'usm')
|
|
. ' ON ' . $db->quoteName('us.update_site_id')
|
|
. ' = ' . $db->quoteName('usm.update_site_id')
|
|
);
|
|
$db->setQuery($usQuery);
|
|
$updateSites = [];
|
|
|
|
foreach ($db->loadAssocList() ?: [] as $us)
|
|
{
|
|
$updateSites[(int) $us['extension_id']] = [
|
|
'name' => $us['site_name'],
|
|
'location' => $us['location'],
|
|
'enabled' => (bool) $us['site_enabled'],
|
|
];
|
|
}
|
|
|
|
// Build response
|
|
$extensions = [];
|
|
|
|
foreach ($rows as $row)
|
|
{
|
|
$manifest = json_decode($row['manifest_cache'] ?: '{}', true);
|
|
$extId = (int) $row['extension_id'];
|
|
|
|
$ext = [
|
|
'extension_id' => $extId,
|
|
'name' => $row['name'],
|
|
'type' => $row['type'],
|
|
'element' => $row['element'],
|
|
'folder' => $row['folder'] ?: null,
|
|
'client_id' => (int) $row['client_id'],
|
|
'enabled' => (bool) $row['enabled'],
|
|
'protected' => (bool) $row['protected'],
|
|
'locked' => (bool) $row['locked'],
|
|
'version' => $manifest['version'] ?? null,
|
|
'author' => $manifest['author'] ?? null,
|
|
'description' => $manifest['description'] ?? null,
|
|
];
|
|
|
|
if (isset($updateSites[$extId]))
|
|
{
|
|
$ext['update_server'] = $updateSites[$extId];
|
|
}
|
|
|
|
$extensions[] = $ext;
|
|
}
|
|
|
|
$this->sendJson(200, [
|
|
'status' => 'ok',
|
|
'count' => count($extensions),
|
|
'extensions' => $extensions,
|
|
]);
|
|
}
|
|
catch (\Throwable $e)
|
|
{
|
|
$this->sendJson(500, [
|
|
'error' => 'Failed to list extensions',
|
|
'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_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
|
|
$app->close();
|
|
}
|
|
}
|