diff --git a/site/src/Controller/FormController.php b/site/src/Controller/FormController.php index 6eb49ce..1aec1ce 100644 --- a/site/src/Controller/FormController.php +++ b/site/src/Controller/FormController.php @@ -1,4 +1,5 @@ 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(); + $this->input->set('view', 'form'); + return parent::display($cachable, $urlparams); } public function save() { - if (!Session::checkToken('post')) { - throw new \RuntimeException(Text::_('JINVALID_TOKEN'), 403); - } + $app = Factory::getApplication(); + $user = Factory::getUser(); - $app = Factory::getApplication(); - $user = $app->getIdentity(); - if ($user->guest || (!$user->authorise('core.manage', 'com_circolari') && !$user->authorise('core.admin', 'com_circolari'))) { + // Permessi: admin/gestione o edit + if (!$user->id || (!$user->authorise('core.manage', 'com_circolari') && !$user->authorise('core.edit', '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 (!Session::checkToken()) { + throw new \RuntimeException(Text::_('JINVALID_TOKEN'), 403); + } - 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; + + $in = $app->input; + + $data = $in->get('jform', [], 'array'); + + // Il tuo form frontend invia campi "piatti" + if (!$data) { + $data = [ + 'id' => $in->getInt('id', 0), + 'title' => $in->getString('title', ''), + 'alias' => $in->getString('alias', ''), + 'categoria_id' => $in->getInt('categoria_id', 0), + 'description' => $in->getRaw('description', ''), + 'state' => $in->getInt('state', 1), + 'firma_obbligatoria' => $in->getInt('firma_obbligatoria', 0), + 'tipologia_firma_id' => $in->getInt('tipologia_firma_id', 0), + 'scadenza' => $in->getString('scadenza', ''), // datetime-local + ]; } /** @var \Pcrt\Component\Circolari\Site\Model\FormModel $model */ - $model = $this->getModel('Form', 'Site'); + $model = $this->getModel('Form'); - 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)); - } + $id = $model->saveData($data, (int) $user->id); + + $this->setRedirect( + Route::_('index.php?option=com_circolari&view=circolare&id=' . (int) $id, false), + Text::_('JLIB_APPLICATION_SAVE_SUCCESS') + ); } public function cancel() diff --git a/site/src/Model/FormModel.php b/site/src/Model/FormModel.php index 6c9c7e4..0d694ab 100644 --- a/site/src/Model/FormModel.php +++ b/site/src/Model/FormModel.php @@ -9,18 +9,6 @@ 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 { @@ -66,48 +54,66 @@ class FormModel extends BaseDatabaseModel 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; + public function getItem(int $id = 0): \stdClass +{ + if ($id <= 0) { + return (object) []; } + $db = \Joomla\CMS\Factory::getContainer()->get('DatabaseDriver'); + $q = $db->getQuery(true) + ->select('*')->from('#__circolari')->where('id=' . (int) $id); + $db->setQuery($q); + return $db->loadObject() ?: (object) []; +} + +public function saveData(array $data, int $userId): int +{ + $app = \Joomla\CMS\Factory::getApplication(); + + // Alias di fallback + if (empty($data['alias']) && !empty($data['title'])) { + $alias = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $data['title']); + $alias = preg_replace('~[^a-z0-9]+~i', '-', strtolower($alias)); + $alias = trim($alias, '-'); + $data['alias'] = $alias ?: ('circolare-' . uniqid()); + } + + // JTable amministrativa per coerenza di check/store + $factory = $app->bootComponent('com_circolari')->getMVCFactory(); + /** @var \Pcrt\Component\Circolari\Administrator\Table\CircolareTable $table */ + $table = $factory->createTable('Circolare', 'Administrator'); + + $id = (int) ($data['id'] ?? 0); + if ($id > 0) { + $table->load($id); + $data['modified_by'] = $userId; + } else { + $data['created_by'] = $userId; + } + + // Sblocca/normalizza + $data['checked_out'] = 0; + $data['checked_out_time'] = null; + + if (!$table->bind($data)) { throw new \RuntimeException($table->getError() ?: 'Bind failed'); } + if (!$table->check()) { throw new \RuntimeException($table->getError() ?: 'Check failed'); } + + // ordering se nuovo + if (empty($table->id) || (int) $table->ordering === 0) { + $db = \Joomla\CMS\Factory::getContainer()->get('DatabaseDriver'); + $max = (int) $db->setQuery( + $db->getQuery(true)->select('COALESCE(MAX(ordering),0)') + ->from('#__circolari') + ->where('categoria_id=' . (int) ($table->categoria_id ?? 0)) + )->loadResult(); + $table->ordering = $max + 1; + } + + if (!$table->store()) { throw new \RuntimeException($table->getError() ?: 'Store failed'); } + + return (int) $table->id; +} + private function createNewFirmatipo(string $nome, string $bottoniRiga): int { diff --git a/site/src/Service/Router.php b/site/src/Service/Router.php index 4190dd8..2170c9f 100644 --- a/site/src/Service/Router.php +++ b/site/src/Service/Router.php @@ -17,102 +17,99 @@ class Router extends RouterView { public function __construct(SiteApplication $app, AbstractMenu $menu) { - // 1) CATEGORIA (se la usi nei percorsi) - - // 2) LISTA (nessuna key!) + // 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) + // DETTAGLIO (ha key id) $circolare = new RouterViewConfiguration('circolare'); $circolare->setKey('id')->setParent($circolari); $this->registerView($circolare); - // 4) FORM (se presente) + // FORM (nessuna key) $form = new RouterViewConfiguration('form'); $form->setParent($circolari); $this->registerView($form); parent::__construct($app, $menu); - // Regole: prima Menu, poi Standard, poi NoMenu $this->attachRule(new MenuRules($this)); $this->attachRule(new StandardRules($this)); $this->attachRule(new NomenuRules($this)); } - /* ---------------- BUILD ---------------- */ + // Pulisci la query quando costruisci gli URL + public function build(&$query) + { + // Se sto costruendo 'form', non agganciare Itemid di altre view del componente + if (($query['view'] ?? '') === 'form' && isset($query['Itemid'])) { + $item = $this->menu->getItem((int) $query['Itemid']); + if ($item && $item->component === 'com_circolari') { + $v = is_array($item->query ?? null) ? ($item->query['view'] ?? '') : ''; + if ($v !== 'form') { + unset($query['Itemid']); // evita override della view + } + } + } + // Lista: non appendere categorie in querystring + if (($query['view'] ?? '') === 'circolari') { + unset($query['categoria_id'], $query['catid'], $query['categories'], $query['categorie'], $query['category_id']); + } - // Segmento categoria = alias (fallback id) + if (($query['view'] ?? '') === 'form' && isset($query['Itemid'])) { + $item = $this->menu->getItem((int) $query['Itemid']); + if ($item && $item->component === 'com_circolari') { + $v = is_array($item->query ?? null) ? ($item->query['view'] ?? '') : ''; + if ($v !== 'form') { + unset($query['Itemid']); + } + } + } + return parent::build($query); + } - // Segmento dettaglio = alias (fallback id se vuoto) + // Segmento dettaglio = alias (fallback id) 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(); return [$alias !== '' ? $alias : (string) (int) $id]; } - /* ---------------- PARSE ---------------- */ - - + // Parse del dettaglio: alias -> id (opz. con categoria) 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)); - if ($categoria_id > 0) { - $q->where('categoria_id = ' . $categoria_id); + if (!empty($query['categoria_id'])) { + $q->where('categoria_id = ' . (int) $query['categoria_id']); } $db->setQuery($q); $id = (int) $db->loadResult(); - // fallback numerico sull’ultimo segmento - if ($id === 0 && ctype_digit((string)$segment)) { + // fallback numerico + if ($id === 0 && ctype_digit((string) $segment)) { $id = (int) $segment; } return $id; } - // ⬇️ AGGIUNGI in Pcrt\Component\Circolari\Site\Service\Router - - // Rimuove categoria_id (ecc.) dalla LISTA prima che Joomla costruisca l’URL. - // Così sparisce anche se il link della voce di menu in DB lo contiene ancora. - public function build(&$query) - { - if (isset($query['view']) && $query['view'] === 'circolari') { - foreach (['categoria_id', 'catid', 'categorie', 'categories', 'category_id'] as $k) { - if (array_key_exists($k, $query)) { - unset($query[$k]); - } - } - } - - // Se vuoi essere ultra-clean, rimuovi anche id/Itemid “sporchi” (non necessario di solito) - // if (isset($query['view']) && $query['view'] === 'circolari' && isset($query['id'])) unset($query['id']); - - return parent::build($query); - } - - // (Opzionale) Non reintrodurre variabili categoria in parse: la lista si filtra da params del menu. + // (Opzionale) Non reintrodurre categorie in parse per la lista public function parse(&$segments) { $vars = parent::parse($segments); - if (isset($vars['view']) && $vars['view'] === 'circolari') { + if (($vars['view'] ?? '') === 'circolari') { unset($vars['categoria_id'], $vars['catid'], $vars['categorie'], $vars['category_id']); } diff --git a/site/src/View/Form/HtmlView.php b/site/src/View/Form/HtmlView.php index d8024b3..8e19571 100644 --- a/site/src/View/Form/HtmlView.php +++ b/site/src/View/Form/HtmlView.php @@ -1,11 +1,10 @@ getModel(); - $this->item = $model->getItem((int) \Joomla\CMS\Factory::getApplication()->input->getInt('id', 0)); + + $id = $app->input->getInt('id', 0); + $this->item = $model->getItem($id); $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); } diff --git a/site/tmpl/circolare/default.php b/site/tmpl/circolare/default.php index a10ae47..f6cfc9d 100644 --- a/site/tmpl/circolare/default.php +++ b/site/tmpl/circolare/default.php @@ -48,6 +48,13 @@ if ($canAdmin) {
+ + + Modifica Circolare + + +

escape($item->title); ?>

@@ -109,15 +116,14 @@ if ($canAdmin) {
diff --git a/site/tmpl/form/default.php b/site/tmpl/form/default.php index 9172712..590013f 100644 --- a/site/tmpl/form/default.php +++ b/site/tmpl/form/default.php @@ -32,7 +32,7 @@ $cancelUrl = $cancelItemId

-
+
@@ -131,8 +131,8 @@ $cancelUrl = $cancelItemId
- - + +