Campi obbligatori & fix
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace Pcrt\Component\Circolari\Site\Controller;
|
||||
|
||||
\defined('_JEXEC') or die;
|
||||
@ -26,6 +27,10 @@ class DisplayController extends BaseController
|
||||
}
|
||||
}
|
||||
|
||||
if (!in_array($view, ['circolari', 'circolare', 'form'])) {
|
||||
$this->input->set('view', $this->default_view);
|
||||
}
|
||||
|
||||
return parent::display($cachable, $urlparams);
|
||||
}
|
||||
}
|
||||
|
||||
84
site/src/Controller/FormController.php
Normal file
84
site/src/Controller/FormController.php
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
namespace Pcrt\Component\Circolari\Site\Controller;
|
||||
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Session\Session;
|
||||
|
||||
class FormController extends BaseController
|
||||
{
|
||||
public function display($cachable = false, $urlparams = [])
|
||||
{
|
||||
// Solo utenti autenticati + permesso admin/manage
|
||||
$app = Factory::getApplication();
|
||||
$user = $app->getIdentity();
|
||||
if ($user->guest || (!$user->authorise('core.manage', 'com_circolari') && !$user->authorise('core.admin', 'com_circolari'))) {
|
||||
throw new \RuntimeException(Text::_('JERROR_ALERTNOAUTHOR'), 403);
|
||||
}
|
||||
|
||||
$view = $this->input->getCmd('view', 'form');
|
||||
$layout = $this->input->getCmd('layout', 'edit');
|
||||
$id = $this->input->getInt('id');
|
||||
|
||||
$this->input->set('view', $view);
|
||||
$this->input->set('layout', $layout);
|
||||
$this->input->set('id', $id);
|
||||
|
||||
return parent::display();
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
if (!Session::checkToken('post')) {
|
||||
throw new \RuntimeException(Text::_('JINVALID_TOKEN'), 403);
|
||||
}
|
||||
|
||||
$app = Factory::getApplication();
|
||||
$user = $app->getIdentity();
|
||||
if ($user->guest || (!$user->authorise('core.manage', 'com_circolari') && !$user->authorise('core.admin', 'com_circolari'))) {
|
||||
throw new \RuntimeException(Text::_('JERROR_ALERTNOAUTHOR'), 403);
|
||||
}
|
||||
|
||||
$data = [
|
||||
'id' => $this->input->getInt('id', 0),
|
||||
'title' => trim($this->input->getString('title', '')),
|
||||
'alias' => trim($this->input->getString('alias', '')),
|
||||
'description' => $this->input->get('description', '', 'raw'),
|
||||
'categoria_id' => $this->input->getInt('categoria_id', 0),
|
||||
'tipologia_firma_id' => $this->input->getInt('tipologia_firma_id', 0),
|
||||
'firma_obbligatoria' => $this->input->getInt('firma_obbligatoria', 0),
|
||||
'scadenza' => $this->input->getString('scadenza', ''), // 'YYYY-MM-DD HH:MM'
|
||||
'state' => $this->input->getInt('state', 1),
|
||||
// nuovi campi per creare tipologia al volo
|
||||
'nuova_tipologia_nome' => trim($this->input->getString('nuova_tipologia_nome', '')),
|
||||
'nuovi_bottoni' => trim($this->input->getString('nuovi_bottoni', '')),
|
||||
];
|
||||
|
||||
if ($data['title'] === '') {
|
||||
$app->enqueueMessage(Text::_('COM_CIRCOLARI_ERR_TITLE_REQUIRED'), 'error');
|
||||
$this->setRedirect(Route::_('index.php?option=com_circolari&view=form&layout=edit&id=' . (int)$data['id'], false));
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var \Pcrt\Component\Circolari\Site\Model\FormModel $model */
|
||||
$model = $this->getModel('Form', 'Site');
|
||||
|
||||
try {
|
||||
$id = $model->saveData($data, $user->id);
|
||||
$app->enqueueMessage(Text::_('COM_CIRCOLARI_MSG_SAVED_OK'), 'message');
|
||||
$this->setRedirect(Route::_('index.php?option=com_circolari&view=circolare&id=' . (int)$id, false));
|
||||
} catch (\Throwable $e) {
|
||||
$app->enqueueMessage($e->getMessage(), 'error');
|
||||
$this->setRedirect(Route::_('index.php?option=com_circolari&view=form&layout=edit&id=' . (int)$data['id'], false));
|
||||
}
|
||||
}
|
||||
|
||||
public function cancel()
|
||||
{
|
||||
$this->setRedirect(Route::_('index.php?option=com_circolari&view=circolari', false));
|
||||
}
|
||||
}
|
||||
148
site/src/Model/FormModel.php
Normal file
148
site/src/Model/FormModel.php
Normal file
@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
namespace Pcrt\Component\Circolari\Site\Model;
|
||||
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
|
||||
|
||||
class FormModel extends BaseDatabaseModel
|
||||
{
|
||||
public function getItem(int $id = 0): ?\stdClass
|
||||
{
|
||||
if ($id <= 0) return null;
|
||||
|
||||
$db = Factory::getContainer()->get('DatabaseDriver');
|
||||
$q = $db->getQuery(true)
|
||||
->select('*')
|
||||
->from('#__circolari')
|
||||
->where('id = ' . (int)$id);
|
||||
$db->setQuery($q);
|
||||
return $db->loadObject() ?: null;
|
||||
}
|
||||
|
||||
public function getCategorie(): array
|
||||
{
|
||||
$db = Factory::getContainer()->get('DatabaseDriver');
|
||||
$q = $db->getQuery(true)
|
||||
->select('id, title, state')
|
||||
->from('#__circolari_categorie')
|
||||
->where('state = 1')
|
||||
->order('title ASC');
|
||||
$db->setQuery($q);
|
||||
return $db->loadAssocList() ?: [];
|
||||
}
|
||||
public function getFirmetipi(): array
|
||||
{
|
||||
$db = \Joomla\CMS\Factory::getContainer()->get('DatabaseDriver');
|
||||
$q = $db->getQuery(true)
|
||||
->select('id, nome')
|
||||
->from('#__circolari_firmetipi')
|
||||
->where('state = 1')
|
||||
->order('nome ASC');
|
||||
$db->setQuery($q);
|
||||
return $db->loadAssocList() ?: [];
|
||||
}
|
||||
|
||||
public function getBottoniByFirmatipo(): array
|
||||
{
|
||||
$db = \Joomla\CMS\Factory::getContainer()->get('DatabaseDriver');
|
||||
$q = $db->getQuery(true)
|
||||
->select('f.id AS firmatipo_id, b.label')
|
||||
->from('#__circolari_firmetipi AS f')
|
||||
->leftJoin('#__circolari_firmetipi_bottoni AS b ON b.firmatipo_id = f.id')
|
||||
->where('f.state = 1')
|
||||
->order('f.id ASC, b.ordering ASC, b.id ASC');
|
||||
$db->setQuery($q);
|
||||
$rows = $db->loadAssocList() ?: [];
|
||||
|
||||
$map = [];
|
||||
foreach ($rows as $r) {
|
||||
$fid = (int) $r['firmatipo_id'];
|
||||
if (!isset($map[$fid])) $map[$fid] = [];
|
||||
if (!empty($r['label'])) $map[$fid][] = $r['label'];
|
||||
}
|
||||
return $map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Salva/aggiorna la circolare; crea anche una nuova tipologia e bottoni se richiesto.
|
||||
* Ritorna l'ID della circolare salvata.
|
||||
*/
|
||||
public function saveData(array $data, int $userId): int
|
||||
{
|
||||
$db = Factory::getContainer()->get('DatabaseDriver');
|
||||
|
||||
|
||||
// 2) normalizza alias
|
||||
if (empty($data['alias'])) {
|
||||
$data['alias'] = $this->slugify($data['title']);
|
||||
}
|
||||
|
||||
// 3) INSERT o UPDATE su #__circolari
|
||||
$now = Factory::getDate()->toSql();
|
||||
$row = (object) [
|
||||
'id' => (int)($data['id'] ?? 0),
|
||||
'title' => $data['title'],
|
||||
'alias' => $data['alias'],
|
||||
'description' => $data['description'],
|
||||
'categoria_id' => (int)$data['categoria_id'],
|
||||
'tipologia_firma_id' => (int)$data['tipologia_firma_id'],
|
||||
'firma_obbligatoria' => (int)$data['firma_obbligatoria'],
|
||||
'scadenza' => $data['scadenza'] ?: null,
|
||||
'state' => (int)$data['state'],
|
||||
];
|
||||
|
||||
if ($row->id > 0) {
|
||||
$row->modified_by = $userId;
|
||||
$row->checked_out = 0;
|
||||
$row->checked_out_time = null;
|
||||
$db->updateObject('#__circolari', $row, ['id']);
|
||||
$id = $row->id;
|
||||
} else {
|
||||
$row->created_by = $userId;
|
||||
$db->insertObject('#__circolari', $row);
|
||||
$id = (int)$db->insertid();
|
||||
}
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
private function createNewFirmatipo(string $nome, string $bottoniRiga): int
|
||||
{
|
||||
$db = Factory::getContainer()->get('DatabaseDriver');
|
||||
|
||||
// crea tipologia
|
||||
$tipo = (object) [
|
||||
'nome' => $nome,
|
||||
'descrizione' => '',
|
||||
'state' => 1,
|
||||
];
|
||||
$db->insertObject('#__circolari_firmetipi', $tipo);
|
||||
$id = (int) $db->insertid();
|
||||
|
||||
// crea bottoni (uno per riga)
|
||||
$labels = array_filter(array_map('trim', preg_split('/\R+/', $bottoniRiga ?: '')));
|
||||
$ordering = 1;
|
||||
foreach ($labels as $label) {
|
||||
$btn = (object) [
|
||||
'firmatipo_id' => $id,
|
||||
'label' => $label,
|
||||
'ordering' => $ordering++,
|
||||
];
|
||||
$db->insertObject('#__circolari_firmetipi_bottoni', $btn);
|
||||
}
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
private function slugify(string $s): string
|
||||
{
|
||||
$t = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $s);
|
||||
$t = strtolower($t);
|
||||
$t = preg_replace('~[^a-z0-9]+~', '-', $t);
|
||||
$t = trim($t, '-');
|
||||
return $t ?: 'circolare';
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace Pcrt\Component\Circolari\Site\Service;
|
||||
|
||||
\defined('_JEXEC') or die;
|
||||
@ -8,123 +9,101 @@ use Joomla\CMS\Menu\AbstractMenu;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Component\Router\RouterView;
|
||||
use Joomla\CMS\Component\Router\RouterViewConfiguration;
|
||||
use Joomla\CMS\Component\Router\Rules\StandardRules;
|
||||
use Joomla\CMS\Component\Router\Rules\MenuRules;
|
||||
use Joomla\CMS\Component\Router\Rules\StandardRules;
|
||||
use Joomla\CMS\Component\Router\Rules\NomenuRules;
|
||||
|
||||
class Router extends RouterView
|
||||
{
|
||||
public function __construct(SiteApplication $app, AbstractMenu $menu)
|
||||
{
|
||||
// Parent: category (annidata → più segmenti)
|
||||
// 1) CATEGORIA (se la usi nei percorsi)
|
||||
$category = new RouterViewConfiguration('category');
|
||||
$category->setKey('id')->setNestable();
|
||||
$this->registerView($category);
|
||||
|
||||
// Child: circolare (lega la category tramite categoria_id)
|
||||
$circolare = new RouterViewConfiguration('circolari');
|
||||
$circolare->setKey('id')->setParent($category, 'categoria_id', 'id');
|
||||
// 2) LISTA (nessuna key!)
|
||||
$circolari = new RouterViewConfiguration('circolari');
|
||||
// Se vuoi, puoi lasciarla senza parent, oppure solo setParent($category) SENZA variabili
|
||||
// $circolari->setParent($category); // opzionale, ma senza 2° e 3° argomento
|
||||
$this->registerView($circolari);
|
||||
|
||||
// DETTAGLIO (ha la key id)
|
||||
$circolare = new RouterViewConfiguration('circolare');
|
||||
$circolare->setKey('id')->setParent($circolari);
|
||||
$this->registerView($circolare);
|
||||
|
||||
// 4) FORM (se presente)
|
||||
$form = new RouterViewConfiguration('form');
|
||||
$form->setParent($circolari);
|
||||
$this->registerView($form);
|
||||
|
||||
parent::__construct($app, $menu);
|
||||
|
||||
// Regole standard di routing
|
||||
$this->attachRule(new StandardRules($this));
|
||||
// Regole: prima Menu, poi Standard, poi NoMenu
|
||||
$this->attachRule(new MenuRules($this));
|
||||
$this->attachRule(new StandardRules($this));
|
||||
$this->attachRule(new NomenuRules($this));
|
||||
}
|
||||
|
||||
/* ---------------- BUILD ---------------- */
|
||||
|
||||
// Segmenti categoria = path completo (parent1/parent2/figlia)
|
||||
// Segmento categoria = alias (fallback id)
|
||||
public function getCategorySegment($id, $query)
|
||||
{
|
||||
$id = (int) ($id ?: 0);
|
||||
if ($id <= 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$db = Factory::getContainer()->get('DatabaseDriver');
|
||||
$path = (string) $db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->select('path')
|
||||
->from('#__circolari_categorie')
|
||||
->where('id = ' . $id)
|
||||
->where("extension = 'com_content'")
|
||||
$db = Factory::getContainer()->get('DatabaseDriver');
|
||||
$alias = (string) $db->setQuery(
|
||||
$db->getQuery(true)->select('alias')->from('#__circolari_categorie')->where('id=' . (int)$id)
|
||||
)->loadResult();
|
||||
|
||||
return $path !== '' ? array_filter(explode('/', $path)) : [(string) $id];
|
||||
return $alias !== '' ? [$alias] : [(string) (int) $id];
|
||||
}
|
||||
|
||||
// Ultimo segmento = SOLO alias della circolare
|
||||
// Segmento dettaglio = alias (fallback id se vuoto)
|
||||
public function getCircolareSegment($id, $query)
|
||||
{
|
||||
$db = Factory::getContainer()->get('DatabaseDriver');
|
||||
$alias = (string) $db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->select('alias')
|
||||
->from('#__circolari')
|
||||
->where('id = ' . (int) $id)
|
||||
$db->getQuery(true)->select('alias')->from('#__circolari')->where('id=' . (int)$id)
|
||||
)->loadResult();
|
||||
|
||||
// Nessun fallback numerico: imponiamo l'alias
|
||||
return [$alias];
|
||||
return [$alias !== '' ? $alias : (string) (int) $id];
|
||||
}
|
||||
|
||||
/* ---------------- PARSE ---------------- */
|
||||
|
||||
// Ricava categoria_id accumulando i segmenti e risolvendo per PATH completo
|
||||
public function getCategoryId($segment, $query)
|
||||
{
|
||||
static $segments = [];
|
||||
$segments[] = $segment;
|
||||
$path = implode('/', $segments);
|
||||
|
||||
$db = Factory::getContainer()->get('DatabaseDriver');
|
||||
|
||||
// match per path (univoco in com_content)
|
||||
$id = (int) $db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->select('id')
|
||||
->from('#__circolari_categorie')
|
||||
->where('path = ' . $db->quote($path))
|
||||
->where("extension = 'com_content'")
|
||||
$db->getQuery(true)->select('id')->from('#__circolari_categorie')->where('alias=' . $db->quote($segment))
|
||||
)->loadResult();
|
||||
|
||||
if ($id > 0) {
|
||||
return $id;
|
||||
}
|
||||
|
||||
// fallback (singolo alias) se si visita direttamente un livello intermedio
|
||||
$id = (int) $db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->select('id')
|
||||
->from('#__circolari_categorie')
|
||||
->where('alias = ' . $db->quote($segment))
|
||||
->where("extension = 'com_content'")
|
||||
->order('level DESC')
|
||||
)->loadResult();
|
||||
|
||||
return $id ?: 0;
|
||||
return $id > 0 ? $id : (ctype_digit((string)$segment) ? (int)$segment : 0);
|
||||
}
|
||||
|
||||
// Alias circolare (+ categoria_id già risolto) → id
|
||||
public function getCircolareId($segment, $query)
|
||||
{
|
||||
$categoria_id = (int) ($query['categoria_id'] ?? 0);
|
||||
|
||||
$db = Factory::getContainer()->get('DatabaseDriver');
|
||||
$q = $db->getQuery(true)
|
||||
->select('id')
|
||||
->from('#__circolari')
|
||||
->where('alias = ' . $db->quote($segment));
|
||||
->select('id')
|
||||
->from('#__circolari')
|
||||
->where('alias = ' . $db->quote($segment));
|
||||
|
||||
if ($categoria_id > 0) {
|
||||
$q->where('categoria_id = ' . $categoria_id);
|
||||
}
|
||||
|
||||
$db->setQuery($q);
|
||||
$id = (int) $db->loadResult();
|
||||
|
||||
return (int) $db->loadResult() ?: 0;
|
||||
// fallback numerico sull’ultimo segmento
|
||||
if ($id === 0 && ctype_digit((string)$segment)) {
|
||||
$id = (int) $segment;
|
||||
}
|
||||
|
||||
return $id;
|
||||
}
|
||||
}
|
||||
|
||||
40
site/src/View/Form/HtmlView.php
Normal file
40
site/src/View/Form/HtmlView.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Pcrt\Component\Circolari\Site\View\Form;
|
||||
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Factory;
|
||||
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
public $item;
|
||||
public $categorie = [];
|
||||
public $firmetipi = [];
|
||||
public $bottoniMap = [];
|
||||
|
||||
public function display($tpl = null)
|
||||
{
|
||||
$model = $this->getModel();
|
||||
$this->item = $model->getItem((int) \Joomla\CMS\Factory::getApplication()->input->getInt('id', 0));
|
||||
$this->categorie = $model->getCategorie();
|
||||
$this->firmetipi = $model->getFirmetipi();
|
||||
$this->bottoniMap = $model->getBottoniByFirmatipo();
|
||||
$app = Factory::getApplication();
|
||||
$user = $app->getIdentity();
|
||||
if ($user->guest || (!$user->authorise('core.manage', 'com_circolari') && !$user->authorise('core.admin', 'com_circolari'))) {
|
||||
throw new \RuntimeException(\Joomla\CMS\Language\Text::_('JERROR_ALERTNOAUTHOR'), 403);
|
||||
}
|
||||
|
||||
/** @var \Pcrt\Component\Circolari\Site\Model\FormModel $model */
|
||||
$model = $this->getModel();
|
||||
|
||||
$id = (int) $app->input->getInt('id', 0);
|
||||
$this->item = $model->getItem($id);
|
||||
$this->categorie = $model->getCategorie();
|
||||
$this->firmetipi = $model->getFirmetipi();
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user