Compare commits

..

33 Commits

Author SHA1 Message Date
f800f0ab7f Merge pull request 'Se ce la mandano buona abbiamo un orario decente su telefono.' (#4) from daniele/orario:dev into dev
Reviewed-on: #4
2025-10-04 17:46:39 +00:00
9c9c26a470 Se ce la mandano buona abbiamo un orario decente su telefono. 2025-10-04 19:38:39 +02:00
40da7d0d58 Rimosse schifezze varie 2025-10-03 17:23:01 +02:00
0561902092 revert f91019b884
revert Aggiornamento README.md
2025-10-03 15:19:13 +00:00
8c8d32e0c8 sono impedito e mi dimentico del readme 2025-10-03 10:17:27 +02:00
35ff83d1d0 Introduzione modalita' sviluppatore e vari change 2025-10-03 10:15:25 +02:00
f91019b884 Aggiornamento README.md 2025-10-03 09:03:18 +02:00
6b5b05199c prova di integrazione SSO Google + riscrizionamento di alcune parti 2025-10-03 09:01:59 +02:00
dc1d07c015 fix CSS 2025-10-02 12:01:42 +02:00
d405a0e21c troppe modifiche, non so cosa scrivere 2025-10-02 11:54:59 +02:00
f68162b80b some changes 2025-10-02 08:51:47 +00:00
f98f5a3c07 changes, finishing later 2025-10-02 09:45:24 +02:00
7249325faf fixes 2025-10-02 09:23:38 +02:00
b599691c2e Manage users 2025-10-02 09:17:32 +02:00
8a37f24b40 design fix 2025-10-01 17:10:20 +02:00
725518ca8a move error message 2025-10-01 17:09:19 +02:00
cbf6ef27a2 design fix and add back to link 2025-10-01 17:07:54 +02:00
9c936ed3be how fucking much can I be dumb?? 2025-10-01 16:59:18 +02:00
c3f8b52990 fucking readme 2025-10-01 16:57:57 +02:00
4de8528da2 fix 2025-10-01 16:57:39 +02:00
0265af9dd2 Change password feature (maybe) 2025-10-01 16:55:28 +02:00
e8079c2ce7 fix 2025-10-01 16:33:26 +02:00
fb72f23544 Readme 2025-10-01 15:50:13 +02:00
ddfa3d6dd8 Docker 2025-10-01 15:49:06 +02:00
c619b748fa Docker image integration (beta) 2025-10-01 15:42:34 +02:00
906beaaa4b Integrated auth by default 2025-10-01 15:15:28 +02:00
86826c86bb Merge pull request 'Fixing mobile view and improving some menus.' (#3) from daniele/orario:dev into dev
Reviewed-on: #3
2025-09-27 16:10:38 +00:00
79a4823726 Fixing mobile view and improving some menus. 2025-09-27 18:06:46 +02:00
459663e069 Update README.md 2025-09-22 08:50:14 +00:00
ccbb9806f5 Testo del copyright 2025-09-11 10:30:21 +02:00
07b197c89a Link al codice sorgente 2025-09-11 10:21:10 +02:00
fff1e6cddf altra piccola modifica 2025-09-11 09:58:22 +02:00
9c044b051c Piccola modifica 2025-09-11 09:29:59 +02:00
22 changed files with 864 additions and 1397 deletions

View File

@@ -1,3 +1,6 @@
## AVVISO IMPORTANTE
Questo è il ramo di SVILUPPO. È inteso per testare le ultime funzionalità e aiutarmi nello sviluppo. La stabilità e il funzionamento del codice non sono garantiti. Usare a proprio rischio e pericolo.
# Orario Scuola # Orario Scuola
Una piattaforma web per visualizzare gli orari scolastici delle classi, degli insegnanti e dei vari laboratori (se presenti) Una piattaforma web per visualizzare gli orari scolastici delle classi, degli insegnanti e dei vari laboratori (se presenti)
@@ -26,7 +29,7 @@ sudo apt install -y composer php-cli curl php-mysql php-curl php-mbstring php-xm
3. **Installa le dipendenze del pannello d'amministrazione** 3. **Installa le dipendenze del pannello d'amministrazione**
- Debian: - Debian:
```bash ```bash
cd /var/www/html/admin cd /var/www/orario/admin
composer install composer install
``` ```
- Windows (con XAMPP): - Windows (con XAMPP):
@@ -37,12 +40,12 @@ composer install
4. **(opzionale) Genera una password hashata** 4. **(opzionale) Genera una password hashata**
- Debian - Debian
```bash ```bash
cd orario/utils cd /var/www/orario/utils
php generate_hash.php <password> php generate_hash.php <password>
``` ```
- Windows: - Windows:
```batch ```batch
cd orario\utils cd C:\xampp\htdocs\utils
C:\xampp\php\php.exe generate_hash.php <password> C:\xampp\php\php.exe generate_hash.php <password>
``` ```
- Modifica quindi questa linea nel file ``schema.sql``, sostituendo l'hash predefinito con quello generato prima: - Modifica quindi questa linea nel file ``schema.sql``, sostituendo l'hash predefinito con quello generato prima:
@@ -50,74 +53,67 @@ C:\xampp\php\php.exe generate_hash.php <password>
VALUES ('admin', '$2y$10$IS9v8CJNJnRXslV1NWDSquAjJ0GgU1sm6spBmGp6mjTLiNApfGcQi'); VALUES ('admin', '$2y$10$IS9v8CJNJnRXslV1NWDSquAjJ0GgU1sm6spBmGp6mjTLiNApfGcQi');
``` ```
5. **Importa il file ``schema.sql`` nel tuo database MySQL** 5. **Importa il file ``schema.sql`` nel tuo database MySQL**
- Esempio Debian:
```bash
mysql -u root -p < orario/schema.sql
```
6. **Modifica il file ``config/config.php`` inserendo i valori richiesti** 6. **Modifica il file ``config/config.php`` inserendo i valori richiesti**
- Esempio file ``config/config.php``: - Esempio file ``config/config.php``:
```php ```php
<?php <?php
// Impostazioni Database // Impostazioni Database
if (!defined('DB_HOST')) { if (!defined('DB_HOST')) {
define('DB_HOST', 'localhost'); // Host del database (ad esempio localhost) define('DB_HOST', 'db');
} }
if (!defined('DB_USER')) { if (!defined('DB_USER')) {
define('DB_USER', 'orario'); // Utente del database (ad esempio orario) define('DB_USER', 'orario');
} }
if (!defined('DB_PASS')) { if (!defined('DB_PASS')) {
define('DB_PASS', 'orario'); // Password dell'utente specificato prima (ad esempio password123) define('DB_PASS', 'orario');
} }
if (!defined('DB_NAME')) { if (!defined('DB_NAME')) {
define('DB_NAME', 'school_timetable'); // Nome del database, non modificare se non sai cosa stai facendo. define('DB_NAME', 'school_timetable');
} }
// Impostazioni sito generali // Impostazioni sito generali
if (!defined('APP_NAME')) { if (!defined('APP_NAME')) {
define('APP_NAME', 'Orario Scuola'); // Nome del sito define('APP_NAME', 'Orario Scuola');
} }
if (!defined('YEAR')) { if (!defined('YEAR')) {
define('YEAR', '2025/26'); // Anno Scolastico Corrente define('YEAR', '2025/26');
} }
if (!defined('DEV_MODE')) { if (!defined('DEV_MODE')) {
define('DEV_MODE', false); // Modalita' di sviluppo: abilita messaggi di debug aggiuntivi. Imposta su false se sei in produzione define('DEV_MODE', false); // Modalita' di sviluppo
} }
// Impostazioni autenticazione dashboard amministrativa // Impostazioni autenticazione dashboard amministrativa
if (!defined('AUTH_TYPE')) { if (!defined('AUTH_TYPE')) {
define('AUTH_TYPE','local'); // Può essere local (integrata), keycloak define('AUTH_TYPE','local'); // Può essere keycloak o local (integrata)
}
if (!defined('KEYCLOAK_DOMAIN')) {
define('KEYCLOAK_DOMAIN','');
}
if (!defined('KEYCLOAK_REALM')) {
define('KEYCLOAK_REALM','');
}
if (!defined('KEYCLOAK_CLIENT_ID')) {
define('KEYCLOAK_CLIENT_ID','');
}
if (!defined('KEYCLOAK_CLIENT_SECRET')) {
define('KEYCLOAK_CLIENT_SECRET','');
} }
if (!defined('APP_DOMAIN')) { if (!defined('APP_DOMAIN')) {
define('APP_DOMAIN',''); // Dominio del sito (ad esempio orario.yourdomain.com), richiesto per autenticazioni non local define('APP_DOMAIN','');
}
// Impostazioni autenticazione via Keycloak (richiesto solo se AUTH_TYPE sta impostato su keycloak)
if (AUTH_TYPE === 'keycloak') {
if (!defined('KEYCLOAK_DOMAIN')) {
define('KEYCLOAK_DOMAIN',''); // Dominio di Keycloak (ad esempio auth.yourdomain.com)
}
if (!defined('KEYCLOAK_REALM')) {
define('KEYCLOAK_REALM',''); // Realm di Keycloak (ad esempio master)
}
if (!defined('KEYCLOAK_CLIENT_ID')) {
define('KEYCLOAK_CLIENT_ID',''); // Client ID per Keycloak (ad esempio orario)
}
if (!defined('KEYCLOAK_CLIENT_SECRET')) {
define('KEYCLOAK_CLIENT_SECRET',''); // Client Secret per Keycloak (ad esempio abcdefghijklm)
}
} }
?> ?>
``` ```
7. **Apri ``http://localhost`` e goditi il sito** 7. **Apri ``http://localhost`` e goditi il sito**
## Installazione con Docker ## Installazione con Docker
1. Installa Curl, Git e Docker NOTA: L'installazione con Docker è in fase di sviluppo attivo, quindi potrebbe non funzionare.
1. Installa Docker
```bash ```bash
apt install curl git
curl -fsSL https://get.docker.com | bash curl -fsSL https://get.docker.com | bash
``` ```
2. Compila e crea il container: 2. Compila e crea il container:
```bash ```bash
git clone https://git.vichingo455.freeddns.org/emmev-code/orario git clone https://git.vichingo455.freeddns.org/emmev-code/orario
cd orario cd orario
git checkout dev # richiesto per passare alla versione di sviluppo
docker compose up -d --build docker compose up -d --build
``` ```
3. Il container dovrebbe diventare disponibile su ``http://localhost:8080`` 3. Il container dovrebbe diventare disponibile su ``http://localhost:8080``
@@ -126,9 +122,6 @@ docker compose up -d --build
Se sei un utente Docker avanzato e vuoi personalizzare puoi modificare la configurazione di docker nei file ``docker/php/config.php``, ``docker-compose.yml`` e ``Dockerfile`` per adattare tutto al tuo ambiente. Se sei un utente Docker avanzato e vuoi personalizzare puoi modificare la configurazione di docker nei file ``docker/php/config.php``, ``docker-compose.yml`` e ``Dockerfile`` per adattare tutto al tuo ambiente.
Per la maggior parte degli utenti consigliamo di usare la configurazione per Docker predefinita. Per la maggior parte degli utenti consigliamo di usare la configurazione per Docker predefinita.
## Segnalare un problema
Per segnalare un problema puoi usare [Bugzilla](https://bugs.vichingo455.freeddns.org/describecomponents.cgi?product=Orario%20Scuola). Clicca [qui](https://bugs.vichingo455.freeddns.org/describecomponents.cgi?product=Orario%20Scuola) per andare a Bugzilla.
## Licenza ## Licenza
**Orario Scuola, Copyright (C) 2025 EmmeV.** **Orario Scuola, Copyright (C) 2025 EmmeV.**

View File

@@ -1,20 +1,4 @@
<?php <?php
/*
Orario Scuola, Copyright (C) 2025 EmmeV.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see https://www.gnu.org/licenses/.
*/
// Impostazioni Database // Impostazioni Database
if (!defined('DB_HOST')) { if (!defined('DB_HOST')) {
define('DB_HOST', 'db'); define('DB_HOST', 'db');
@@ -60,4 +44,19 @@ if (AUTH_TYPE === 'keycloak') {
define('KEYCLOAK_CLIENT_SECRET',''); // Client Secret per Keycloak (ad esempio abcdefghijklm) define('KEYCLOAK_CLIENT_SECRET',''); // Client Secret per Keycloak (ad esempio abcdefghijklm)
} }
} }
// Impostazioni autenticazione con Google (richieste solo se AUTH_TYPE sta impostato su google)
if (AUTH_TYPE === 'google') {
if (!defined('GOOGLE_CLIENT_ID')) {
define('GOOGLE_CLIENT_ID',''); // Client ID fornito da Google
}
if (!defined('GOOGLE_CLIENT_SECRET')) {
define('GOOGLE_CLIENT_SECRET',''); // Client Secret fornito da Google
}
if (!defined('GOOGLE_ONLY_ALLOWED_DOMAINS')) {
define('GOOGLE_ONLY_ALLOWED_DOMAINS', false); // Attivare (impostare su true) per impostare restrizioni sui domini e-mail consentiti
}
if (!defined('GOOGLE_ALLOWED_DOMAINS')) {
define('GOOGLE_ALLOWED_DOMAINS', ['']); // Domini E-Mail consentiti. Serve abilitare l'opzione GOOGLE_ONLY_ALLOWED_DOMAINS
}
}
?> ?>

View File

@@ -1,20 +1,4 @@
<?php <?php
/*
Orario Scuola, Copyright (C) 2025 EmmeV.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see https://www.gnu.org/licenses/.
*/
session_start(); session_start();
if (!isset($_SESSION['admin'])) { header("Location: login.php"); exit; } if (!isset($_SESSION['admin'])) { header("Location: login.php"); exit; }
include("../lib/db.php"); include("../lib/db.php");
@@ -65,7 +49,7 @@ if (isset($_GET['delete'])) {
echo "<tr> echo "<tr>
<td>{$row['id']}</td> <td>{$row['id']}</td>
<td>{$row['name']}</td> <td>{$row['name']}</td>
<td><a href='classes.php?delete={$row['id']}' class='delete-link' onclick='return confirm(\"Sei sicuro di voler eliminare questa classe?\")'>Elimina</a></td> <td><a href='classes.php?delete={$row['id']}' class='delete-link'>Elimina</a></td>
</tr>"; </tr>";
} }
?> ?>

View File

@@ -1,349 +0,0 @@
<?php
/*
Orario Scuola, Copyright (C) 2025 EmmeV.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see https://www.gnu.org/licenses/.
*/
session_start();
if (!isset($_SESSION['admin'])) { header("Location: login.php"); exit; }
include("../lib/db.php");
$message = "";
$messageType = "";
// Gestione importazione
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST['import'])) {
$classe_codice = trim($_POST['classe_codice']);
$classe_id = intval($_POST['classe_id']);
$api_url = trim($_POST['api_url']);
if (empty($classe_codice) || $classe_id === 0) {
$message = "Compila tutti i campi obbligatori.";
$messageType = "error";
} else {
try {
// Chiama l'API Node.js
$url = $api_url . "?classe=" . urlencode($classe_codice);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new Exception("Errore nella chiamata API (HTTP $httpCode)");
}
$data = json_decode($response, true);
if (!$data || !isset($data['giorni'])) {
throw new Exception("Formato JSON non valido");
}
// Cancella l'orario esistente per questa classe
$stmt = $conn->prepare("DELETE FROM timetable WHERE class_id = ?");
$stmt->bind_param("i", $classe_id);
$stmt->execute();
$stmt->close();
$inserimenti = 0;
$materie_create = [];
// Processa ogni giorno
foreach ($data['giorni'] as $giorno => $ore) {
foreach ($ore as $oraData) {
// Salta ore vuote
if ($oraData['materia'] === null) {
continue;
}
$ora = $oraData['ora'];
$materia = $oraData['materia'];
$docenti = $oraData['docenti'];
$laboratori = $oraData['laboratori']; // Ora è un array
// Se non ci sono docenti, salta (situazione anomala)
if (count($docenti) === 0) {
continue;
}
// Caso 1: Stesso numero di docenti e laboratori → associazione 1:1
if (count($docenti) === count($laboratori) && count($laboratori) > 0) {
foreach ($docenti as $idx => $docente) {
$laboratorio = $laboratori[$idx];
// Cerca/crea materia
$stmt = $conn->prepare("SELECT id FROM subjects WHERE name = ? AND teacher = ? AND room = ?");
$stmt->bind_param("sss", $materia, $docente, $laboratorio);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
$subject_id = $result->fetch_assoc()['id'];
} else {
$stmt2 = $conn->prepare("INSERT INTO subjects (name, teacher, room) VALUES (?, ?, ?)");
$stmt2->bind_param("sss", $materia, $docente, $laboratorio);
$stmt2->execute();
$subject_id = $conn->insert_id;
$stmt2->close();
$materie_create[] = "$materia ($docente - $laboratorio)";
}
$stmt->close();
// Inserisci in timetable
$stmt3 = $conn->prepare("INSERT INTO timetable (class_id, day, hour, subject_id) VALUES (?, ?, ?, ?)");
$stmt3->bind_param("isii", $classe_id, $giorno, $ora, $subject_id);
$stmt3->execute();
$stmt3->close();
$inserimenti++;
}
}
// Caso 2: Più docenti, un laboratorio (o nessuno) → stesso laboratorio per tutti
else if (count($laboratori) <= 1) {
$laboratorio = count($laboratori) > 0 ? $laboratori[0] : null;
foreach ($docenti as $docente) {
// Cerca/crea materia
if ($laboratorio) {
$stmt = $conn->prepare("SELECT id FROM subjects WHERE name = ? AND teacher = ? AND room = ?");
$stmt->bind_param("sss", $materia, $docente, $laboratorio);
} else {
$stmt = $conn->prepare("SELECT id FROM subjects WHERE name = ? AND teacher = ? AND (room IS NULL OR room = '')");
$stmt->bind_param("ss", $materia, $docente);
}
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
$subject_id = $result->fetch_assoc()['id'];
} else {
$stmt2 = $conn->prepare("INSERT INTO subjects (name, teacher, room) VALUES (?, ?, ?)");
$stmt2->bind_param("sss", $materia, $docente, $laboratorio);
$stmt2->execute();
$subject_id = $conn->insert_id;
$stmt2->close();
$materie_create[] = "$materia ($docente" . ($laboratorio ? " - $laboratorio" : "") . ")";
}
$stmt->close();
// Inserisci in timetable
$stmt3 = $conn->prepare("INSERT INTO timetable (class_id, day, hour, subject_id) VALUES (?, ?, ?, ?)");
$stmt3->bind_param("isii", $classe_id, $giorno, $ora, $subject_id);
$stmt3->execute();
$stmt3->close();
$inserimenti++;
}
}
// Caso 3: Più laboratori che docenti → usa il primo laboratorio per tutti
else {
$laboratorio = $laboratori[0];
foreach ($docenti as $docente) {
$stmt = $conn->prepare("SELECT id FROM subjects WHERE name = ? AND teacher = ? AND room = ?");
$stmt->bind_param("sss", $materia, $docente, $laboratorio);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
$subject_id = $result->fetch_assoc()['id'];
} else {
$stmt2 = $conn->prepare("INSERT INTO subjects (name, teacher, room) VALUES (?, ?, ?)");
$stmt2->bind_param("sss", $materia, $docente, $laboratorio);
$stmt2->execute();
$subject_id = $conn->insert_id;
$stmt2->close();
$materie_create[] = "$materia ($docente - $laboratorio)";
}
$stmt->close();
$stmt3 = $conn->prepare("INSERT INTO timetable (class_id, day, hour, subject_id) VALUES (?, ?, ?, ?)");
$stmt3->bind_param("isii", $classe_id, $giorno, $ora, $subject_id);
$stmt3->execute();
$stmt3->close();
$inserimenti++;
}
}
}
}
$message = "Importazione completata con successo!<br>";
$message .= "- Inserite $inserimenti ore di lezione<br>";
if (count($materie_create) > 0) {
$message .= "- Create " . count($materie_create) . " nuove materie";
}
$messageType = "success";
} catch (Exception $e) {
$message = "Errore durante l'importazione: " . htmlspecialchars($e->getMessage());
$messageType = "error";
}
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Importa Orario</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<style>
.import-form {
max-width: 600px;
margin: 20px auto;
padding: 20px;
background: #f9f9f9;
border-radius: 8px;
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
.form-group input,
.form-group select {
width: 100%;
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
.form-group small {
display: block;
margin-top: 5px;
color: #666;
font-size: 0.9em;
}
.message {
padding: 15px;
margin: 20px 0;
border-radius: 5px;
}
.message.success {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.message.error {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.warning-box {
background: #fff3cd;
border: 1px solid #ffc107;
padding: 15px;
margin: 20px 0;
border-radius: 5px;
}
.warning-box strong {
color: #856404;
}
</style>
</head>
<body>
<div class="navbar">
<div class="logo">Admin Dashboard</div>
<div class="links">
<a href="index.php">Dashboard</a>
<a href="logout.php">Logout</a>
</div>
</div>
<div class="admin-container">
<h1>Importa Orario da Sistema Esterno</h1>
<a href="index.php" class="back-link">⬅ Torna al Dashboard</a>
<?php if ($message): ?>
<div class="message <?php echo $messageType; ?>">
<?php echo $message; ?>
</div>
<?php endif; ?>
<div class="warning-box">
<strong>Attenzione:</strong> L'importazione cancellerà l'orario esistente della classe selezionata
e lo sostituirà con i dati importati dal sistema esterno.
Verranno create automaticamente le materie mancanti.
</div>
<div class="import-form">
<h2>Configura Importazione</h2>
<form method="POST">
<div class="form-group">
<label for="classe_id">Classe di destinazione *</label>
<select name="classe_id" id="classe_id" required>
<option value="">-- Seleziona classe --</option>
<?php
$res = $conn->query("SELECT * FROM classes ORDER BY name ASC");
while ($row = $res->fetch_assoc()) {
echo "<option value='{$row['id']}'>{$row['name']}</option>";
}
?>
</select>
<small>Classe nel tuo database dove importare l'orario</small>
</div>
<div class="form-group">
<label for="classe_codice">Codice classe sorgente *</label>
<input type="text" name="classe_codice" id="classe_codice"
placeholder="es: 1A, 2B, 3BIN..." required>
<small>Codice della classe nel sistema esterno</small>
</div>
<div class="form-group">
<label for="api_url">URL API Node.js</label>
<input type="text" name="api_url" id="api_url"
value="http://localhost:3006/classe" required>
<small>Endpoint dell'API Node.js per lo scraping</small>
</div>
<button type="submit" name="import" style="width: 100%; padding: 12px; font-size: 16px;">
🔄 Importa Orario
</button>
</form>
</div>
<div class="admin-container" style="margin-top: 30px;">
<h3>Come funziona l'importazione</h3>
<ol>
<li>Assicurati che il server Node.js sia avviato (<code>node server.js</code>)</li>
<li>Seleziona la classe di destinazione nel tuo database</li>
<li>Inserisci il codice della classe nel sistema esterno (es: 3BIN, 1A, 5AINF)</li>
<li>Clicca su "Importa Orario"</li>
<li>Il sistema cancellerà l'orario esistente e importerà i nuovi dati</li>
</ol>
<h3>Gestione casi speciali</h3>
<ul>
<li><strong>Più docenti, più laboratori</strong>: Associazione 1:1 (docente1→lab1, docente2→lab2)</li>
<li><strong>Più docenti, un laboratorio</strong>: Stesso laboratorio per tutti i docenti</li>
<li><strong>Più docenti, nessun laboratorio</strong>: Nessun laboratorio per tutti</li>
<li><strong>Un docente, più laboratori</strong>: Viene usato il primo laboratorio</li>
</ul>
</div>
<p style="text-align: center; margin-top: 30px;">
Copyright (C) 2025 EmmeV. - Released under <a href="https://git.vichingo455.freeddns.org/emmev-code/orario/src/branch/stable/LICENSE.txt" target="_blank">GNU AGPL 3.0 License</a>.
</p>
</div>
</body>
</html>

View File

@@ -1,20 +1,4 @@
<?php <?php
/*
Orario Scuola, Copyright (C) 2025 EmmeV.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see https://www.gnu.org/licenses/.
*/
include_once __DIR__ . '/../config/config.php'; include_once __DIR__ . '/../config/config.php';
session_start(); session_start();
if (!isset($_SESSION['admin'])) { if (!isset($_SESSION['admin'])) {
@@ -41,12 +25,11 @@ if (!isset($_SESSION['admin'])) {
<!-- Contenuto Dashboard --> <!-- Contenuto Dashboard -->
<div class="dashboard"> <div class="dashboard">
<h1>Benvenuto, <?php echo htmlspecialchars($_SESSION['admin']); ?>!</h1> <h1>Benvenuto, <?php echo $_SESSION['admin']; ?>!</h1>
<p> <p>
<a href="classes.php">Gestisci Classi</a> <a href="classes.php">Gestisci Classi</a>
<a href="subjects.php">Gestisci Materie</a> <a href="subjects.php">Gestisci Materie</a>
<a href="timetable.php">Gestisci Orario</a> <a href="timetable.php">Gestisci Orario</a>
<a href="importer.php" style="background: #28a745;">🔄 Importa Orario</a>
<?php <?php
if ($_SESSION['auth_type'] === 'local') { if ($_SESSION['auth_type'] === 'local') {
echo '<a href="password.php">Cambia Password</a>'; echo '<a href="password.php">Cambia Password</a>';
@@ -65,3 +48,4 @@ if (!isset($_SESSION['admin'])) {
</div> </div>
</body> </body>
</html> </html>

View File

@@ -1,20 +1,4 @@
<?php <?php
/*
Orario Scuola, Copyright (C) 2025 EmmeV.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see https://www.gnu.org/licenses/.
*/
use Jumbojett\OpenIDConnectClient; use Jumbojett\OpenIDConnectClient;
require 'vendor/autoload.php'; require 'vendor/autoload.php';
session_start(); session_start();
@@ -80,12 +64,12 @@ else if (AUTH_TYPE === 'keycloak') {
try { try {
// Configura il client Keycloak // Configura il client Keycloak
$oidc = new OpenIDConnectClient( $oidc = new OpenIDConnectClient(
'https://' . KEYCLOAK_DOMAIN . '/realms/' . KEYCLOAK_REALM . '/', 'https://' + KEYCLOAK_DOMAIN + '/realms/' + KEYCLOAK_REALM + '/',
KEYCLOAK_CLIENT_ID, KEYCLOAK_CLIENT_ID,
KEYCLOAK_CLIENT_SECRET KEYCLOAK_CLIENT_SECRET
); );
// Redirect post-login // Redirect post-login
$oidc->setRedirectURL('https://' . APP_DOMAIN . '/admin/login.php'); $oidc->setRedirectURL('https://' + APP_DOMAIN + '/admin/login.php');
$oidc->authenticate(); $oidc->authenticate();
$userinfo = $oidc->getVerifiedClaims(); $userinfo = $oidc->getVerifiedClaims();
$_SESSION['admin'] = $userinfo->preferred_username; $_SESSION['admin'] = $userinfo->preferred_username;
@@ -129,4 +113,97 @@ HTML;
exit; exit;
} }
} }
else if (AUTH_TYPE === 'google') {
try {
$oidc = new OpenIDConnectClient(
'https://accounts.google.com',
GOOGLE_CLIENT_ID,
GOOGLE_CLIENT_SECRET
);
$oidc->setRedirectURL(GOOGLE_REDIRECT_URI);
$oidc->addScope(['openid', 'email', 'profile']);
// Callback da Google
if (isset($_GET['code'])) {
$oidc->authenticate();
$email = $oidc->requestUserInfo('email');
$domain = substr(strrchr($email, "@"), 1);
if (!GOOGLE_ONLY_ALLOWED_DOMAINS || in_array($domain, GOOGLE_ALLOWED_DOMAINS)) {
$_SESSION['admin'] = $email;
$_SESSION['auth_type'] = 'google';
header("Location: index.php");
exit;
} else {
http_response_code(403);
echo <<<HTML
<!DOCTYPE html>
<html>
<head>
<title>Login Admin</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="navbar">
<div class="logo">Admin Dashboard</div>
<div class="links">
<a href="/">Torna al sito</a>
</div>
</div>
<!-- Container login -->
<div class="login-container">
<h1>Login Admin</h1>
HTML;
echo "<br><div class='error'>Non sei autorizzato ad accedere a questa pagina</div>";
echo <<<HTML
</div>
<p style="text-align: center;">Copyright (C) 2025 EmmeV. - Released under <a href="https://git.vichingo455.freeddns.org/emmev-code/orario/src/branch/stable/LICENSE.txt" target="_blank">GNU AGPL 3.0 License</a>.</p>
</body>
</html>
HTML;
exit;
}
}
} catch (Exception $e) {
http_response_code(500);
echo <<<HTML
<!DOCTYPE html>
<html>
<head>
<title>Login Admin</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="navbar">
<div class="logo">Admin Dashboard</div>
<div class="links">
<a href="/">Torna al sito</a>
</div>
</div>
<!-- Container login -->
<div class="login-container">
<h1>Login Admin</h1>
HTML;
if (DEV_MODE) {
echo "<br><div class='error'>Errore durante l'autenticazione con Google. Assicurati di avere impostato i vari parametri correttamente. Ulteriori dettagli: " . $e . "</div>";
} else {
echo "<br><div class='error'>Errore durante l'autenticazione con Google. Contatta l'amministratore del sito.</div>";
}
echo <<<HTML
</div>
<p style="text-align: center;">Copyright (C) 2025 EmmeV. - Released under <a href="https://git.vichingo455.freeddns.org/emmev-code/orario/src/branch/stable/LICENSE.txt" target="_blank">GNU AGPL 3.0 License</a>.</p>
</body>
</html>
HTML;
exit;
}
}
?> ?>

View File

@@ -1,25 +1,9 @@
<?php <?php
/*
Orario Scuola, Copyright (C) 2025 EmmeV.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see https://www.gnu.org/licenses/.
*/
include("../config/config.php"); include("../config/config.php");
session_start(); session_start();
session_destroy(); session_destroy();
if (AUTH_TYPE === 'local') if (AUTH_TYPE === 'local' || AUTH_TYPE === 'google')
header("Location: /index.php"); header("Location: /index.php");
else if (AUTH_TYPE === 'keycloak') else if (AUTH_TYPE === 'keycloak')
header('Location: https://' . KEYCLOAK_DOMAIN . '/realms/' . KEYCLOAK_REALM . '/protocol/openid-connect/logout?post_logout_redirect_uri=https://' . APP_DOMAIN . '&client_id=' . KEYCLOAK_CLIENT_ID); header('Location: https://' + KEYCLOAK_DOMAIN + '/realms/' + KEYCLOAK_REALM + '/protocol/openid-connect/logout?post_logout_redirect_uri=https://' + APP_DOMAIN + '&client_id=' + KEYCLOAK_CLIENT_ID);
?> ?>

View File

@@ -1,20 +1,4 @@
<?php <?php
/*
Orario Scuola, Copyright (C) 2025 EmmeV.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see https://www.gnu.org/licenses/.
*/
session_start(); session_start();
include("../lib/db.php"); include("../lib/db.php");

View File

@@ -1,20 +1,4 @@
/* /* Body e font */
Orario Scuola, Copyright (C) 2025 EmmeV.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see https://www.gnu.org/licenses/.
*/
/* ===== BASE ===== */
body { body {
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
background-color: #f0f2f5; background-color: #f0f2f5;
@@ -23,7 +7,7 @@ body {
padding: 20px; padding: 20px;
} }
/* ===== NAVBAR ===== */ /* Navbar */
.navbar { .navbar {
background-color: #2c3e50; background-color: #2c3e50;
padding: 10px 20px; padding: 10px 20px;
@@ -36,15 +20,6 @@ body {
box-shadow: 0 2px 5px rgba(0,0,0,0.1); box-shadow: 0 2px 5px rgba(0,0,0,0.1);
} }
.navbar.text-center {
justify-content: center;
}
.navbar .logo {
font-size: 1.3em;
font-weight: bold;
}
.navbar a { .navbar a {
color: #fff; color: #fff;
text-decoration: none; text-decoration: none;
@@ -57,38 +32,27 @@ body {
color: #f39c12; color: #f39c12;
} }
/* ===== CONTAINERS ===== */ .navbar .logo {
.dashboard, font-size: 1.3em;
.admin-container, font-weight: bold;
.login-container { }
/* Dashboard container */
.dashboard {
max-width: 800px; max-width: 800px;
margin: 0 auto; margin: 0 auto;
text-align: center;
background: #fff; background: #fff;
padding: 30px; padding: 30px;
border-radius: 10px; border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1); box-shadow: 0 2px 10px rgba(0,0,0,0.1);
} }
.login-container { .dashboard h1 {
max-width: 400px;
margin: 80px auto;
text-align: center;
}
.dashboard {
text-align: center;
}
/* ===== HEADINGS ===== */
.dashboard h1,
.admin-container h1,
.login-container h1 {
margin-bottom: 20px; margin-bottom: 20px;
color: #2c3e50; color: #2c3e50;
text-align: center;
} }
/* ===== LINKS ===== */
.dashboard a { .dashboard a {
display: inline-block; display: inline-block;
margin: 10px; margin: 10px;
@@ -102,8 +66,26 @@ body {
.dashboard a:hover { .dashboard a:hover {
background-color: #f39c12; background-color: #f39c12;
color: #fff;
}
/* Container principale */
.admin-container {
max-width: 800px;
margin: 0 auto;
background: #fff;
padding: 30px;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
} }
/* Titolo */
.admin-container h1 {
text-align: center;
color: #2c3e50;
margin-bottom: 20px;
}
/* Link ritorno */
.admin-container a.back-link { .admin-container a.back-link {
display: inline-block; display: inline-block;
margin-bottom: 15px; margin-bottom: 15px;
@@ -116,6 +98,55 @@ body {
color: #f39c12; color: #f39c12;
} }
/* Form aggiungi classe */
.admin-container form {
margin-bottom: 20px;
text-align: center;
}
.admin-container input[type="text"],
.admin-container input[type="password"] {
padding: 8px 12px;
border: 1px solid #ccc;
border-radius: 6px;
width: 200px;
margin-right: 10px;
}
.admin-container button {
padding: 8px 15px;
border: none;
background-color: #1f618d;
color: #fff;
border-radius: 6px;
cursor: pointer;
transition: background-color 0.2s;
}
.admin-container button:hover {
background-color: #f39c12;
}
/* Tabella */
.admin-container table {
width: 100%;
border-collapse: collapse;
}
.admin-container th, .admin-container td {
border: 1px solid #ccc;
padding: 10px;
text-align: center;
}
.admin-container th {
background-color: #eee;
}
.admin-container tr:hover td {
background-color: #f7f7f7;
}
.admin-container a.delete-link { .admin-container a.delete-link {
color: #e74c3c; color: #e74c3c;
font-weight: bold; font-weight: bold;
@@ -126,34 +157,125 @@ body {
.admin-container a.delete-link:hover { .admin-container a.delete-link:hover {
color: #c0392b; color: #c0392b;
} }
/* Login container */
.login-container {
max-width: 400px;
margin: 80px auto;
background: #fff;
padding: 30px;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
text-align: center;
}
.admin-container a.edit-link { /* Titolo */
color: #4d5cdb; .login-container h1 {
margin-bottom: 20px;
color: #2c3e50;
}
/* Input */
.login-container input[type="text"],
.login-container input[type="password"] {
width: 90%;
padding: 10px;
margin: 10px 0;
border-radius: 6px;
border: 1px solid #ccc;
font-size: 1em;
}
/* Pulsante */
.login-container button {
padding: 10px 20px;
background-color: #1f618d;
color: #fff;
border: none;
border-radius: 6px;
cursor: pointer;
transition: background-color 0.2s;
font-size: 1em;
}
.login-container button:hover {
background-color: #f39c12;
color: #fff;
}
/* Messaggio errore */
.login-container .error {
color: #e74c3c;
font-weight: bold;
margin-bottom: 10px;
}
/* Navbar minima per login */
.navbar {
background-color: #2c3e50;
padding: 10px 20px;
color: #fff;
text-align: center;
border-radius: 0 0 10px 10px;
margin-bottom: 30px;
}
/* Riutilizziamo .admin-container, h1, navbar già definiti */
/* Form Gestione Materie */
.admin-container form input[type="text"] {
padding: 8px 12px;
border: 1px solid #ccc;
border-radius: 6px;
margin: 5px;
width: 200px;
}
.admin-container form button {
padding: 8px 20px;
background-color: #1f618d;
color: #fff;
border: none;
border-radius: 6px;
cursor: pointer;
transition: background-color 0.2s;
}
.admin-container form button:hover {
background-color: #f39c12;
color: #fff;
}
/* Tabella Materie */
.admin-container table {
width: 100%;
border-collapse: collapse;
margin-top: 15px;
}
.admin-container th, .admin-container td {
border: 1px solid #ccc;
padding: 10px;
text-align: center;
}
.admin-container th {
background-color: #eee;
}
.admin-container tr:hover td {
background-color: #f7f7f7;
}
.admin-container a.delete-link {
color: #e74c3c;
font-weight: bold; font-weight: bold;
text-decoration: none; text-decoration: none;
transition: color 0.2s; transition: color 0.2s;
} }
.admin-container a.edit-link:hover { .admin-container a.delete-link:hover {
color: #3a2bc0; color: #c0392b;
} }
/* Form gestione orario */
.admin-container form a.cancel-edit {
display: inline-block;
margin: 10px;
padding: 12px 25px;
background-color: #1f618d;
color: #fff;
text-decoration: none;
border-radius: 8px;
transition: background-color 0.2s;
}
.admin-container form a.cancel-edit:hover {
background-color: #f39c12;
}
/* ===== FORMS ===== */
.admin-container form { .admin-container form {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
@@ -162,28 +284,6 @@ body {
margin-bottom: 20px; margin-bottom: 20px;
} }
.admin-container input[type="text"],
.admin-container input[type="password"],
.login-container input[type="text"],
.login-container input[type="password"] {
padding: 10px 12px;
border: 1px solid #ccc;
border-radius: 6px;
font-size: 1em;
}
.admin-container input[type="text"],
.admin-container input[type="password"] {
width: 200px;
margin: 5px;
}
.login-container input[type="text"],
.login-container input[type="password"] {
width: 90%;
margin: 10px 0;
}
.admin-container form select { .admin-container form select {
padding: 8px 12px; padding: 8px 12px;
border-radius: 6px; border-radius: 6px;
@@ -191,74 +291,45 @@ body {
min-width: 120px; min-width: 120px;
} }
.admin-container button, .admin-container form button {
.login-container button { padding: 8px 20px;
padding: 10px 20px;
border: none;
background-color: #1f618d; background-color: #1f618d;
color: #fff; color: #fff;
border: none;
border-radius: 6px; border-radius: 6px;
cursor: pointer; cursor: pointer;
transition: background-color 0.2s; transition: background-color 0.2s;
font-size: 1em;
} }
.admin-container button:hover, .admin-container form button:hover {
.login-container button:hover {
background-color: #f39c12; background-color: #f39c12;
color: #fff;
} }
/* ===== TABLES ===== */ /* Titolo */
.table-container { .admin-container h1 {
width: 100%;
overflow-x: auto;
}
.admin-container table,
.responsive-table {
width: 100%;
border-collapse: collapse;
margin-top: 15px;
}
.admin-container th,
.admin-container td,
.responsive-table th,
.responsive-table td {
border: 1px solid #ccc;
padding: 10px;
text-align: center; text-align: center;
color: #2c3e50;
margin-bottom: 20px;
} }
.responsive-table th, /* Link ritorno */
.responsive-table td { .admin-container a.back-link {
text-align: left; display: inline-block;
padding: 8px; margin-bottom: 15px;
} text-decoration: none;
color: #1f618d;
.admin-container th,
.responsive-table th {
background-color: #eee;
}
.admin-container tr:hover td {
background-color: #f7f7f7;
}
/* ===== MESSAGES ===== */
.login-container .error {
color: #e74c3c;
font-weight: bold; font-weight: bold;
margin-bottom: 10px;
} }
/* ===== RESPONSIVE DESIGN ===== */ .admin-container a.back-link:hover {
@media (max-width: 768px) { color: #f39c12;
body { }
padding: 10px;
}
/* Form responsive */ /* Mobile responsive */
@media (max-width: 768px) {
/* Form input gestione orario */
.admin-container form { .admin-container form {
flex-direction: column; flex-direction: column;
align-items: stretch; align-items: stretch;
@@ -272,27 +343,22 @@ body {
margin: 5px 0; margin: 5px 0;
} }
/* Tabelle responsive */ /* Tabella */
.admin-container table, .admin-container table,
.responsive-table {
display: block;
}
.admin-container thead, .admin-container thead,
.responsive-table thead {
display: none;
}
.admin-container tbody, .admin-container tbody,
.responsive-table tbody, .admin-container th,
.admin-container tr, .admin-container td,
.responsive-table tr { .admin-container tr {
display: block; display: block;
width: 100%; width: 100%;
} }
.admin-container tr, .admin-container thead {
.responsive-table tr { display: none; /* Nasconde intestazioni */
}
.admin-container tr {
margin-bottom: 15px; margin-bottom: 15px;
border: 1px solid #ddd; border: 1px solid #ddd;
border-radius: 8px; border-radius: 8px;
@@ -301,39 +367,28 @@ body {
box-shadow: 0 1px 5px rgba(0,0,0,0.05); box-shadow: 0 1px 5px rgba(0,0,0,0.05);
} }
.admin-container td, .admin-container td {
.responsive-table td {
display: block;
text-align: left; text-align: left;
padding: 8px 10px;
padding-left: 50%; padding-left: 50%;
position: relative; position: relative;
border: none; border: none;
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
word-wrap: break-word; display: flex;
white-space: normal; justify-content: space-between;
max-width: 100%; padding: 8px 10px;
} }
.admin-container td:last-child, .admin-container td::before {
.responsive-table td:last-child {
border-bottom: none;
}
.admin-container td::before,
.responsive-table td::before {
content: attr(data-label); content: attr(data-label);
position: absolute; position: absolute;
left: 10px; left: 10px;
top: 8px;
width: 45%; width: 45%;
font-weight: bold; font-weight: bold;
white-space: normal; white-space: nowrap;
color: #333;
} }
.responsive-table td span { .admin-container td:last-child {
display: block; border-bottom: 0;
} }
.admin-container a.delete-link { .admin-container a.delete-link {
@@ -342,15 +397,14 @@ body {
} }
} }
/* Extra piccolo schermo */
@media (max-width: 480px) { @media (max-width: 480px) {
.admin-container td::before, .admin-container td::before {
.responsive-table td::before {
width: 50%; width: 50%;
font-size: 0.9em; font-size: 0.9em;
} }
.admin-container td, .admin-container td {
.responsive-table td {
font-size: 0.9em; font-size: 0.9em;
padding: 6px 8px; padding: 6px 8px;
} }
@@ -362,3 +416,70 @@ body {
font-size: 0.95em; font-size: 0.95em;
} }
} }
.table-container {
width: 100%;
overflow-x: auto;
}
.responsive-table {
width: 100%;
border-collapse: collapse;
}
.responsive-table th,
.responsive-table td {
border: 1px solid #ccc;
padding: 8px;
text-align: left;
}
.responsive-table th {
background: #f4f4f4;
}
/* Modalità mobile */
@media (max-width: 768px) {
.responsive-table thead {
display: none; /* nasconde lintestazione */
}
.responsive-table tr {
display: block;
margin-bottom: 15px;
border: 1px solid #ddd;
border-radius: 8px;
padding: 10px;
background: #fff;
}
.responsive-table td {
display: block;
justify-content: space-between;
padding: 8px 5px;
padding-top: 30px;
border: none;
border-bottom: 1px solid #eee;
word-wrap: break-word;
white-space: normal;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
}
.responsive-table td:last-child {
border-bottom: none;
}
.responsive-table td::before {
content: attr(data-label);
font-weight: bold;
margin-right: 10px;
color: #333;
position: absolute;
left: 10px;
top: 10px;
width: 45%;
white-space: normal; /* permette a "Materia" di andare a capo */
font-weight: bold;
}
.response-table td span {
display: block; /* forza l'output del contenuto su una riga separata */
}
}

View File

@@ -1,65 +1,22 @@
<?php <?php
/*
Orario Scuola, Copyright (C) 2025 EmmeV.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see https://www.gnu.org/licenses/.
*/
session_start(); session_start();
if (!isset($_SESSION['admin'])) { header("Location: login.php"); exit; } if (!isset($_SESSION['admin'])) { header("Location: login.php"); exit; }
include("../lib/db.php"); include("../lib/db.php");
// FIX: Usa prepared statements per sicurezza if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['name'])) {
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['name']) && !isset($_POST['update'])) {
$name = $_POST['name']; $name = $_POST['name'];
$teacher = $_POST['teacher']; $teacher = $_POST['teacher'];
$room = $_POST['room']; $room = $_POST['room'];
if (!empty($name)) { if (!empty($name)) {
$stmt = $conn->prepare("INSERT INTO subjects (name, teacher, room) VALUES (?, ?, ?)"); $conn->query("INSERT INTO subjects (name,teacher,room) VALUES ('$name','$teacher','$room')");
$stmt->bind_param("sss", $name, $teacher, $room);
$stmt->execute();
$stmt->close();
} }
header("Location: subjects.php"); header("Location: subjects.php"); exit;
exit;
} }
// FIX: Aggiunto redirect dopo update
if(isset($_POST['update'])){
$id = intval($_POST['id']);
$name = $_POST['name'];
$teacher = $_POST['teacher'];
$room = $_POST['room'];
$stmt = $conn->prepare("UPDATE subjects SET name=?, teacher=?, room=? WHERE id=?");
$stmt->bind_param("sssi", $name, $teacher, $room, $id);
$stmt->execute();
$stmt->close();
header("Location: subjects.php");
exit;
}
// FIX: Usa prepared statement anche per delete
if (isset($_GET['delete'])) { if (isset($_GET['delete'])) {
$id = intval($_GET['delete']); $id = intval($_GET['delete']);
$stmt = $conn->prepare("DELETE FROM subjects WHERE id=?"); $conn->query("DELETE FROM subjects WHERE id=$id");
$stmt->bind_param("i", $id); header("Location: subjects.php"); exit;
$stmt->execute();
$stmt->close();
header("Location: subjects.php");
exit;
} }
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
@@ -84,56 +41,56 @@ if (isset($_GET['delete'])) {
<h1>Gestisci Materie</h1> <h1>Gestisci Materie</h1>
<a href="index.php" class="back-link">⬅ Torna al Dashboard</a> <a href="index.php" class="back-link">⬅ Torna al Dashboard</a>
<?php
// Mostra form di modifica solo se richiesto
if(isset($_GET['edit'])){
$id = intval($_GET['edit']);
$stmt = $conn->prepare("SELECT * FROM subjects WHERE id=?");
$stmt->bind_param("i", $id);
$stmt->execute();
$res = $stmt->get_result();
if($res->num_rows > 0){
$subject = $res->fetch_assoc();
?>
<h3>Modifica materia</h3>
<form method="post" action="subjects.php">
<input type="hidden" name="id" value="<?php echo $subject['id']; ?>">
<label>Materia:</label>
<input type="text" name="name" value="<?php echo htmlspecialchars($subject['name']); ?>" required><br>
<label>Docente:</label>
<input type="text" name="teacher" value="<?php echo htmlspecialchars($subject['teacher']); ?>" required><br>
<label>Laboratorio (opzionale):</label>
<input type="text" name="room" value="<?php echo htmlspecialchars($subject['room']); ?>"><br>
<button type="submit" name="update">Salva modifiche</button>
<a class="cancel-edit" href="subjects.php" style="margin-left: 10px;">Annulla</a>
</form>
<hr>
<?php
}
$stmt->close();
}
?>
<h2>Aggiungi Nuova Materia</h2>
<form method="POST"> <form method="POST">
<input type="text" name="name" placeholder="Materia" required> <input type="text" name="name" placeholder="Materia" required>
<input type="text" name="teacher" placeholder="Docente" required> <input type="text" name="teacher" placeholder="Docente" required>
<input type="text" name="room" placeholder="Laboratorio (opzionale)"> <input type="text" name="room" placeholder="Laboratorio (opzionale)">
<button type="submit">Aggiungi</button> <button type="submit">Aggiungi</button>
</form> </form>
<?php
// 1. Aggiornamento dati
if(isset($_POST['update'])){
$id = intval($_POST['id']);
$name = $conn->real_escape_string($_POST['name']);
$teacher = $conn->real_escape_string($_POST['teacher']);
$room = $conn->real_escape_string($_POST['room']);
<h2>Elenco Materie</h2> $conn->query("UPDATE subjects
SET name='$name', teacher='$teacher', room='$room'
WHERE id=$id");
}
// 2. Mostrare il form se edit richiesto
if(isset($_GET['edit'])){
$id = intval($_GET['edit']);
$res = $conn->query("SELECT * FROM subjects WHERE id=$id");
if($res->num_rows > 0){
$subject = $res->fetch_assoc();
?>
<h3>Modifica materia</h3>
<form method="post" action="subjects.php">
<input type="hidden" name="id" value="<?php echo $subject['id']; ?>">
<label>Materia:</label>
<input type="text" name="name" value="<?php echo htmlspecialchars($subject['name']); ?>"><br>
<label>Docente:</label>
<input type="text" name="teacher" value="<?php echo htmlspecialchars($subject['teacher']); ?>"><br>
<label>Aula:</label>
<input type="text" name="room" value="<?php echo htmlspecialchars($subject['room']); ?>"><br>
<button type="submit" name="update">Salva modifiche</button>
</form>
<?php
}
}
?>
<table> <table>
<tr> <tr>
<th>ID</th> <th>ID</th>
<th>Materia</th> <th>Materia</th>
<th>Docente</th> <th>Docente</th>
<th>Laboratorio</th> <th>Aula</th>
<th>Azione</th> <th>Azione</th>
</tr> </tr>
<?php <?php
@@ -141,12 +98,12 @@ if (isset($_GET['delete'])) {
while($row=$res->fetch_assoc()){ while($row=$res->fetch_assoc()){
echo "<tr> echo "<tr>
<td>{$row['id']}</td> <td>{$row['id']}</td>
<td>" . htmlspecialchars($row['name']) . "</td> <td>{$row['name']}</td>
<td>" . htmlspecialchars($row['teacher']) . "</td> <td>{$row['teacher']}</td>
<td>" . htmlspecialchars($row['room']) . "</td> <td>{$row['room']}</td>
<td> <td>
<a href='subjects.php?edit={$row['id']}' class='edit-link'>Modifica</a> | <a href='subjects.php?edit={$row['id']}' class='edit-link'>Modifica</a> |
<a href='subjects.php?delete={$row['id']}' class='delete-link' onclick='return confirm(\"Sei sicuro di voler eliminare questa materia?\")'>Elimina</a> <a href='subjects.php?delete={$row['id']}' class='delete-link'>Elimina</a>
</td> </td>
</tr>"; </tr>";
} }

View File

@@ -1,20 +1,4 @@
<?php <?php
/*
Orario Scuola, Copyright (C) 2025 EmmeV.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see https://www.gnu.org/licenses/.
*/
session_start(); session_start();
if (!isset($_SESSION['admin'])) { header("Location: login.php"); exit; } if (!isset($_SESSION['admin'])) { header("Location: login.php"); exit; }
include("../lib/db.php"); include("../lib/db.php");

View File

@@ -1,20 +1,4 @@
<?php <?php
/*
Orario Scuola, Copyright (C) 2025 EmmeV.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see https://www.gnu.org/licenses/.
*/
session_start(); session_start();
include("../lib/db.php"); include("../lib/db.php");

View File

@@ -1,20 +1,4 @@
<?php <?php
/*
Orario Scuola, Copyright (C) 2025 EmmeV.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see https://www.gnu.org/licenses/.
*/
// Impostazioni Database // Impostazioni Database
if (!defined('DB_HOST')) { if (!defined('DB_HOST')) {
define('DB_HOST', '<MYSQL_HOST>'); // Host del database (ad esempio localhost) define('DB_HOST', '<MYSQL_HOST>'); // Host del database (ad esempio localhost)
@@ -40,7 +24,7 @@ if (!defined('DEV_MODE')) {
} }
// Impostazioni autenticazione dashboard amministrativa // Impostazioni autenticazione dashboard amministrativa
if (!defined('AUTH_TYPE')) { if (!defined('AUTH_TYPE')) {
define('AUTH_TYPE','local'); // Può essere local (integrata), keycloak define('AUTH_TYPE','local'); // Può essere local (integrata), keycloak, google
} }
if (!defined('APP_DOMAIN')) { if (!defined('APP_DOMAIN')) {
define('APP_DOMAIN',''); // Dominio del sito (ad esempio orario.yourdomain.com), richiesto per autenticazioni non local define('APP_DOMAIN',''); // Dominio del sito (ad esempio orario.yourdomain.com), richiesto per autenticazioni non local
@@ -60,4 +44,19 @@ if (AUTH_TYPE === 'keycloak') {
define('KEYCLOAK_CLIENT_SECRET',''); // Client Secret per Keycloak (ad esempio abcdefghijklm) define('KEYCLOAK_CLIENT_SECRET',''); // Client Secret per Keycloak (ad esempio abcdefghijklm)
} }
} }
// Impostazioni autenticazione con Google (richieste solo se AUTH_TYPE sta impostato su google)
if (AUTH_TYPE === 'google') {
if (!defined('GOOGLE_CLIENT_ID')) {
define('GOOGLE_CLIENT_ID',''); // Client ID fornito da Google
}
if (!defined('GOOGLE_CLIENT_SECRET')) {
define('GOOGLE_CLIENT_SECRET',''); // Client Secret fornito da Google
}
if (!defined('GOOGLE_ONLY_ALLOWED_DOMAINS')) {
define('GOOGLE_ONLY_ALLOWED_DOMAINS', false); // Attivare (impostare su true) per impostare restrizioni sui domini e-mail consentiti
}
if (!defined('GOOGLE_ALLOWED_DOMAINS')) {
define('GOOGLE_ALLOWED_DOMAINS', ['']); // Domini E-Mail consentiti. Serve abilitare l'opzione GOOGLE_ONLY_ALLOWED_DOMAINS
}
}
?> ?>

View File

@@ -1,142 +1,109 @@
/*
Orario Scuola, Copyright (C) 2025 EmmeV.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see https://www.gnu.org/licenses/.
*/
/* Base styles */ /* Base styles */
body { body {
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
padding: 15px; padding: 15px;
background-color: #f0f2f5; background-color: #f0f2f5;
color: #333; color: #333;
margin: 0; margin: 0;
} }
h1, h2 { h1, h2 {
text-align: center; text-align: center;
margin: 10px 0 20px 0; margin: 10px 0 20px 0;
} }
h1 { h1 { color: #2c3e50; font-size: 1.8em; }
color: #2c3e50; h2 { color: #34495e; font-size: 1.4em; }
font-size: 1.8em;
}
h2 {
color: #34495e;
font-size: 1.4em;
}
/* Grid layout */ /* Grid layout */
.grid { .grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 15px; gap: 15px;
max-width: 1000px; max-width: 1000px;
margin: 0 auto; margin: 0 auto;
} }
/* Card styles */ /* Card styles */
ul { ul {
list-style: none; list-style: none;
padding: 15px; padding: 15px;
background: #fff; background: #fff;
border-radius: 10px; border-radius: 10px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); box-shadow: 0 2px 5px rgba(0,0,0,0.1);
transition: transform 0.2s, box-shadow 0.2s; transition: transform 0.2s, box-shadow 0.2s;
} }
ul:hover { ul:hover {
transform: translateY(-3px); transform: translateY(-3px);
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.15); box-shadow: 0 5px 10px rgba(0,0,0,0.15);
} }
li { li {
margin: 6px 0; margin: 6px 0;
} }
li b { li b {
display: block; display: block;
margin-bottom: 8px; margin-bottom: 8px;
font-size: 1em; font-size: 1em;
color: #1f618d; color: #1f618d;
} }
a { a {
text-decoration: none; text-decoration: none;
color: #0066cc; color: #0066cc;
padding: 5px 8px; padding: 5px 8px;
border-radius: 5px; border-radius: 5px;
transition: background-color 0.2s, color 0.2s; transition: background-color 0.2s, color 0.2s;
} }
a:hover { a:hover {
background-color: #0066cc; background-color: #0066cc;
color: #fff; color: #fff;
} }
/* Responsive adjustments */ /* Responsive adjustments */
@media screen and (max-width: 768px) { @media screen and (max-width: 768px) {
body { body {
padding: 10px; padding: 10px;
font-size: 0.95em; font-size: 0.95em;
} }
h1 { h1 { font-size: 1.5em; }
font-size: 1.5em; h2 { font-size: 1.2em; }
}
h2 { .grid {
font-size: 1.2em; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
} gap: 10px;
}
.grid { ul {
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); padding: 10px;
gap: 10px; }
}
ul { a {
padding: 10px; padding: 8px 10px;
} font-size: 0.95em;
}
a {
padding: 8px 10px;
font-size: 0.95em;
}
} }
@media screen and (max-width: 480px) { @media screen and (max-width: 480px) {
h1 { h1 { font-size: 1.3em; }
font-size: 1.3em; h2 { font-size: 1em; }
}
h2 { .grid {
font-size: 1em; grid-template-columns: 1fr; /* single column for small screens */
} gap: 10px;
}
.grid { ul {
grid-template-columns: 1fr; padding: 8px;
gap: 10px; }
}
ul { a {
padding: 8px; display: block;
} text-align: center;
padding: 10px;
a { }
display: block;
text-align: center;
padding: 10px;
}
} }

View File

@@ -1,79 +1,29 @@
/*
Orario Scuola, Copyright (C) 2025 EmmeV.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see https://www.gnu.org/licenses/.
*/
/* Navbar */ /* Navbar */
.navbar { .navbar {
background-color: #2c3e50; background-color: #2c3e50;
padding: 10px 20px; padding: 10px 20px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
color: #fff; color: #fff;
border-radius: 0 0 10px 10px; border-radius: 0 0 10px 10px;
margin-bottom: 20px; margin-bottom: 20px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); box-shadow: 0 2px 5px rgba(0,0,0,0.1);
} }
.navbar a { .navbar a {
color: #fff; color: #fff;
text-decoration: none; text-decoration: none;
margin-left: 15px; margin-left: 15px;
font-weight: bold; font-weight: bold;
transition: color 0.2s; transition: color 0.2s;
} }
.navbar a:hover { .navbar a:hover {
color: #f39c12; color: #f39c12;
} }
.navbar .logo { .navbar .logo {
font-size: 1.3em; font-size: 1.3em;
font-weight: bold; font-weight: bold;
}
/* Responsive navbar */
@media (max-width: 768px) {
.navbar {
flex-direction: column;
gap: 10px;
padding: 15px;
}
.navbar a {
margin-left: 0;
margin: 0 10px;
}
.navbar .logo {
font-size: 1.2em;
margin-bottom: 5px;
}
}
@media (max-width: 480px) {
.navbar {
padding: 12px;
}
.navbar .logo {
font-size: 1.1em;
}
.navbar a {
font-size: 0.9em;
margin: 0 8px;
}
} }

View File

@@ -1,161 +1,214 @@
/*
Orario Scuola, Copyright (C) 2025 EmmeV.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see https://www.gnu.org/licenses/.
*/
/* Base styles */
body { body {
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
padding: 15px; padding: 15px;
background-color: #f0f2f5; background-color: #f0f2f5;
color: #333; color: #333;
margin: 0; margin: 0;
} }
h1 { h1 {
text-align: center; text-align: center;
margin-bottom: 20px; margin-bottom: 20px;
color: #2c3e50; color: #2c3e50;
font-size: 1.8em; font-size: 1.8em;
} }
/* Table styles */ /* Table styles */
table { table {
border-collapse: collapse; border-collapse: collapse;
width: 100%; width: 100%;
max-width: 1000px; max-width: 1000px;
margin: 0 auto; margin: 0 auto;
background: #fff; background: #fff;
border-radius: 10px; border-radius: 10px;
overflow: hidden; overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); box-shadow: 0 2px 8px rgba(0,0,0,0.1);
} }
th, td { th, td {
border: 1px solid #ccc; border: 1px solid #ccc;
text-align: center; text-align: center;
padding: 10px; padding: 10px;
vertical-align: top; vertical-align: top;
} }
th { th {
background-color: #e0e0e0; background-color: #e0e0e0;
font-weight: bold; font-weight: bold;
} }
td { td {
transition: background-color 0.2s; transition: background-color 0.2s;
} }
td:hover { td:hover {
background-color: #f7f7f7; background-color: #f7f7f7;
} }
.subject { .subject {
font-weight: bold; font-weight: bold;
color: #1f618d; color: #1f618d;
} }
.teacher { .teacher {
font-size: 0.9em; font-size: 0.9em;
color: #2c3e50; color: #2c3e50;
} }
.room { .room {
font-size: 0.8em; font-size: 0.8em;
color: #666; color: #666;
} }
/* Desktop/Mobile layout control */ /*
.desktop-schedule {
display: table;
width: 100%;
border-collapse: collapse;
}
.mobile-schedule {
display: none;
}
/* Mobile styles */
@media (max-width: 768px) { @media (max-width: 768px) {
.desktop-schedule { table, thead, tbody, th, td, tr {
display: none; display: block;
} width: 100%;
}
.mobile-schedule { tr {
display: flex; margin-bottom: 15px;
flex-direction: column; border-bottom: 2px solid #ddd;
gap: 1.5rem; padding-bottom: 10px;
} }
.mobile-schedule .day { th {
background: #f8f8f8; display: none;
border-radius: 10px; }
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
padding: 1rem;
}
.mobile-schedule h2 { td {
margin-top: 0; text-align: left;
margin-bottom: 0.8rem; padding: 10px 10px 10px 45%;
font-size: 1.2rem; position: relative;
color: #111; border: none;
border-bottom: 1px solid #ddd; border-bottom: 1px solid #eee;
padding-bottom: 0.3rem; }
}
.lesson { td::before {
background: #fff; position: absolute;
border: 1px solid #eee; left: 10px;
border-radius: 8px; top: 10px;
padding: 0.6rem 0.8rem; width: 40%;
margin-bottom: 0.6rem; white-space: nowrap;
} font-weight: bold;
content: attr(data-label);
}
.lesson.empty { td:last-child {
opacity: 0.6; border-bottom: 0;
} }
.hour {
font-size: 0.9rem;
color: #666;
margin-bottom: 3px;
}
.subject {
font-weight: 600;
color: #222;
}
.teacher {
font-size: 0.85rem;
color: #555;
}
.room {
font-size: 0.8rem;
color: #777;
}
} }
@media (max-width: 480px) { @media (max-width: 480px) {
body { body { padding: 10px; }
padding: 10px; h1 { font-size: 1.5em; }
} td::before { font-size: 0.9em; }
td { padding-left: 50%; }
h1 { }
font-size: 1.5em; */
}
/* --- tuoi stili desktop (questi restano uguali) --- */
table {
border-collapse: collapse;
width: 100%;
max-width: 1000px;
margin: 0 auto;
background: #fff;
border-radius: 10px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
th, td {
border: 1px solid #ccc;
text-align: center;
padding: 10px;
vertical-align: top;
}
th {
background-color: #e0e0e0;
font-weight: bold;
}
td {
transition: background-color 0.2s;
}
td:hover {
background-color: #f7f7f7;
}
.subject {
font-weight: bold;
color: #1f618d;
}
.teacher {
font-size: 0.9em;
color: #2c3e50;
}
.room {
font-size: 0.8em;
color: #666;
}
/* Mostra solo la tabella su desktop */
.desktop-schedule { display: table; width: 100%; border-collapse: collapse; }
.mobile-schedule { display: none; }
/* Mobile: nasconde tabella, mostra card */
@media (max-width: 768px) {
.desktop-schedule { display: none; }
.mobile-schedule { display: flex; flex-direction: column; gap: 1.5rem; }
.mobile-schedule .day {
background: #f8f8f8;
border-radius: 10px;
box-shadow: 0 2px 6px rgba(0,0,0,0.05);
padding: 1rem;
}
.mobile-schedule h2 {
margin-top: 0;
margin-bottom: .8rem;
font-size: 1.2rem;
color: #111;
border-bottom: 1px solid #ddd;
padding-bottom: .3rem;
}
.lesson {
background: #fff;
border: 1px solid #eee;
border-radius: 8px;
padding: .6rem .8rem;
margin-bottom: .6rem;
}
.lesson.empty {
opacity: .6;
}
.hour {
font-size: 0.9rem;
color: #666;
margin-bottom: 3px;
}
.subject {
font-weight: 600;
color: #222;
}
.teacher {
font-size: 0.85rem;
color: #555;
}
.room {
font-size: 0.8rem;
color: #777;
}
} }

View File

@@ -1,43 +1,25 @@
<?php <?php
/*
Orario Scuola, Copyright (C) 2025 EmmeV.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see https://www.gnu.org/licenses/.
*/
include("lib/db.php"); include("lib/db.php");
$teacher = $_GET['teacher'];
$days = ["Lunedì","Martedì","Mercoledì","Giovedì","Venerdì","Sabato"]; $days = ["Lunedì","Martedì","Mercoledì","Giovedì","Venerdì","Sabato"];
$hours = [ $hours = [
1 => "Prima ora<br> 7:50 - 8:50", 1 => "Prima ora<br>7:50 - 8:50",
2 => "Seconda ora<br> 8:50 - 9:45", 2 => "Seconda ora<br>8:50 - 9:45",
3 => "Terza ora<br> 9:55 - 10:50", 3 => "Terza ora<br>9:55 - 10:50",
4 => "Quarta ora<br> 10:50 - 11:45", 4 => "Quarta ora<br>10:50 - 11:45",
5 => "Quinta ora<br> 11:55 - 12:50", 5 => "Quinta ora<br>11:55 - 12:50",
6 => "Sesta ora<br> 12:50 - 13:50" 6 => "Sesta ora<br>12:50 - 13:50"
]; ];
if ($teacher == "No Lezione" || $teacher == "sconosciuto") {
if (!isset($_GET['teacher'])) { header("Location: index.php");
exit;
}
else if (!isset($_GET['teacher'])) {
header("Location: index.php"); header("Location: index.php");
exit; exit;
} }
$teacher = $conn->real_escape_string($_GET['teacher']); $teacher = $conn->real_escape_string($_GET['teacher']);
if ($teacher == "No Lezione" || $teacher == "sconosciuto") {
header("Location: index.php");
exit;
}
$res = $conn->query("SELECT DISTINCT teacher FROM subjects WHERE teacher = '$teacher' LIMIT 1"); $res = $conn->query("SELECT DISTINCT teacher FROM subjects WHERE teacher = '$teacher' LIMIT 1");
if ($res->num_rows === 0) { if ($res->num_rows === 0) {
@@ -60,11 +42,8 @@ if ($res->num_rows === 0) {
<a href="index.php">Home</a> <a href="index.php">Home</a>
</div> </div>
</div> </div>
<h1>Orario docente <?php echo htmlspecialchars($teacher); ?></h1> <h1>Orario docente <?php echo htmlspecialchars($teacher); ?></h1>
<table>
<!-- Visualizzazione Desktop -->
<table class="desktop-schedule">
<tr> <tr>
<th></th> <th></th>
<?php foreach($days as $d) echo "<th>$d</th>"; ?> <?php foreach($days as $d) echo "<th>$d</th>"; ?>
@@ -80,12 +59,10 @@ if ($res->num_rows === 0) {
WHERE subjects.teacher='$teacher' AND timetable.day='$d' AND timetable.hour=$hnum"); WHERE subjects.teacher='$teacher' AND timetable.day='$d' AND timetable.hour=$hnum");
if($row = $q->fetch_assoc()){ if($row = $q->fetch_assoc()){
echo "<td data-label='$d'> echo "<td data-label='$d'>
<div class='subject'>" . htmlspecialchars($row['name']) . "</div> <div class='subject'>{$row['name']}</div>
<div class='teacher'>" . htmlspecialchars($row['class_name']) . "</div>"; <div class='teacher'>{$row['class_name']}</div>
if(!empty($row['room'])) { <div class='room'>{$row['room']}</div>
echo "<div class='room'>" . htmlspecialchars($row['room']) . "</div>"; </td>";
}
echo "</td>";
} else { } else {
echo "<td data-label='$d'></td>"; echo "<td data-label='$d'></td>";
} }
@@ -94,41 +71,6 @@ if ($res->num_rows === 0) {
} }
?> ?>
</table> </table>
<!-- FIX: Visualizzazione Mobile aggiunta -->
<div class="mobile-schedule">
<?php foreach($days as $d): ?>
<div class="day">
<h2><?= htmlspecialchars($d) ?></h2>
<?php
foreach($hours as $hnum => $hlabel):
$q = $conn->query("SELECT subjects.name, classes.name AS class_name, subjects.room
FROM timetable
LEFT JOIN subjects ON timetable.subject_id = subjects.id
LEFT JOIN classes ON timetable.class_id = classes.id
WHERE subjects.teacher='$teacher' AND timetable.day='$d' AND timetable.hour=$hnum");
if($row = $q->fetch_assoc()):
?>
<div class="lesson">
<div class="hour"><?= strip_tags($hlabel) ?></div>
<div class="subject"><?= htmlspecialchars($row['name']) ?></div>
<div class="teacher"><?= htmlspecialchars($row['class_name']) ?></div>
<?php if(!empty($row['room'])): ?>
<div class="room"><?= htmlspecialchars($row['room']) ?></div>
<?php endif; ?>
</div>
<?php else: ?>
<div class="lesson empty">
<div class="hour"><?= strip_tags($hlabel) ?></div>
<div class="subject">—</div>
</div>
<?php endif; ?>
<?php endforeach; ?>
</div>
<?php endforeach; ?>
</div>
<p style="text-align: center;">Copyright (C) 2025 EmmeV. - Released under <a href="https://git.vichingo455.freeddns.org/emmev-code/orario/src/branch/stable/LICENSE.txt" target="_blank">GNU AGPL 3.0 License</a>.</p> <p style="text-align: center;">Copyright (C) 2025 EmmeV. - Released under <a href="https://git.vichingo455.freeddns.org/emmev-code/orario/src/branch/stable/LICENSE.txt" target="_blank">GNU AGPL 3.0 License</a>.</p>
</body> </body>
</html> </html>

View File

@@ -1,20 +1,4 @@
<?php <?php
/*
Orario Scuola, Copyright (C) 2025 EmmeV.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see https://www.gnu.org/licenses/.
*/
include("lib/db.php"); include("lib/db.php");
?> ?>
<!DOCTYPE html> <!DOCTYPE html>

View File

@@ -1,31 +1,15 @@
<?php <?php
/*
Orario Scuola, Copyright (C) 2025 EmmeV.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see https://www.gnu.org/licenses/.
*/
include("lib/db.php"); include("lib/db.php");
$room = $_GET['room']; // aula selezionata
$days = ["Lunedì","Martedì","Mercoledì","Giovedì","Venerdì","Sabato"]; $days = ["Lunedì","Martedì","Mercoledì","Giovedì","Venerdì","Sabato"];
$hours = [ $hours = [
1 => "Prima ora<br> 7:50 - 8:50", 1 => "Prima ora<br>7:50 - 8:50",
2 => "Seconda ora<br> 8:50 - 9:45", 2 => "Seconda ora<br>8:50 - 9:45",
3 => "Terza ora<br> 9:55 - 10:50", 3 => "Terza ora<br>9:55 - 10:50",
4 => "Quarta ora<br> 10:50 - 11:45", 4 => "Quarta ora<br>10:50 - 11:45",
5 => "Quinta ora<br> 11:55 - 12:50", 5 => "Quinta ora<br>11:55 - 12:50",
6 => "Sesta ora<br> 12:50 - 13:50" 6 => "Sesta ora<br>12:50 - 13:50"
]; ];
if (!isset($_GET['room'])) { if (!isset($_GET['room'])) {
header("Location: index.php"); header("Location: index.php");
exit; exit;
@@ -35,6 +19,7 @@ $room = $conn->real_escape_string($_GET['room']);
$res = $conn->query("SELECT DISTINCT room FROM subjects WHERE room = '$room' LIMIT 1"); $res = $conn->query("SELECT DISTINCT room FROM subjects WHERE room = '$room' LIMIT 1");
if ($res->num_rows === 0) { if ($res->num_rows === 0) {
// Aula non trovata
header("Location: index.php"); header("Location: index.php");
exit; exit;
} }
@@ -57,8 +42,7 @@ if ($res->num_rows === 0) {
<h1>Orario <?php echo htmlspecialchars($room); ?></h1> <h1>Orario <?php echo htmlspecialchars($room); ?></h1>
<!-- Visualizzazione Desktop --> <table>
<table class="desktop-schedule">
<tr> <tr>
<th></th> <th></th>
<?php foreach($days as $d) echo "<th>$d</th>"; ?> <?php foreach($days as $d) echo "<th>$d</th>"; ?>
@@ -79,21 +63,18 @@ if ($res->num_rows === 0) {
if($q->num_rows > 0){ if($q->num_rows > 0){
$subject = null; $subject = null;
// FIX: Uso array associativo per evitare duplicati classe+docente $entries = [];
$class_teacher_pairs = [];
while($row = $q->fetch_assoc()){ while($row = $q->fetch_assoc()){
// salvo materia (prendo la prima, di solito è la stessa per tutti)
if($subject === null) { if($subject === null) {
$subject = $row['subject_name']; $subject = $row['subject_name'];
} }
// Creo una coppia unica classe-docente // accumulo classi + docente
$pair = $row['class_name'] . " (" . $row['teacher'] . ")"; $entries[] = $row['class_name'] . " (" . $row['teacher'] . ")";
$class_teacher_pairs[$pair] = true; // Uso chiave per evitare duplicati
} }
// Converto in array e unisco // unisci le classi con " e " se sono 2, altrimenti virgole + "e" finale
$entries = array_keys($class_teacher_pairs);
if(count($entries) > 1){ if(count($entries) > 1){
$last = array_pop($entries); $last = array_pop($entries);
$entries_list = implode(", ", $entries) . " e " . $last; $entries_list = implode(", ", $entries) . " e " . $last;
@@ -102,8 +83,8 @@ if ($res->num_rows === 0) {
} }
echo "<td data-label='$d'> echo "<td data-label='$d'>
<div class='subject'>" . htmlspecialchars($subject) . "</div> <div class='subject'>$subject</div>
<div class='room'>" . htmlspecialchars($entries_list) . "</div> <div class='room'>$entries_list</div>
</td>"; </td>";
} else { } else {
echo "<td data-label='$d'></td>"; echo "<td data-label='$d'></td>";
@@ -113,60 +94,6 @@ if ($res->num_rows === 0) {
} }
?> ?>
</table> </table>
<p style="text-align: center;">Copyright (C) 2025 EmmeV. All rights reserved.</p>
<!-- Visualizzazione Mobile -->
<div class="mobile-schedule">
<?php foreach($days as $d): ?>
<div class="day">
<h2><?= htmlspecialchars($d) ?></h2>
<?php
foreach($hours as $hnum => $hlabel):
$q = $conn->query("
SELECT subjects.name AS subject_name, subjects.teacher, classes.name AS class_name
FROM timetable
LEFT JOIN subjects ON timetable.subject_id = subjects.id
LEFT JOIN classes ON timetable.class_id = classes.id
WHERE subjects.room='". $conn->real_escape_string($room) ."'
AND timetable.day='$d' AND timetable.hour=$hnum
");
if($q->num_rows > 0):
$subject = null;
$class_teacher_pairs = [];
while($row = $q->fetch_assoc()){
if($subject === null) {
$subject = $row['subject_name'];
}
$pair = $row['class_name'] . " (" . $row['teacher'] . ")";
$class_teacher_pairs[$pair] = true;
}
$entries = array_keys($class_teacher_pairs);
if(count($entries) > 1){
$last = array_pop($entries);
$entries_list = implode(", ", $entries) . " e " . $last;
} else {
$entries_list = $entries[0];
}
?>
<div class="lesson">
<div class="hour"><?= strip_tags($hlabel) ?></div>
<div class="subject"><?= htmlspecialchars($subject) ?></div>
<div class="room"><?= htmlspecialchars($entries_list) ?></div>
</div>
<?php else: ?>
<div class="lesson empty">
<div class="hour"><?= strip_tags($hlabel) ?></div>
<div class="subject">—</div>
</div>
<?php endif; ?>
<?php endforeach; ?>
</div>
<?php endforeach; ?>
</div>
<p style="text-align: center;">Copyright (C) 2025 EmmeV. - Released under <a href="https://git.vichingo455.freeddns.org/emmev-code/orario/src/branch/stable/LICENSE.txt" target="_blank">GNU AGPL 3.0 License</a>.</p>
</body> </body>
</html> </html>

View File

@@ -1,20 +1,4 @@
<?php <?php
/*
Orario Scuola, Copyright (C) 2025 EmmeV.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see https://www.gnu.org/licenses/.
*/
include_once __DIR__ . '/../config/config.php'; include_once __DIR__ . '/../config/config.php';
$host = DB_HOST; $host = DB_HOST;
$user = DB_USER; $user = DB_USER;

View File

@@ -1,43 +1,26 @@
<?php <?php
/* #include("lib/db.php");
Orario Scuola, Copyright (C) 2025 EmmeV.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see https://www.gnu.org/licenses/.
*/
include("lib/db.php"); // FIX: Decommentato
$class_id = intval($_GET['class_id']); $class_id = intval($_GET['class_id']);
$class = $conn->query("SELECT * FROM classes WHERE id=$class_id")->fetch_assoc(); $class = $conn->query("SELECT * FROM classes WHERE id=$class_id")->fetch_assoc();
$days = ["Lunedì","Martedì","Mercoledì","Giovedì","Venerdì","Sabato"]; $days = ["Lunedì","Martedì","Mercoledì","Giovedì","Venerdì","Sabato"];
$hours = [ $hours = [
1 => "Prima ora<br> 7:50 - 8:50", 1 => "Prima ora<br>7:50 - 8:50",
2 => "Seconda ora<br> 8:50 - 9:45", 2 => "Seconda ora<br>8:50 - 9:45",
3 => "Terza ora<br> 9:55 - 10:50", 3 => "Terza ora<br>9:55 - 10:50",
4 => "Quarta ora<br> 10:50 - 11:45", 4 => "Quarta ora<br>10:50 - 11:45",
5 => "Quinta ora<br> 11:55 - 12:50", 5 => "Quinta ora<br>11:55 - 12:50",
6 => "Sesta ora<br> 12:50 - 13:50" 6 => "Sesta ora<br>12:50 - 13:50"
]; ];
// FIX: Validazione classe prima di tutto
if (!isset($_GET['class_id'])) { if (!isset($_GET['class_id'])) {
header("Location: index.php"); header("Location: index.php");
exit; exit;
} }
$class_id = intval($_GET['class_id']); $class_id = intval($_GET['class_id']); // sicurezza
$res = $conn->query("SELECT id FROM classes WHERE id = $class_id LIMIT 1"); $res = $conn->query("SELECT id FROM classes WHERE id = $class_id LIMIT 1");
if ($res->num_rows === 0) { if ($res->num_rows === 0) {
// Classe non trovata
header("Location: index.php"); header("Location: index.php");
exit; exit;
} }
@@ -45,7 +28,7 @@ if ($res->num_rows === 0) {
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Orario <?php echo htmlspecialchars($class['name']); ?></title> <title>Orario <?php echo $class['name']; ?></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/timetable.css"> <link rel="stylesheet" href="css/timetable.css">
<link rel="stylesheet" href="css/navbar.css"> <link rel="stylesheet" href="css/navbar.css">
@@ -57,10 +40,8 @@ if ($res->num_rows === 0) {
<a href="index.php">Home</a> <a href="index.php">Home</a>
</div> </div>
</div> </div>
<h1>Orario della classe <?php echo htmlspecialchars($class['name']); ?></h1> <h1>Orario della classe <?php echo $class['name']; ?></h1>
<table>
<!-- Visualizzazione Desktop -->
<table class="desktop-schedule">
<tr> <tr>
<th></th> <th></th>
<?php foreach($days as $d) echo "<th>$d</th>"; ?> <?php foreach($days as $d) echo "<th>$d</th>"; ?>
@@ -75,34 +56,31 @@ if ($res->num_rows === 0) {
WHERE class_id=$class_id AND day='$d' AND hour=$hnum"); WHERE class_id=$class_id AND day='$d' AND hour=$hnum");
if($q->num_rows > 0){ if($q->num_rows > 0){
// FIX: Gestione corretta di multipli docenti/materie $row = $q->fetch_assoc();
$entries = []; $subject = $row['name'];
$subject = null; $room = $row['room'];
$room = null;
// metto il primo docente
$teachers = [$row['teacher']];
// aggiungo eventuali altri docenti
while($row = $q->fetch_assoc()){ while($row = $q->fetch_assoc()){
if($subject === null) { $teachers[] = $row['teacher'];
$subject = $row['name'];
$room = $row['room'];
}
$entries[] = $row['teacher'];
} }
// Unisci i docenti correttamente // se più docenti -> unisci con virgola e "e" finale
if(count($entries) > 1){ if(count($teachers) > 1){
$last = array_pop($entries); $last = array_pop($teachers);
$teachers_list = implode(", ", $entries) . " e " . $last; $teachers_list = implode(", ", $teachers) . " e " . $last;
} else { } else {
$teachers_list = $entries[0]; $teachers_list = $teachers[0];
} }
echo "<td data-label='$d'> echo "<td data-label='$d'>
<div class='subject'>" . htmlspecialchars($subject) . "</div> <div class='subject'>$subject</div>
<div class='teacher'>" . htmlspecialchars($teachers_list) . "</div>"; <div class='teacher'>$teachers_list</div>
if(!empty($room)) { <div class='room'>$room</div>
echo "<div class='room'>" . htmlspecialchars($room) . "</div>"; </td>";
}
echo "</td>";
} else { } else {
echo "<td data-label='$d'></td>"; echo "<td data-label='$d'></td>";
} }
@@ -111,12 +89,10 @@ if ($res->num_rows === 0) {
} }
?> ?>
</table> </table>
<!-- Visualizzazione Mobile -->
<div class="mobile-schedule"> <div class="mobile-schedule">
<?php foreach($days as $d): ?> <?php foreach($days as $d): ?>
<div class="day"> <div class="day">
<h2><?= htmlspecialchars($d) ?></h2> <h2><?= $d ?></h2>
<?php <?php
foreach($hours as $hnum => $hlabel): foreach($hours as $hnum => $hlabel):
$q = $conn->query("SELECT subjects.name, subjects.teacher, subjects.room $q = $conn->query("SELECT subjects.name, subjects.teacher, subjects.room
@@ -125,35 +101,31 @@ if ($res->num_rows === 0) {
WHERE class_id=$class_id AND day='$d' AND hour=$hnum"); WHERE class_id=$class_id AND day='$d' AND hour=$hnum");
if($q->num_rows > 0): if($q->num_rows > 0):
// FIX: Stessa logica corretta anche per mobile $row = $q->fetch_assoc();
$entries = []; $subject = $row['name'];
$subject = null; $room = $row['room'];
$room = null;
$teachers = [$row['teacher']];
while($row = $q->fetch_assoc()){ while($row = $q->fetch_assoc()){
if($subject === null) { $teachers[] = $row['teacher'];
$subject = $row['name'];
$room = $row['room'];
}
$entries[] = $row['teacher'];
} }
if(count($entries) > 1){ if(count($teachers) > 1){
$last = array_pop($entries); $last = array_pop($teachers);
$teachers_list = implode(", ", $entries) . " e " . $last; $teachers_list = implode(", ", $teachers) . " e " . $last;
} else { } else {
$teachers_list = $entries[0]; $teachers_list = $teachers[0];
} }
?> ?>
<div class="lesson"> <div class="lesson">
<div class="hour"><?= strip_tags($hlabel) ?></div> <div class="hour"><?= $hlabel ?></div>
<div class="subject"><?= htmlspecialchars($subject) ?></div> <div class="subject"><?= $subject ?></div>
<div class="teacher"><?= htmlspecialchars($teachers_list) ?></div> <div class="teacher"><?= $teachers_list ?></div>
<?php if(!empty($room)): ?><div class="room"><?= htmlspecialchars($room) ?></div><?php endif; ?> <?php if($room): ?><div class="room"><?= $room ?></div><?php endif; ?>
</div> </div>
<?php else: ?> <?php else: ?>
<div class="lesson empty"> <div class="lesson empty">
<div class="hour"><?= strip_tags($hlabel) ?></div> <div class="hour"><?= $hlabel ?></div>
<div class="subject">—</div> <div class="subject">—</div>
</div> </div>
<?php endif; ?> <?php endif; ?>
@@ -161,7 +133,6 @@ if ($res->num_rows === 0) {
</div> </div>
<?php endforeach; ?> <?php endforeach; ?>
</div> </div>
<p style="text-align: center;">Copyright (C) 2025 EmmeV. - Released under <a href="https://git.vichingo455.freeddns.org/emmev-code/orario/src/branch/stable/LICENSE.txt" target="_blank">GNU AGPL 3.0 License</a>.</p> <p style="text-align: center;">Copyright (C) 2025 EmmeV. - Released under <a href="https://git.vichingo455.freeddns.org/emmev-code/orario/src/branch/stable/LICENSE.txt" target="_blank">GNU AGPL 3.0 License</a>.</p>
</body> </body>
</html> </html>

View File

@@ -1,20 +1,8 @@
<?php <?php
/* // Hashed Password Generator
Orario Scuola, Copyright (C) 2025 EmmeV. // Copyright (C) 2025 EmmeV. All rights reserved.
// Usage: php generate_hash.php password_to_hash
This program is free software: you can redistribute it and/or modify // Example: php generate_hash.php admin
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see https://www.gnu.org/licenses/.
*/
if ($argc > 1) { if ($argc > 1) {
$primoArgomento = $argv[1]; $primoArgomento = $argv[1];