Files
pkg_circolari/site/src/Model/CircolareModel.php

269 lines
9.1 KiB
PHP

<?php
namespace Pcrt\Component\Circolari\Site\Model;
\defined('_JEXEC') or die;
use Joomla\CMS\MVC\Model\ItemModel;
use Joomla\CMS\Factory;
use Joomla\CMS\User\UserHelper;
use Joomla\CMS\Language\Text;
class CircolareModel extends ItemModel
{
protected function populateState()
{
$app = Factory::getApplication();
$id = $app->input->getInt('id', 0);
$this->setState('circolare.id', $id);
$categoria_id = $app->input->getInt('categoria_id', 0);
$this->setState('filter.categoria_id', $categoria_id);
parent::populateState();
}
public function getItem($pk = null)
{
$pk = (int) ($pk ?: $this->getState('circolare.id'));
if ($pk <= 0) {
return null;
}
$db = $this->getDatabase();
$q = $db->getQuery(true)
->select('c.*')
->from($db->quoteName('#__circolari') . ' AS c')
->where('c.id = ' . (int) $pk);
// Se esistono le colonne, applica filtri
$cols = array_change_key_case(
$db->getTableColumns($db->replacePrefix('#__circolari'), false),
CASE_LOWER
);
// categoria_id (se impostato e colonna esiste)
$categoria_id = (int) $this->getState('filter.categoria_id', 0);
if ($categoria_id > 0 && isset($cols['categoria_id'])) {
$q->where('c.categoria_id = ' . $categoria_id);
}
// stato (se colonna esiste)
if (isset($cols['state'])) {
$q->where('COALESCE(c.state, 1) = 1');
}
$db->setQuery($q);
$row = $db->loadObject();
return $row ?: null;
}
public function getBottoniFirma(int $firmatipoId): array
{
$buttons = []; // <- sempre inizializzato
if ($firmatipoId <= 0) {
return $buttons;
}
$db = Factory::getContainer()->get('DatabaseDriver');
// 1) Tabella relazionale
$q = $db->getQuery(true)
->select($db->quoteName(['id', 'label']))
->from($db->quoteName('#__circolari_firmetipi_bottoni'))
->where($db->quoteName('firmatipo_id') . ' = ' . (int) $firmatipoId)
->order($db->escape('ordering ASC, id ASC'));
$db->setQuery($q);
$buttons = (array) $db->loadObjectList();
// 2) Fallback JSON
if (!$buttons) {
$q2 = $db->getQuery(true)
->select($db->quoteName('bottoni_firma'))
->from($db->quoteName('#__circolari_firmetipi'))
->where($db->quoteName('id') . ' = ' . (int) $firmatipoId);
$db->setQuery($q2);
$json = (string) $db->loadResult();
if ($json) {
$rows = json_decode($json, true) ?: [];
foreach ($rows as $r) {
$label = trim((string) ($r['etichetta'] ?? ''));
if ($label !== '') {
$buttons[] = (object) ['id' => 0, 'label' => $label];
}
}
}
}
return $buttons;
}
public function userCanFirmare(int $circolareId, ?int $userId = null): bool
{
$user = Factory::getUser($userId);
if ($user->guest) {
return false;
}
// Gruppi (inclusa ereditarietà). In J4/J5 puoi usare UserHelper::getUserGroups
$userGroups = array_map('intval', UserHelper::getUserGroups($user->id));
if (!$userGroups) {
return false;
}
$db = Factory::getContainer()->get('DatabaseDriver');
$q = $db->getQuery(true)
->select('COUNT(*)')
->from($db->quoteName('#__circolari_usergroups'))
->where($db->quoteName('circolare_id') . ' = ' . (int) $circolareId)
->where($db->quoteName('usergroup_id') . ' IN (' . implode(',', $userGroups) . ')');
$db->setQuery($q);
return ((int) $db->loadResult()) > 0;
}
public function bottoneValidoPerCircolare(int $circolareId, int $bottoneId): bool
{
$db = Factory::getContainer()->get('DatabaseDriver');
$q = $db->getQuery(true)
->select('1')
->from($db->quoteName('#__circolari', 'c'))
->join('INNER', $db->quoteName('#__circolari_firmetipi_bottoni', 'b')
. ' ON ' . $db->quoteName('b.firmatipo_id') . ' = ' . $db->quoteName('c.tipologia_firma_id'))
->where($db->quoteName('c.id') . ' = ' . (int) $circolareId)
->where($db->quoteName('b.id') . ' = ' . (int) $bottoneId);
$db->setQuery($q, 0, 1);
return (bool) $db->loadResult();
}
public function insertFirma(int $circolareId, int $userId, int $bottoneId): bool
{
$db = Factory::getContainer()->get('DatabaseDriver');
$now = Factory::getDate()->toSql();
$ip = $_SERVER['REMOTE_ADDR'] ?? '';
$columns = ['circolare_id', 'user_id', 'firmatipo_bottone_id', 'signed_at', 'ip'];
$values = [
(int) $circolareId,
(int) $userId,
(int) $bottoneId,
$db->quote($now),
$db->quote($ip)
];
$q = $db->getQuery(true)
->insert($db->quoteName('#__circolari_firme'))
->columns($db->quoteName($columns))
->values(implode(',', $values));
try {
$db->setQuery($q)->execute();
} catch (\RuntimeException $e) {
// 1062 = duplicate key (violazione UNIQUE circolare_id+user_id)
if ((int) $e->getCode() === 1062 || stripos($e->getMessage(), 'Duplicate') !== false) {
throw new \RuntimeException(Text::_('COM_CIRCOLARI_ERR_ALREADY_SIGNED'), 409);
}
throw $e;
}
return true;
}
public function getFirmaUtente(int $circolareId, int $userId): ?object
{
if ($circolareId <= 0 || $userId <= 0) {
return null;
}
$db = Factory::getContainer()->get('DatabaseDriver');
// Schema compatibile con entrambe le versioni (ENUM "firma" oppure nuovo schema con firmatipo_bottone_id/firma_label)
$q = $db->getQuery(true)
->select($db->quoteName(['id', 'circolare_id', 'user_id']))
->select('' . $db->quoteName('firmatipo_bottone_id') . ' AS firmatipo_bottone_id')
->select('' . $db->quoteName('firma_label') . ' AS firma_label')
//->select('' . $db->quoteName('firma') . ' AS firma_enum')
->from($db->quoteName('#__circolari_firme'))
->where($db->quoteName('circolare_id') . ' = ' . (int)$circolareId)
->where($db->quoteName('user_id') . ' = ' . (int)$userId);
$db->setQuery($q, 0, 1);
$row = $db->loadObject();
return $row ?: null;
}
public function getFirmeCircolare(int $circolareId): array
{
if ($circolareId <= 0) {
return [];
}
$db = Factory::getContainer()->get('DatabaseDriver');
// Rileva le colonne della tabella firme (schema nuovo vs enum)
$cols = array_change_key_case($db->getTableColumns('#__circolari_firme', false));
$hasBtn = isset($cols['firmatipo_bottone_id']);
$hasLabel = isset($cols['firma_label']);
$hasEnum = isset($cols['firma']);
$q = $db->getQuery(true)
->select([
'f.id',
'f.circolare_id',
'f.user_id',
'f.data_firma',
($hasLabel ? 'f.firma_label' : 'NULL') . ' AS firma_label',
($hasEnum ? 'f.firma' : 'NULL') . ' AS firma_enum'
])
->from($db->quoteName('#__circolari_firme', 'f'))
->join('INNER', $db->quoteName('#__users', 'u') . ' ON u.id = f.user_id')
->select('u.name AS user_name, u.username, u.email')
->where('f.circolare_id = ' . (int) $circolareId)
->order('f.data_firma DESC');
if ($hasBtn) {
$q->select('b.label AS bottone_label')
->join('LEFT', $db->quoteName('#__circolari_firmetipi_bottoni', 'b') . ' ON b.id = f.firmatipo_bottone_id');
} else {
$q->select('NULL AS bottone_label');
}
$db->setQuery($q);
$rows = (array) $db->loadAssocList();
// Post-processing: normalizza la label scelta
foreach ($rows as &$r) {
$label = $r['firma_label'] ?: $r['bottone_label'] ?: $r['firma_enum'];
if ($label && $label === $r['firma_enum']) {
$label = ucwords(str_replace('_', ' ', $label)); // enum -> "Presa Visione"
}
$r['scelta_label'] = $label ?: '-';
}
unset($r);
return $rows;
}
/**
* Incrementa gli hits della circolare.
*/
public function hit($pk = null)
{
$pk = $pk ?: (int) $this->getState($this->getName() . '.id');
if (!$pk) {
return false;
}
$db = $this->getDatabase();
$query = $db->getQuery(true)
->update($db->quoteName('#__circolari'))
->set($db->quoteName('hits') . ' = ' . $db->quoteName('hits') . ' + 1')
->where($db->quoteName('id') . ' = ' . (int)$pk);
$db->setQuery($query)->execute();
return true;
}
}