| Current Path : /var/www/html/libraries/noboss/src/Util/ |
| Current File : /var/www/html/libraries/noboss/src/Util/NbModuleParamsUtil.php |
<?php
/**
* @package No Boss Extensions
* @subpackage No Boss Library
* @author No Boss Technology <contact@nobosstechnology.com>
* @copyright Copyright (C) 2026 No Boss Technology. All rights reserved.
* @license GNU Lesser General Public License version 3 or later; see <https://www.gnu.org/licenses/lgpl-3.0.en.html>
*/
namespace Noboss\Library\Util;
use Joomla\CMS\Factory;
use Joomla\Database\DatabaseInterface;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Utilitário para exportar e importar os parâmetros (coluna `params`) de instâncias de módulo.
*
* Permite copiar configurações de um módulo para outro — inclusive entre sites diferentes.
*
* Endpoints via com_nobossajax:
* GET index.php?option=com_nobossajax&library=noboss.src.Util.NbModuleParamsUtil&method=exportModuleParams&id_module=X&format=raw
* POST index.php?option=com_nobossajax&library=noboss.src.Util.NbModuleParamsUtil&method=importModuleParams&format=raw
*/
class NbModuleParamsUtil
{
/**
* Verifica se o usuário está autenticado e tem permissão administrativa.
* Em caso negativo, emite JSON de erro e encerra a execução.
*/
private static function requireAdminUser(): void
{
header('Content-Type: application/json; charset=utf-8');
$user = Factory::getApplication()->getIdentity();
if ($user->guest) {
http_response_code(401);
echo json_encode(['success' => false, 'message' => 'Authentication required.']);
exit;
}
if (!$user->authorise('core.admin') && !in_array(8, $user->groups, true)) {
http_response_code(403);
echo json_encode(['success' => false, 'message' => 'Access denied: administrator permission required.']);
exit;
}
}
/**
* Exporta a coluna `params` de um módulo como arquivo JSON para download.
*
* Parâmetros GET:
* - id_module (int, obrigatório): ID da linha em #__modules
*
* O arquivo gerado pode ser reimportado diretamente por importModuleParams().
*/
public static function exportModuleParams(): void
{
self::requireAdminUser();
$input = Factory::getApplication()->input;
$idModule = $input->getInt('id_module', 0);
if ($idModule <= 0) {
http_response_code(400);
echo json_encode(['success' => false, 'message' => 'Missing required parameter: id_module.']);
exit;
}
$db = Factory::getContainer()->get(DatabaseInterface::class);
$query = $db->getQuery(true)
->select($db->quoteName(['id', 'title', 'module', 'params']))
->from($db->quoteName('#__modules'))
->where($db->quoteName('id') . ' = ' . $idModule);
$db->setQuery($query);
$row = $db->loadObject();
if (empty($row)) {
http_response_code(404);
echo json_encode(['success' => false, 'message' => 'Module not found (id=' . $idModule . ').']);
exit;
}
$params = json_decode($row->params);
if ($params === null && $row->params !== '' && $row->params !== 'null') {
http_response_code(500);
echo json_encode(['success' => false, 'message' => 'The module params column does not contain valid JSON.']);
exit;
}
// Envelope com metadados para facilitar identificação no momento da importação
$export = [
'_nb_layout_export' => true,
'_module' => $row->module,
'_module_id' => (int) $row->id,
'_module_title' => $row->title,
'_exported_at' => date('Y-m-d H:i:s'),
'params' => $params ?? new \stdClass(),
];
$filename = $row->module . '_id' . $row->id . '_layout_' . date('Ymd_His') . '.json';
header('Content-Type: application/json; charset=utf-8');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');
echo json_encode($export, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
exit;
}
/**
* Importa um arquivo de layout JSON e salva na coluna `params` do módulo indicado.
*
* Parâmetros POST:
* - id_module (int, obrigatório): ID da linha em #__modules que receberá os dados
* - json_content (string, obrigatório): conteúdo JSON bruto do arquivo exportado
*
* Validações:
* 1. JSON válido
* 2. Raiz deve ser um objeto (não primitivo, não array simples sem chaves de string)
* 3. Pelo menos uma chave presente
*
* Retorna JSON: { success: bool, message: string }
*/
public static function importModuleParams(): void
{
self::requireAdminUser();
$input = Factory::getApplication()->input;
$idModule = $input->getInt('id_module', 0);
$jsonContent = $input->post->getRaw('json_content', '');
if ($idModule <= 0) {
echo json_encode(['success' => false, 'message' => 'Missing required parameter: id_module.']);
exit;
}
if (empty(trim($jsonContent))) {
echo json_encode(['success' => false, 'message' => 'No JSON content received.']);
exit;
}
// Valida o JSON recebido
$decoded = json_decode($jsonContent, true);
if (json_last_error() !== JSON_ERROR_NONE) {
echo json_encode([
'success' => false,
'message' => 'Invalid file: not valid JSON. Error: ' . json_last_error_msg(),
]);
exit;
}
// A raiz deve ser um objeto associativo (array com chaves string no PHP)
if (!is_array($decoded)) {
echo json_encode([
'success' => false,
'message' => 'Invalid structure: the JSON root must be an object, not a primitive value.',
]);
exit;
}
// Detecta envelope gerado por exportModuleParams() e extrai apenas a chave params
if (isset($decoded['_nb_layout_export'], $decoded['params']) && $decoded['_nb_layout_export'] === true) {
$paramsToSave = $decoded['params'];
if (!is_array($paramsToSave) && !is_object($paramsToSave)) {
echo json_encode([
'success' => false,
'message' => 'Invalid file: the "params" key inside the exported file is not an object.',
]);
exit;
}
} else {
// Aceita também um objeto de params puro (sem envelope)
$paramsToSave = $decoded;
}
if (empty($paramsToSave)) {
echo json_encode([
'success' => false,
'message' => 'The JSON contains no parameters to import (empty object).',
]);
exit;
}
// Confirma que o módulo existe no banco
$db = Factory::getContainer()->get(DatabaseInterface::class);
$query = $db->getQuery(true)
->select($db->quoteName('id'))
->from($db->quoteName('#__modules'))
->where($db->quoteName('id') . ' = ' . $idModule);
$db->setQuery($query);
$existingId = $db->loadResult();
if (empty($existingId)) {
echo json_encode([
'success' => false,
'message' => 'Module with id=' . $idModule . ' was not found in the database.',
]);
exit;
}
// Serializa de volta para string JSON, como o Joomla espera na coluna params
$paramsJson = json_encode($paramsToSave, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$query = $db->getQuery(true)
->update($db->quoteName('#__modules'))
->set($db->quoteName('params') . ' = ' . $db->quote($paramsJson))
->where($db->quoteName('id') . ' = ' . $idModule);
$db->setQuery($query);
if (!$db->execute()) {
echo json_encode([
'success' => false,
'message' => 'Database error: could not save the layout.',
]);
exit;
}
echo json_encode([
'success' => true,
'message' => 'Layout imported successfully! Reload the page to see the changes.',
]);
exit;
}
}