Predisposizione lista circolari

This commit is contained in:
2025-08-29 11:24:11 +02:00
parent 16ac92a59e
commit 22fb3c0871
9 changed files with 218 additions and 90 deletions

View File

@ -3,20 +3,29 @@ namespace Pcrt\Component\Circolari\Site\Controller;
\defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\MVC\Controller\BaseController;
class DisplayController extends BaseController
{
protected $default_view = 'circolare'; // default se manca ?view=
public function display($cachable = false, $urlparams = [])
{
// Se qualcuno forza un view strano, non rompiamo
$view = $this->input->getCmd('view', $this->default_view);
if (!in_array($view, ['circolare'], true)) {
$view = $this->default_view;
$this->input->set('view', $view);
$app = Factory::getApplication();
$in = $app->input;
$view = $in->getCmd('view', '');
$id = $in->getInt('id', 0);
if ($id > 0) {
// Singolo solo se c'è l'id
$in->set('view', 'circolare');
} else {
// Nessun id: forziamo la lista (anche se il menu chiede "circolare")
if ($view === '' || $view === 'circolare' || $view === 'category') {
$in->set('view', 'circolari'); // <- lista
}
}
return parent::display($cachable, $urlparams);
}
}

View File

@ -3,31 +3,56 @@ namespace Pcrt\Component\Circolari\Site\Model;
\defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\MVC\Model\ItemModel;
use Joomla\CMS\Factory;
class CircolareModel extends ItemModel
{
protected function populateState(): void
protected function populateState()
{
$app = Factory::getApplication();
$this->setState('circolare.id', (int) $app->input->getInt('id'));
$id = $app->input->getInt('id', 0);
$this->setState('circolare.id', $id);
$catid = $app->input->getInt('catid', 0);
$this->setState('filter.catid', $catid);
parent::populateState();
}
public function getItem($pk = null)
{
$pk = $pk ?: (int) $this->getState('circolare.id');
if (!$pk) return null;
$pk = (int) ($pk ?: $this->getState('circolare.id'));
$db = Factory::getContainer()->get('DatabaseDriver');
if ($pk <= 0) {
return null;
}
$db = $this->getDatabase();
$q = $db->getQuery(true)
->select('*')
->from($db->quoteName('#__circolari'))
->where($db->quoteName('id') . ' = ' . (int) $pk)
->where($db->quoteName('state') . ' = 1');
$db->setQuery($q);
->select('c.*') // <<< evita errori di colonne
->from($db->quoteName('#__circolari') . ' AS c')
->where('c.id = ' . (int) $pk);
return $db->loadObject();
// Se esistono le colonne, applica filtri
$cols = array_change_key_case(
$db->getTableColumns($db->replacePrefix('#__circolari'), false),
CASE_LOWER
);
// catid (se impostato e colonna esiste)
$catid = (int) $this->getState('filter.catid', 0);
if ($catid > 0 && isset($cols['catid'])) {
$q->where('c.catid = ' . $catid);
}
// stato (se colonna esiste)
if (isset($cols['state'])) {
$q->where('COALESCE(c.state, 1) = 1');
}
$db->setQuery($q);
$row = $db->loadObject();
return $row ?: null;
}
}

View File

@ -0,0 +1,59 @@
<?php
namespace Pcrt\Component\Circolari\Site\Model;
\defined('_JEXEC') or die;
use Joomla\CMS\MVC\Model\ListModel;
class CircolariModel extends ListModel
{
protected $context = 'com_circolari.circolari';
protected function getListQuery()
{
$db = $this->getDatabase();
$q = $db->getQuery(true)
->select('c.*') // evita errori per colonne mancanti
->from($db->quoteName('#__circolari') . ' AS c');
// Colonne realmente presenti
$cols = array_change_key_case(
$db->getTableColumns($db->replacePrefix('#__circolari'), false),
CASE_LOWER
);
// Stato (solo se esiste la colonna)
if (isset($cols['state'])) {
$q->where('COALESCE(c.state, 1) = 1');
}
// Filtro categoria (solo se esiste colonna e valore)
$catid = (int) $this->getState('filter.catid', 0);
if ($catid > 0 && isset($cols['catid'])) {
$q->where('c.catid = ' . $catid);
}
// Ordinamento (ripiega su id se la colonna non c'è)
$orderCol = (string) $this->getState('list.ordering', 'c.id');
$orderDir = strtoupper((string) $this->getState('list.direction', 'DESC')) === 'ASC' ? 'ASC' : 'DESC';
$orderKey = ltrim(str_ireplace('c.', '', $orderCol));
if (!isset($cols[strtolower($orderKey)])) {
$orderCol = 'c.id';
}
$q->order($db->escape($orderCol . ' ' . $orderDir));
return $q;
}
public function getItems()
{
$items = parent::getItems();
if (!is_array($items)) {
return [];
}
// Filtra eventuali elementi nulli/invalidi
return array_values(array_filter($items, static function ($it) {
return is_object($it) && isset($it->id) && (int) $it->id > 0;
}));
}
}

View File

@ -1,21 +0,0 @@
<?php
/**
* @version CVS: 1.0.0
* @package Com_Circolari
* @author Tommaso Cippitelli <tommaso.cippitelli@protocollicreativi.it>
* @copyright 2025 Tommaso Cippitelli
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Pcrt\Component\Circolari\Site\Service;
// No direct access
defined('_JEXEC') or die;
use \Joomla\CMS\Categories\Categories;
/**
* Content Component Category Tree
*
* @since 1.0.0
*/

View File

@ -3,35 +3,50 @@ namespace Pcrt\Component\Circolari\Site\View\Circolare;
\defined('_JEXEC') or die;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Factory;
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
use Joomla\CMS\Language\Text;
class HtmlView extends BaseHtmlView
{
protected $item;
public $items = [];
public $pagination;
public $state;
public function display($tpl = null)
{
// Carica la singola
$this->item = $this->get('Item');
// Se NON c'è l'item → mostra la lista
if (!$this->item) {
throw new \Exception(Text::_('COM_CIRCOLARI_ITEM_NOT_FOUND'), 404);
$app = \Joomla\CMS\Factory::getApplication();
$factory = $app->bootComponent('com_circolari')->getMVCFactory();
/** @var \Pcrt\Component\Circolari\Site\Model\CircolariModel $model */
$model = $factory->createModel('Circolari', 'Site', ['ignore_request' => true]);
// Imposta gli stati MANUALMENTE (niente populateState: è protected)
$model->setState('filter.catid', 0); // nessun filtro categoria
$model->setState('list.start', 0);
$model->setState('list.limit', 0); // 0 = nessun limite (tutte)
$model->setState('list.ordering', 'c.id'); // colonna di ordinamento
$model->setState('list.direction', 'DESC'); // direzione
// Recupera i dati
$this->state = $model->getState();
$this->items = $model->getItems();
$this->pagination = $model->getPagination();
// Usa il layout della lista (tmpl/circolari/default.php)
$this->setLayout('default');
$this->addTemplatePath(JPATH_COMPONENT_SITE . '/tmpl/circolari');
return parent::display($tpl);
}
// Se il layout non c'è, stampa un fallback minimale (debug-friendly)
$tplPath = JPATH_COMPONENT_SITE . '/tmpl/circolare/default.php';
if (!is_file($tplPath)) {
$title = htmlspecialchars($this->item->title ?? 'Circolare');
$body = $this->item->description ?? $this->item->testo ?? $this->item->descrizione ?? '';
$html = '<article class="com-content-article item-page">'
. '<header class="page-header"><h1 class="page-title">'.$title.'</h1></header>'
. '<div class="article-body">'.$body.'</div>'
. '</article>';
$this->document->setBuffer($html, 'component');
return;
}
parent::display($tpl);
// Rendering normale della singola
return parent::display($tpl);
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace Pcrt\Component\Circolari\Site\View\Circolari;
\defined('_JEXEC') or die;
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
class HtmlView extends BaseHtmlView
{
public $items;
public $pagination;
public $state;
public function display($tpl = null)
{
$this->state = $this->get('State');
$this->items = $this->get('Items');
$this->pagination = $this->get('Pagination');
return parent::display($tpl);
}
}

View File

@ -1,33 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<metadata>
<!-- titolo del tipo voce di menu, visibile nel backend -->
<layout title="COM_CIRCOLARI_MENU_CATEGORY" option="com_circolari" />
<!-- campi che finiscono nella query dell'URL -->
<fields name="request">
<fieldset name="request">
<!-- forza la view "category" -->
<field name="view" type="hidden" default="category" />
<!-- scegli la categoria di Joomla (com_content) che fa da base del percorso -->
<field
name="id"
type="category"
extension="com_content"
label="JCATEGORY"
description="Seleziona la categoria di com_content da usare come base del percorso URL."
required="true"
default="11"
/>
</fieldset>
</fields>
<!-- parametri opzionali della voce (non obbligatori) -->
<fields name="params">
<fieldset name="basic" label="JOPTIONS">
<field name="show_category_title" type="radio" label="COM_CIRCOLARI_SHOW_CATEGORY_TITLE" default="0">
<option value="0">JHIDE</option>
<option value="1">JSHOW</option>
</field>
</fieldset>
</fields>
</metadata>

View File

@ -0,0 +1,43 @@
<?php
\defined('_JEXEC') or die;
use Joomla\CMS\Router\Route;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Factory;
$rows = $this->items ?? [];
if (!is_array($rows)) $rows = (array) $rows;
$rows = array_values(array_filter($rows, static function ($it) {
return is_object($it) && !empty($it->id);
}));
$Itemid = (int) (Factory::getApplication()->input->getInt('Itemid') ?: 0);
?>
<div class="circolari-list">
<?php if (!count($rows)) : ?>
<p><?php echo htmlspecialchars(Text::_('COM_CIRCOLARI_NO_ITEMS') ?: 'Nessuna circolare', ENT_QUOTES, 'UTF-8'); ?></p>
<?php else : ?>
<ul class="circolari-list__ul">
<?php foreach ($rows as $item) : ?>
<?php
$url = Route::_(
'index.php?option=com_circolari&view=circolare'
. '&id=' . (int) $item->id
. '&catid=' . (int) ($item->catid ?? 0)
. ($Itemid ? '&Itemid=' . $Itemid : '')
);
?>
<li class="circolari-list__li">
<a href="<?php echo $url; ?>">
<?php echo htmlspecialchars($item->title ?? ('#' . (int) $item->id), ENT_QUOTES, 'UTF-8'); ?>
</a>
<?php if (!empty($item->attachment)) : ?>
<small> — <a href="<?php echo htmlspecialchars($item->attachment, ENT_QUOTES, 'UTF-8'); ?>" target="_blank" rel="noopener">
<?php echo Text::_('COM_CIRCOLARI_READ_PDF') ?: 'PDF'; ?>
</a></small>
<?php endif; ?>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</div>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<metadata>
<layout title="COM_CIRCOLARI_MENU_LIST" option="com_circolari" />
<fields name="request">
<fieldset name="request">
<field name="view" type="hidden" default="circolari" />
<field name="catid" type="category" extension="com_content" label="JCATEGORY" required="false" />
</fieldset>
</fields>
</metadata>