405 lines
18 KiB
PHP
405 lines
18 KiB
PHP
<?php
|
|
\defined('_JEXEC') or die;
|
|
|
|
use Joomla\CMS\Factory;
|
|
use Joomla\CMS\Router\Route;
|
|
use Joomla\CMS\HTML\HTMLHelper;
|
|
use Joomla\CMS\Language\Text;
|
|
use Joomla\CMS\Session\Session;
|
|
|
|
$app = Factory::getApplication();
|
|
$user = $app->getIdentity();
|
|
$model = method_exists($this, 'getModel') ? $this->getModel('Circolare') : null;
|
|
$item = $this->item;
|
|
|
|
$canAdmin = $user->authorise('core.admin', 'com_circolari') || $user->authorise('core.manage', 'com_circolari');
|
|
|
|
// Firma dell'utente (se esiste)
|
|
$firma = ($model && !$user->guest) ? $model->getFirmaUtente((int)$item->id, (int)$user->id) : null;
|
|
$hasVoted = (bool) $firma;
|
|
|
|
// Helper per confrontare anche in caso di schema ENUM
|
|
$slugify = function (string $s): string {
|
|
$s = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $s);
|
|
$s = strtolower($s);
|
|
$s = preg_replace('~[^a-z0-9]+~', '_', $s);
|
|
return trim($s, '_');
|
|
};
|
|
|
|
$selectedBtnId = isset($firma->firmatipo_bottone_id) ? (int)$firma->firmatipo_bottone_id : 0;
|
|
$selectedEnum = isset($firma->firma_enum) ? (string)$firma->firma_enum : '';
|
|
$buttons = $this->getModel()->getBottoniFirma((int)$item->tipologia_firma_id);
|
|
$firme = [];
|
|
if ($canAdmin) {
|
|
$model = method_exists($this, 'getModel') ? $this->getModel('Circolare') : null;
|
|
if (!$model) {
|
|
// fallback creazione model via MVCFactory se necessario
|
|
try {
|
|
$factory = $app->bootComponent('com_circolari')->getMVCFactory();
|
|
$model = $factory->createModel('Circolare', 'Site', ['ignore_request' => true]);
|
|
} catch (\Throwable $e) {
|
|
$model = null;
|
|
}
|
|
}
|
|
$firme = $model ? $model->getFirmeCircolare((int)$item->id) : [];
|
|
}
|
|
?>
|
|
|
|
<div class="container my-5 mega-container">
|
|
|
|
<?php if ($canAdmin): ?>
|
|
<a class="btn btn-primary"
|
|
href="<?php echo \Joomla\CMS\Router\Route::_('index.php?option=com_circolari&task=form.display&id=' . (int)$this->item->id, false); ?>">
|
|
Modifica Circolare
|
|
</a>
|
|
<?php endif; ?>
|
|
|
|
<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>
|
|
<?php //Condividi
|
|
?>
|
|
<div class="col-md-3 col-12 text-md-end mt-2 mt-md-0">
|
|
<a class="toggle-actions small text-decoration-none text-uppercase fw-bold d-flex justify-content-end align-items-center" style="color: #003274" href="#" title="Vedi azioni" data-bs-toggle="modal" data-bs-target="#modalaction" data-focus-mouse="false">
|
|
<span class="me-1">Condividi</span>
|
|
<svg class="icon" style="width: 24px; height: 24px; fill: #003274">
|
|
<use href="/media/templates/site/tpl_istituzionale/images/sprites.svg#it-more-items"></use>
|
|
</svg>
|
|
</a>
|
|
<div class="modal modal-actions fade no-print" tabindex="-1" id="modalaction" aria-labelledby="modalCenterTitle" style="display: none;" data-focus-mouse="false" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-centered" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
|
|
<button class="btn-close" type="button" data-bs-dismiss="modal" aria-label="Chiudi finestra modale" data-focus-mouse="false">
|
|
<svg class="icon">
|
|
<use href="/media/templates/site/tpl_istituzionale/images/sprites.svg#it-close"></use>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="link-list-wrapper">
|
|
<ul class="link-list ps-0 ms-0">
|
|
<li>
|
|
<a href="javascript:window.print();" class="list-item left-icon" title="Stampa il contenuto" data-focus-mouse="false">
|
|
<svg class="icon">
|
|
<use href="/media/templates/site/tpl_istituzionale/images/sprites.svg#it-print"></use>
|
|
</svg>
|
|
<span>Stampa</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="mailto:?subject=Back to School 2025: pronti per un nuovo anno!&body=https://www.liceoariosto.edu.it/novita/le-notizie/back-to-school-2025-pronti-per-un-nuovo-anno" class="list-item left-icon" title="Invia il contenuto">
|
|
<svg class="icon">
|
|
<use href="/media/templates/site/tpl_istituzionale/images/sprites.svg#it-mail"></use>
|
|
</svg>
|
|
<span>Invia</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a class="list-item link-toggle" title="Condividi" href="#social-share" data-bs-toggle="collapse" aria-expanded="true" aria-controls="social-share" role="button" id="share-control" data-focus-mouse="false">
|
|
<svg class="icon">
|
|
<use href="/media/templates/site/tpl_istituzionale/images/sprites.svg#it-share"></use>
|
|
</svg>
|
|
<span>Condividi</span>
|
|
<svg class="icon icon-right">
|
|
<use href="/media/templates/site/tpl_istituzionale/images/sprites.svg#it-expand"></use>
|
|
</svg>
|
|
</a>
|
|
<ul class="ps-0 link-sublist collapse show" id="social-share" role="region" aria-labelledby="share-control" style="">
|
|
<li>
|
|
<a class="list-item" href="https://www.facebook.com/sharer/sharer.php?u=https://www.liceoariosto.edu.it/novita/le-notizie/back-to-school-2025-pronti-per-un-nuovo-anno" title="Condividi su: Facebook" target="_blank" data-focus-mouse="false">
|
|
<svg class="icon">
|
|
<use href="/media/templates/site/tpl_istituzionale/images/sprites.svg#it-facebook"></use>
|
|
</svg>
|
|
<span>Facebook</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a class="list-item" href="http://twitter.com/share?text=Back to School 2025: pronti per un nuovo anno!&url=https://www.liceoariosto.edu.it/novita/le-notizie/back-to-school-2025-pronti-per-un-nuovo-anno" title="Condividi su: Twitter" target="_blank">
|
|
<svg class="icon">
|
|
<use href="/media/templates/site/tpl_istituzionale/images/sprites.svg#it-twitter"></use>
|
|
</svg>
|
|
<span>Twitter</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a class="list-item" href="https://www.linkedin.com/shareArticle?mini=true&url=https://www.liceoariosto.edu.it/novita/le-notizie/back-to-school-2025-pronti-per-un-nuovo-anno&title=Back to School 2025: pronti per un nuovo anno!&source=Liceo Ariosto Ferrara" title="Condividi su: Linkedin" target="_blank">
|
|
<svg class="icon">
|
|
<use href="/media/templates/site/tpl_istituzionale/images/sprites.svg#it-linkedin"></use>
|
|
</svg>
|
|
<span>Linkedin</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="py-1 px-3 btn btn-primary btn-sm" data-bs-dismiss="modal" type="button">Ok</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php if ($item->image): ?>
|
|
<div class="mb-4">
|
|
<img src="/<?php echo $item->image ?>" alt="" class="img-fluid h-50 w-100 shadow-sm" style="border-radius: 15px;">
|
|
</div>
|
|
<?php endif; ?>
|
|
<?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" data-sign-group="circolare-<?php echo (int)$item->id; ?>">
|
|
<?php foreach ($buttons as $btn) :
|
|
$btnId = (int) $btn->id;
|
|
$isSelected =
|
|
($selectedBtnId > 0 && $selectedBtnId === $btnId)
|
|
|| ($selectedEnum !== '' && in_array($selectedEnum, [
|
|
$slugify($btn->label),
|
|
str_replace('-', '_', $slugify($btn->label)), // normalizza trattini→underscore
|
|
], true));
|
|
|
|
// Classi bootstrap: selezionato = "success", altri disattivi = outline-secondary
|
|
$btnClasses = 'btn btn-sm ' . ($isSelected ? 'btn-success' : ($hasVoted ? 'btn-outline-secondary' : 'btn-primary'));
|
|
?>
|
|
|
|
<?php if ($hasVoted): ?>
|
|
<button type="button"
|
|
class="<?php echo $btnClasses; ?> opacity-75"
|
|
disabled
|
|
aria-disabled="true"
|
|
title="<?php echo $isSelected ? $this->escape(Text::_('Hai già scelto questo')) : $this->escape(Text::_('Hai già firmato')); ?>">
|
|
<?php echo htmlspecialchars($btn->label, ENT_QUOTES, 'UTF-8'); ?>
|
|
</button>
|
|
<?php else: ?>
|
|
<form method="post"
|
|
action="<?= Route::_('index.php?option=com_circolari&task=circolare.sign&id=' . (int)$item->id); ?>"
|
|
class="d-inline-block">
|
|
<input type="hidden" name="bottone_id" value="<?php echo $btnId; ?>">
|
|
<button type="submit"
|
|
class="<?php echo $btnClasses; ?> js-sign-btn">
|
|
<?php echo htmlspecialchars($btn->label, ENT_QUOTES, 'UTF-8'); ?>
|
|
</button>
|
|
<?= HTMLHelper::_('form.token'); ?>
|
|
</form>
|
|
<?php endif; ?>
|
|
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
<div class="article-body mt-3">
|
|
<?php echo $item->description; ?>
|
|
</div>
|
|
<?php
|
|
// Normalizza lista allegati: prima prova array $item->attachments (nuova logica),
|
|
// altrimenti fallback ai vecchi campi singoli $item->attachment / $item->allegato_titolo.
|
|
$attachments = [];
|
|
|
|
// 1) Nuova logica: array di allegati dal Model (path, title, ordering)
|
|
if (!empty($item->attachments) && is_array($item->attachments)) {
|
|
foreach ($item->attachments as $att) {
|
|
$path = (string) ($att['path'] ?? ($att->path ?? ''));
|
|
if ($path === '') continue;
|
|
$title = (string) ($att['title'] ?? ($att->title ?? ''));
|
|
$ord = (int) ($att['ordering'] ?? ($att->ordering ?? 0));
|
|
$attachments[] = ['href' => $path, 'label' => $title, 'ordering' => $ord];
|
|
}
|
|
}
|
|
|
|
// 2) Fallback legacy: singolo allegato
|
|
if (empty($attachments) && !empty($item->attachment)) {
|
|
$attachments[] = [
|
|
'href' => (string) $item->attachment,
|
|
'label' => (string) ($item->allegato_titolo ?: ''),
|
|
'ordering' => 0,
|
|
];
|
|
}
|
|
|
|
// Ordina per ordering, poi per label
|
|
usort($attachments, function ($a, $b) {
|
|
$o = ($a['ordering'] <=> $b['ordering']);
|
|
if ($o !== 0) return $o;
|
|
return strcmp((string)$a['label'], (string)$b['label']);
|
|
});
|
|
|
|
// Mappa icone in base all'estensione (puoi adattare gli id alle tue sprite)
|
|
$spritePath = '/media/templates/site/tpl_istituzionale/images/sprites.svg';
|
|
function _att_icon_id(string $ext): string
|
|
{
|
|
$ext = strtolower($ext);
|
|
if (in_array($ext, ['pdf'], true)) return 'it-file-pdf';
|
|
if (in_array($ext, ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'svg', 'tif', 'tiff', 'heic', 'heif'], true)) return 'it-file-image';
|
|
if (in_array($ext, ['doc', 'docx', 'rtf', 'odt'], true)) return 'it-file-doc';
|
|
if (in_array($ext, ['xls', 'xlsx', 'ods', 'csv'], true)) return 'it-file-xls';
|
|
if (in_array($ext, ['ppt', 'pptx', 'odp'], true)) return 'it-file-ppt';
|
|
if (in_array($ext, ['zip', 'rar', '7z', 'gz', 'bz2', 'tar'], true)) return 'it-file-zip';
|
|
return 'it-file'; // generico
|
|
}
|
|
?>
|
|
|
|
<?php if (!empty($attachments)): ?>
|
|
<h6 class="mt-4"><?php echo JText::_('Allegati'); ?></h6>
|
|
<div class="row g-3 mb-2">
|
|
<?php foreach ($attachments as $att):
|
|
$hrefRaw = (string) ($att['href'] ?? '');
|
|
$labelRaw = (string) ($att['label'] ?? '');
|
|
// Fallback label = basename del file se non presente
|
|
$basename = basename(htmlspecialchars_decode($hrefRaw));
|
|
$label = trim($labelRaw) !== '' ? $labelRaw : $basename;
|
|
|
|
// Estensione per icona e testo accessibile
|
|
$ext = strtolower(pathinfo($basename, PATHINFO_EXTENSION));
|
|
if ($ext === 'jpeg') {
|
|
$ext = 'jpg';
|
|
} // coerenza
|
|
$iconId = _att_icon_id($ext);
|
|
|
|
$href = htmlspecialchars($hrefRaw, ENT_QUOTES, 'UTF-8');
|
|
$labelEsc = htmlspecialchars($label, ENT_QUOTES, 'UTF-8');
|
|
$titleAttr = 'Scarica ' . $label;
|
|
$titleEsc = htmlspecialchars($titleAttr, ENT_QUOTES, 'UTF-8');
|
|
|
|
// Testo accessibile sul tipo file (es. "file PDF", "file immagine", ecc.)
|
|
$a11yType = '';
|
|
switch ($iconId) {
|
|
case 'it-file-pdf':
|
|
$a11yType = ' (file PDF)';
|
|
break;
|
|
case 'it-file-image':
|
|
$a11yType = ' (file immagine)';
|
|
break;
|
|
case 'it-file-doc':
|
|
$a11yType = ' (documento)';
|
|
break;
|
|
case 'it-file-xls':
|
|
$a11yType = ' (foglio di calcolo)';
|
|
break;
|
|
case 'it-file-ppt':
|
|
$a11yType = ' (presentazione)';
|
|
break;
|
|
case 'it-file-zip':
|
|
$a11yType = ' (archivio compresso)';
|
|
break;
|
|
default:
|
|
$a11yType = $ext ? ' (file .' . htmlspecialchars($ext, ENT_QUOTES, 'UTF-8') . ')' : '';
|
|
}
|
|
?>
|
|
<div class="col-12 col-lg-6">
|
|
<div class="card card-documento card-bg card-icon rounded shadow-sm h-100">
|
|
<div class="card-body d-flex align-items-center">
|
|
<svg class="icon" aria-hidden="true" focusable="false" style="fill:#d1344c;">
|
|
<use xlink:href="<?php echo $spritePath . '#' . $iconId; ?>"></use>
|
|
</svg>
|
|
<div class="card-icon-content">
|
|
<p class="mb-0">
|
|
<a
|
|
class="text-decoration-none"
|
|
href="<?php echo $href; ?>"
|
|
download
|
|
title="<?php echo $titleEsc; ?>"
|
|
data-focus-mouse="false">
|
|
<strong><?php echo $labelEsc; ?></strong>
|
|
<span class="visually-hidden"><?php echo $a11yType; ?></span>
|
|
</a>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
|
|
</div>
|
|
|
|
<style>
|
|
.card.card-icon .icon {
|
|
width: 34px;
|
|
height: 34px;
|
|
flex-shrink: 0;
|
|
margin: 0 8px 0 0;
|
|
}
|
|
</style>
|
|
|
|
<?php if ($canAdmin & $item->firma_obbligatoria): ?>
|
|
<div class="card mt-4">
|
|
<div class="card-header d-flex justify-content-between align-items-center">
|
|
<strong>Firme ricevute</strong>
|
|
<a class="btn btn-outline-secondary btn-sm"
|
|
href="<?=
|
|
\Joomla\CMS\Router\Route::_(
|
|
'index.php?option=com_circolari&task=circolare.exportFirme&id=' . (int)$item->id . '&' . \Joomla\CMS\Session\Session::getFormToken() . '=1'
|
|
); ?>"
|
|
download>
|
|
Scarica Excel
|
|
</a>
|
|
|
|
</div>
|
|
|
|
<div class="table-responsive">
|
|
<table class="table table-sm mb-0 align-middle">
|
|
<thead>
|
|
<tr>
|
|
<th>Nome</th>
|
|
<th class="text-muted">Username</th>
|
|
<th>Scelta</th>
|
|
<th class="text-end">Data</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php if (empty($firme)) : ?>
|
|
<tr>
|
|
<td colspan="4" class="text-center text-muted py-3">Nessuna firma registrata.</td>
|
|
</tr>
|
|
<?php else : ?>
|
|
<?php foreach ($firme as $r) : ?>
|
|
<tr>
|
|
<td><?php echo htmlspecialchars($r['user_name'], ENT_QUOTES, 'UTF-8'); ?></td>
|
|
<td class="text-muted"><?php echo htmlspecialchars($r['username'], ENT_QUOTES, 'UTF-8'); ?></td>
|
|
<td>
|
|
<span class="badge bg-secondary"><?php echo htmlspecialchars($r['scelta_label'], ENT_QUOTES, 'UTF-8'); ?></span>
|
|
</td>
|
|
<td class="text-end">
|
|
<?php echo htmlspecialchars(Factory::getDate($r['data_firma'])->format('d/m/Y H:i'), ENT_QUOTES, 'UTF-8'); ?>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
</div>
|
|
|
|
|
|
<?php if (!$hasVoted): ?>
|
|
<script>
|
|
(function() {
|
|
var container = document.querySelector('[data-sign-group="circolare-<?php echo (int)$item->id; ?>"]');
|
|
if (!container) return;
|
|
container.addEventListener('submit', function(e) {
|
|
var form = e.target.closest('form');
|
|
if (!form) return;
|
|
var clickedBtn = form.querySelector('button');
|
|
var allBtns = container.querySelectorAll('button');
|
|
allBtns.forEach(function(b) {
|
|
b.classList.remove('btn-primary');
|
|
b.classList.add('btn-outline-secondary');
|
|
b.setAttribute('disabled', 'disabled');
|
|
b.setAttribute('aria-disabled', 'true');
|
|
b.classList.add('opacity-75');
|
|
});
|
|
if (clickedBtn) {
|
|
clickedBtn.classList.remove('btn-outline-secondary', 'opacity-75');
|
|
clickedBtn.classList.add('btn-success');
|
|
}
|
|
}, true); // usa capture per intercettare subito
|
|
})();
|
|
</script>
|
|
<?php endif; ?>
|