aggiunta firma circolari
This commit is contained in:
@ -18,9 +18,7 @@
|
||||
<field name="alias" type="text" label="JFIELD_ALIAS_LABEL" description="JFIELD_ALIAS_DESC" />
|
||||
|
||||
<field name="categoria_id" type="Categoria" label="Categoria" required="true" />
|
||||
<field name="usergroup_id" type="usergrouplist"
|
||||
label="COM_CIRCOLARI_FORM_LBL_CIRCOLARE_USERGROUP"
|
||||
description="COM_CIRCOLARI_FORM_DESC_CIRCOLARE_USERGROUP" />
|
||||
|
||||
<field name="description" type="editor" label="COM_CIRCOLARI_FORM_LBL_CIRCOLARE_DESCRIPTION"
|
||||
filter="safehtml" buttons="true" />
|
||||
<field name="attachment" type="media" label="COM_CIRCOLARI_FORM_LBL_CIRCOLARE_ATTACHMENT"
|
||||
@ -38,6 +36,17 @@
|
||||
|
||||
</field>
|
||||
|
||||
|
||||
<field
|
||||
name="usergroup_ids"
|
||||
type="usergrouplist"
|
||||
label="Gruppi abilitati alla firma"
|
||||
description="Seleziona i gruppi che possono firmare la circolare"
|
||||
multiple="true"
|
||||
required="false"
|
||||
showon="firma_obbligatoria:1"
|
||||
/>
|
||||
|
||||
<field name="tipologia_firma_id" type="Tipologiafirma" label="Tipologia firma"
|
||||
showon="firma_obbligatoria:1" />
|
||||
<field name="scadenza" type="CalSafe" label="Data Scadenza Firma"
|
||||
|
||||
12
administrator/sql/updates/1.1.7.sql
Normal file
12
administrator/sql/updates/1.1.7.sql
Normal file
@ -0,0 +1,12 @@
|
||||
-- tabella ponte: quali gruppi possono firmare quale circolare
|
||||
CREATE TABLE IF NOT EXISTS `#__circolari_usergroups` (
|
||||
`circolare_id` INT NOT NULL,
|
||||
`usergroup_id` INT NOT NULL,
|
||||
`required` TINYINT(1) NOT NULL DEFAULT 0, -- opzionale: firma obbligatoria del gruppo
|
||||
`can_firmare` TINYINT(1) NOT NULL DEFAULT 1, -- opzionale: futura granularità
|
||||
PRIMARY KEY (`circolare_id`, `usergroup_id`),
|
||||
KEY `idx_group` (`usergroup_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
|
||||
ALTER TABLE `#__circolari` DROP COLUMN `usergroup_id`;
|
||||
@ -135,6 +135,17 @@ class CircolareModel extends AdminModel
|
||||
}
|
||||
}
|
||||
|
||||
$id = (int) ($data->id ?? $this->getState($this->getName() . '.id'));
|
||||
if ($id) {
|
||||
$db = Factory::getContainer()->get('DatabaseDriver');
|
||||
$q = $db->getQuery(true)
|
||||
->select($db->quoteName('usergroup_id'))
|
||||
->from($db->quoteName('#__circolari_usergroups'))
|
||||
->where($db->quoteName('circolare_id') . ' = ' . (int) $id);
|
||||
$db->setQuery($q);
|
||||
$data->usergroup_ids = $db->loadColumn() ?: [];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
@ -324,4 +335,47 @@ class CircolareModel extends AdminModel
|
||||
$this->_db->setQuery($q);
|
||||
return ((int) $this->_db->loadResult()) > 0;
|
||||
}
|
||||
|
||||
public function save($data)
|
||||
{
|
||||
$ok = parent::save($data);
|
||||
if (!$ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$id = (int) $this->getState($this->getName() . '.id');
|
||||
$groups = array_map('intval', $data['usergroup_ids'] ?? []);
|
||||
|
||||
$db = Factory::getContainer()->get('DatabaseDriver');
|
||||
$db->transactionStart();
|
||||
|
||||
try {
|
||||
// ripulisci associazioni esistenti
|
||||
$db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->delete($db->quoteName('#__circolari_usergroups'))
|
||||
->where($db->quoteName('circolare_id') . ' = ' . (int) $id)
|
||||
)->execute();
|
||||
|
||||
// reinserisci le nuove
|
||||
if (!empty($groups)) {
|
||||
$q = $db->getQuery(true)
|
||||
->insert($db->quoteName('#__circolari_usergroups'))
|
||||
->columns([$db->quoteName('circolare_id'), $db->quoteName('usergroup_id')]);
|
||||
|
||||
foreach ($groups as $gid) {
|
||||
$q->values((int) $id . ',' . (int) $gid);
|
||||
}
|
||||
$db->setQuery($q)->execute();
|
||||
}
|
||||
|
||||
$db->transactionCommit();
|
||||
} catch (\Throwable $e) {
|
||||
$db->transactionRollback();
|
||||
$this->setError($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ HTMLHelper::_('bootstrap.tooltip');
|
||||
<?php echo $this->form->renderField('attachment'); ?>
|
||||
<?php echo $this->form->renderField('image'); ?>
|
||||
<?php echo $this->form->renderField('firma_obbligatoria'); ?>
|
||||
<?php echo $this->form->renderField('tipologia_firma_id'); ?>
|
||||
<?php echo $this->form->renderField('usergroup_ids'); ?>
|
||||
<?php echo $this->form->renderField('scadenza'); ?>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
@ -82,7 +82,7 @@ if (!empty($saveOrder)) {
|
||||
|
||||
<th scope="col" class="w-3 d-none d-lg-table-cell">
|
||||
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JGRID_HEADING_ID', 'a.id', $listDirn, $listOrder); ?> </th>
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JGRID_HEADING_ID', 'a.id', $listDirn, $listOrder); ?> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tfoot>
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<author>Tommaso Cippitelli</author>
|
||||
<authorEmail>tommaso.cippitelli@protocollicreativi.it</authorEmail>
|
||||
<authorUrl>http://</authorUrl>
|
||||
<version>1.1.6</version>
|
||||
<version>1.1.7</version>
|
||||
<description></description>
|
||||
<namespace path="src">Pcrt\Component\Circolari</namespace>
|
||||
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
<?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;
|
||||
|
||||
class CircolareModel extends ItemModel
|
||||
{
|
||||
@ -55,23 +57,90 @@ class CircolareModel extends ItemModel
|
||||
|
||||
return $row ?: null;
|
||||
}
|
||||
}
|
||||
|
||||
public function getBottoniFirma(int $firmatipoId): array
|
||||
{
|
||||
$buttons = []; // <- sempre inizializzato
|
||||
|
||||
/**
|
||||
* Incrementa gli hits della circolare.
|
||||
*/
|
||||
public function hit($pk = null)
|
||||
{
|
||||
$pk = $pk ?: (int) $this->getState($this->getName() . '.id');
|
||||
if (!$pk) {
|
||||
return false;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
$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;
|
||||
}
|
||||
|
||||
@ -14,14 +14,13 @@ class CircolariModel extends ListModel
|
||||
protected $filter_fields = [
|
||||
'id', 'c.id',
|
||||
'title', 'c.title',
|
||||
'created', 'c.created',
|
||||
'hits', 'c.hits',
|
||||
'categoria_id', 'c.categoria_id',
|
||||
'state', 'c.state',
|
||||
];
|
||||
|
||||
protected function populateState($ordering = 'c.created', $direction = 'DESC')
|
||||
{
|
||||
{
|
||||
$app = Factory::getApplication();
|
||||
|
||||
// paging
|
||||
@ -80,9 +79,6 @@ class CircolariModel extends ListModel
|
||||
}
|
||||
|
||||
// ordinamento
|
||||
$orderCol = $this->getState('list.ordering', 'c.created');
|
||||
$orderDir = $this->getState('list.direction', 'DESC');
|
||||
$q->order($db->escape($orderCol . ' ' . $orderDir));
|
||||
|
||||
return $q;
|
||||
}
|
||||
@ -116,4 +112,4 @@ class CircolariModel extends ListModel
|
||||
return \is_object($it) && !empty($it->id);
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -22,7 +22,7 @@ class Router extends RouterView
|
||||
$this->registerView($category);
|
||||
|
||||
// Child: circolare (lega la category tramite categoria_id)
|
||||
$circolare = new RouterViewConfiguration('circolare');
|
||||
$circolare = new RouterViewConfiguration('circolari');
|
||||
$circolare->setKey('id')->setParent($category, 'categoria_id', 'id');
|
||||
$this->registerView($circolare);
|
||||
|
||||
|
||||
@ -6,6 +6,8 @@ use Joomla\CMS\Language\Text;
|
||||
|
||||
/** @var \Pcrt\Component\Circolari\Site\View\Circolare\HtmlView $this */
|
||||
$item = $this->item;
|
||||
|
||||
$buttons = $this->getModel()->getBottoniFirma((int)$item->tipologia_firma_id);
|
||||
?>
|
||||
|
||||
<div class="container my-5 mega-container">
|
||||
@ -18,6 +20,18 @@ $item = $this->item;
|
||||
<div class="col-md-3 col-12 text-md-end mt-2 mt-md-0">
|
||||
<a href="#" class="small text-decoration-none text-uppercase fw-bold">Condividi</a>
|
||||
</div>
|
||||
|
||||
<?php if ($item->firma_obbligatoria && $this->getModel()->userCanFirmare($item->id, $this->getModel()->currentUser->id) && !empty($buttons)) : ?>
|
||||
<div class="mt-4">
|
||||
<div class="d-flex flex-wrap gap-2">
|
||||
<?php foreach ($buttons as $btn) : ?>
|
||||
<button type="button" class="btn btn-primary btn-sm">
|
||||
<?php echo htmlspecialchars($btn->label, ENT_QUOTES, 'UTF-8'); ?>
|
||||
</button>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="article-body mt-3">
|
||||
<?php echo $item->description ?: $item->testo ?: $item->descrizione ?: '<em>(Nessun testo)</em>'; ?>
|
||||
</div>
|
||||
|
||||
@ -1,67 +1,44 @@
|
||||
<?php
|
||||
// ... intestazione invariata ...
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
|
||||
/** @var \Pcrt\Component\Circolari\Site\View\Circolare\HtmlView $this */
|
||||
$item = $this->item;
|
||||
dump($item);
|
||||
|
||||
$buttons = $this->getModel()->getBottoniFirma((int)$item->tipologia_firma_id);
|
||||
dump($this->getModel()->currentUser);
|
||||
|
||||
// $listOrder / $listDirn / $filter già come li hai
|
||||
$Itemid = (int) ($input->getInt('Itemid') ?: 0);
|
||||
?>
|
||||
<form action="<?php echo htmlspecialchars(Uri::getInstance()->toString(), ENT_QUOTES, 'UTF-8'); ?>"
|
||||
method="post"
|
||||
name="adminForm"
|
||||
id="adminForm"
|
||||
class="com-content-category__articles">
|
||||
|
||||
<!-- filtro -->
|
||||
<!-- (invariato) -->
|
||||
<div class="container my-5 mega-container">
|
||||
|
||||
<!-- Limite per pagina -->
|
||||
<?php if ($pagination && \method_exists($pagination, 'getLimitBox')) : ?>
|
||||
<div class="com-content-category__pagination btn-group float-end">
|
||||
<label for="limit" class="visually-hidden"><?php echo Text::_('JGLOBAL_DISPLAY_NUM'); ?></label>
|
||||
<?php echo $pagination->getLimitBox(); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- tabella -->
|
||||
<table class="com-content-category__table category table table-striped table-bordered table-hover mt-3">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" id="circolari_header_title">
|
||||
<?php echo HTMLHelper::_('grid.sort', 'JGLOBAL_TITLE', 'c.title', $listDirn, $listOrder, null, 'asc', '', 'adminForm'); ?>
|
||||
</th>
|
||||
<th scope="col" id="circolari_header_date" class="small">
|
||||
<?php echo HTMLHelper::_('grid.sort', Text::_('JDATE'), 'c.created', $listDirn, $listOrder, null, 'asc', '', 'adminForm'); ?>
|
||||
</th>
|
||||
<th scope="col" id="circolari_header_attachment" class="text-center">
|
||||
<?php echo Text::_('COM_CIRCOLARI_ATTACHMENT') ?: 'Allegato'; ?>
|
||||
</th>
|
||||
<th scope="col" id="circolari_header_hits" class="text-end">
|
||||
<?php echo HTMLHelper::_('grid.sort', 'JGLOBAL_HITS', 'c.hits', $listDirn, $listOrder, null, 'asc', '', 'adminForm'); ?>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<!-- tbody invariato -->
|
||||
</table>
|
||||
|
||||
<!-- paginazione -->
|
||||
<?php if ($pagination && $pagination->pagesTotal > 1) : ?>
|
||||
<div class="com-content-category__navigation w-100">
|
||||
<p class="com-content-category__counter counter float-end pt-3 pe-2">
|
||||
<?php echo $pagination->getPagesCounter(); ?>
|
||||
</p>
|
||||
<div class="com-content-category__pagination">
|
||||
<?php echo $pagination->getPagesLinks(); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- hidden -->
|
||||
<div>
|
||||
<input type="hidden" name="option" value="com_circolari">
|
||||
<input type="hidden" name="view" value="circolari">
|
||||
<?php if ($Itemid) : ?><input type="hidden" name="Itemid" value="<?php echo $Itemid; ?>"><?php endif; ?>
|
||||
<input type="hidden" name="filter_order" value="<?php echo $listOrder; ?>">
|
||||
<input type="hidden" name="filter_order_Dir" value="<?php echo $listDirn; ?>">
|
||||
<input type="hidden" name="limitstart" value="<?php echo (int) ($pagination?->limitstart ?? 0); ?>">
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
<div class="row mb-4 align-items-end">
|
||||
<div class="col-md-9 col-12">
|
||||
<h1 class="h2 mb-1"><?= $this->escape($item->title); ?></h1>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
<div class="col-md-3 col-12 text-md-end mt-2 mt-md-0">
|
||||
<a href="#" class="small text-decoration-none text-uppercase fw-bold">Condividi</a>
|
||||
</div>
|
||||
|
||||
<?php if ( $item->firma_obbligatoria && !empty($buttons)) : ?>
|
||||
<div class="mt-4">
|
||||
<div class="d-flex flex-wrap gap-2">
|
||||
<?php foreach ($buttons as $btn) : ?>
|
||||
<button type="button" class="btn btn-primary btn-sm">
|
||||
<?php echo htmlspecialchars($btn->label, ENT_QUOTES, 'UTF-8'); ?>
|
||||
</button>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="article-body mt-3">
|
||||
<?php echo $item->description ?: $item->testo ?: $item->descrizione ?: '<em>(Nessun testo)</em>'; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@ -1,10 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<metadata>
|
||||
<layout title="COM_CIRCOLARI_MENU_LIST" option="com_circolari" />
|
||||
<layout title="Lista di categorie Circolari" option="com_circolari">
|
||||
<help key="JHELP_MENUS_MENU_ITEM_GENERIC" />
|
||||
</layout>
|
||||
|
||||
<!-- Parametri che finiscono direttamente nella URL (request) -->
|
||||
<fields name="request">
|
||||
<fieldset name="request">
|
||||
<!-- Selezione della categoria delle circolari -->
|
||||
<field
|
||||
name="categoria_id"
|
||||
type="sql"
|
||||
label="Categoria"
|
||||
required="true"
|
||||
query="SELECT id AS value, title AS text FROM #__circolari_categorie WHERE state = 1 ORDER BY title"
|
||||
key_field="value"
|
||||
value_field="text"
|
||||
translate="false"
|
||||
/>
|
||||
|
||||
<!-- Forza la view corretta -->
|
||||
<field name="view" type="hidden" default="circolari" />
|
||||
<field name="categoria_id" type="category" extension="com_content" label="JCATEGORY" required="false" />
|
||||
</fieldset>
|
||||
</fields>
|
||||
|
||||
<!-- Opzioni pagina (facoltative) -->
|
||||
<fields name="params">
|
||||
<fieldset name="advanced" label="JGLOBAL_FIELDSET_ADVANCED">
|
||||
<field name="page_title" type="text" label="JGLOBAL_TITLE" />
|
||||
<field name="show_page_heading" type="radio" default="1" label="JGLOBAL_SHOW_PAGE_HEADING">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
</fieldset>
|
||||
</fields>
|
||||
</metadata>
|
||||
|
||||
Reference in New Issue
Block a user