Update from Git Manager GUI

This commit is contained in:
2026-02-20 18:38:42 +01:00
parent d14646c5ae
commit 535b0aa2f3
5 changed files with 375 additions and 187 deletions

View File

@@ -177,7 +177,6 @@ public class DatabaseManager {
// ─────────────────────────── Tabellen erstellen ────────────────────────
private void createTables() {
// close_comment ist jetzt von Anfang an in der CREATE-Anweisung enthalten
String sql = """
CREATE TABLE IF NOT EXISTS tickets (
id INT AUTO_INCREMENT PRIMARY KEY,
@@ -198,7 +197,8 @@ public class DatabaseManager {
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
claimed_at TIMESTAMP NULL,
closed_at TIMESTAMP NULL,
close_comment VARCHAR(500) NULL
close_comment VARCHAR(500) NULL,
player_deleted BOOLEAN DEFAULT FALSE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
""";
try (Connection conn = getConnection(); Statement stmt = conn.createStatement()) {
@@ -210,11 +210,9 @@ public class DatabaseManager {
/**
* Ergänzt fehlende Spalten in bestehenden Datenbanken automatisch.
* Wichtig für Server, die das Plugin bereits installiert hatten bevor
* close_comment existierte.
*/
private void ensureColumns() {
// close_comment hinzufügen, falls nicht vorhanden
// close_comment hinzufügen
String checkSql = """
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
@@ -225,20 +223,34 @@ public class DatabaseManager {
Statement stmt = conn.createStatement()) {
ResultSet rs = stmt.executeQuery(checkSql);
if (rs.next() && rs.getInt(1) == 0) {
// Spalte existiert nicht → hinzufügen
stmt.execute("ALTER TABLE tickets ADD COLUMN close_comment VARCHAR(500) NULL");
plugin.getLogger().info("[TicketSystem] Spalte 'close_comment' wurde zur Datenbank hinzugefügt.");
}
} catch (SQLException e) {
plugin.getLogger().log(Level.SEVERE, "Fehler bei ensureColumns(): " + e.getMessage(), e);
}
// player_deleted Spalte prüfen
String checkSqlDel = """
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'tickets'
AND COLUMN_NAME = 'player_deleted'
""";
try (Connection conn = getConnection();
Statement stmt = conn.createStatement()) {
ResultSet rs = stmt.executeQuery(checkSqlDel);
if (rs.next() && rs.getInt(1) == 0) {
stmt.execute("ALTER TABLE tickets ADD COLUMN player_deleted BOOLEAN DEFAULT FALSE");
plugin.getLogger().info("[TicketSystem] Spalte 'player_deleted' wurde hinzugefügt.");
}
} catch (SQLException e) {
plugin.getLogger().log(Level.SEVERE, "Fehler bei ensureColumns(player_deleted): " + e.getMessage(), e);
}
}
// ─────────────────────────── CRUD ──────────────────────────────────────
/**
* Speichert ein neues Ticket in der DB und gibt die generierte ID zurück.
*/
public int createTicket(Ticket ticket) {
if (useMySQL) {
String sql = """
@@ -282,13 +294,14 @@ public class DatabaseManager {
}
}
/**
* Claimt ein Ticket (Status → CLAIMED).
*/
// ─── FIX: player_deleted wird beim Claimen zurückgesetzt, damit der Spieler
// sein Ticket wieder sieht, sobald ein Supporter es annimmt. ───────
public boolean claimTicket(int ticketId, UUID claimerUUID, String claimerName) {
if (useMySQL) {
String sql = """
UPDATE tickets SET status = 'CLAIMED', claimer_uuid = ?, claimer_name = ?, claimed_at = NOW()
UPDATE tickets
SET status = 'CLAIMED', claimer_uuid = ?, claimer_name = ?,
claimed_at = NOW(), player_deleted = FALSE
WHERE id = ? AND status = 'OPEN'
""";
try (Connection conn = getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) {
@@ -307,6 +320,7 @@ public class DatabaseManager {
t.setClaimerUUID(claimerUUID);
t.setClaimerName(claimerName);
t.setClaimedAt(new Timestamp(System.currentTimeMillis()));
t.setPlayerDeleted(false); // FIX: Sichtbarkeit für den Spieler wiederherstellen
dataConfig.set("tickets." + ticketId, t);
try {
dataConfig.save(dataFile);
@@ -318,9 +332,6 @@ public class DatabaseManager {
}
}
/**
* Schließt ein Ticket (Status → CLOSED).
*/
public boolean closeTicket(int ticketId, String closeComment) {
if (useMySQL) {
String sql = """
@@ -352,9 +363,36 @@ public class DatabaseManager {
}
}
/**
* Löscht ein Ticket anhand der ID.
*/
// ─── Soft Delete Methode ────────────────────────────────────────────────
public boolean markAsPlayerDeleted(int id) {
if (useMySQL) {
String sql = "UPDATE tickets SET player_deleted = TRUE WHERE id = ?";
try (Connection conn = getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setInt(1, id);
return ps.executeUpdate() > 0;
} catch (SQLException e) {
plugin.getLogger().log(Level.SEVERE, "Fehler beim Markieren als gelöscht: " + e.getMessage(), e);
}
return false;
} else {
if (dataConfig.contains("tickets." + id)) {
Ticket t = (Ticket) dataConfig.get("tickets." + id);
if (t != null) {
t.setPlayerDeleted(true);
dataConfig.set("tickets." + id, t);
try {
dataConfig.save(dataFile);
backupDataFile();
return true;
} catch (IOException e) {
plugin.getLogger().severe("Fehler beim Speichern (Soft Delete): " + e.getMessage());
}
}
}
return false;
}
}
public boolean deleteTicket(int id) {
if (useMySQL) {
String sql = "DELETE FROM tickets WHERE id = ?";
@@ -384,13 +422,14 @@ public class DatabaseManager {
}
}
/**
* Leitet ein Ticket an einen anderen Supporter weiter (Status → FORWARDED).
*/
// ─── FIX: player_deleted wird beim Weiterleiten zurückgesetzt, damit der
// Spieler sein Ticket wieder sieht, sobald es weitergeleitet wird. ──
public boolean forwardTicket(int ticketId, UUID toUUID, String toName) {
if (useMySQL) {
String sql = """
UPDATE tickets SET status = 'FORWARDED', forwarded_to_uuid = ?, forwarded_to_name = ?
UPDATE tickets
SET status = 'FORWARDED', forwarded_to_uuid = ?, forwarded_to_name = ?,
player_deleted = FALSE
WHERE id = ? AND status != 'CLOSED'
""";
try (Connection conn = getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) {
@@ -408,6 +447,7 @@ public class DatabaseManager {
t.setStatus(TicketStatus.FORWARDED);
t.setForwardedToUUID(toUUID);
t.setForwardedToName(toName);
t.setPlayerDeleted(false); // FIX: Sichtbarkeit für den Spieler wiederherstellen
dataConfig.set("tickets." + ticketId, t);
try {
dataConfig.save(dataFile);
@@ -421,9 +461,6 @@ public class DatabaseManager {
// ─────────────────────────── Abfragen ──────────────────────────────────
/**
* Gibt alle Tickets mit einem bestimmten Status zurück.
*/
public List<Ticket> getTicketsByStatus(TicketStatus... statuses) {
List<Ticket> list = new ArrayList<>();
if (statuses.length == 0) return list;
@@ -452,9 +489,6 @@ public class DatabaseManager {
}
}
/**
* Gibt alle Tickets zurück (alle Status).
*/
public List<Ticket> getAllTickets() {
List<Ticket> list = new ArrayList<>();
if (useMySQL) {
@@ -475,9 +509,6 @@ public class DatabaseManager {
return list;
}
/**
* Gibt ein einzelnes Ticket anhand der ID zurück.
*/
public Ticket getTicketById(int id) {
if (useMySQL) {
String sql = "SELECT * FROM tickets WHERE id = ?";
@@ -497,9 +528,6 @@ public class DatabaseManager {
}
}
/**
* Anzahl offener Tickets (OPEN) für Join-Benachrichtigung.
*/
public int countOpenTickets() {
if (useMySQL) {
String sql = "SELECT COUNT(*) FROM tickets WHERE status = 'OPEN'";
@@ -522,9 +550,6 @@ public class DatabaseManager {
}
}
/**
* Anzahl offener Tickets eines bestimmten Spielers.
*/
public int countOpenTicketsByPlayer(UUID uuid) {
if (useMySQL) {
String sql = "SELECT COUNT(*) FROM tickets WHERE creator_uuid = ? AND status IN ('OPEN', 'CLAIMED', 'FORWARDED')";
@@ -553,9 +578,6 @@ public class DatabaseManager {
// ─────────────────────────── Archivierung ──────────────────────────────
/**
* Archiviert alle geschlossenen Tickets in eine separate Datei.
*/
public int archiveClosedTickets() {
List<Ticket> all = getAllTickets();
List<Ticket> toArchive = new ArrayList<>();
@@ -705,11 +727,6 @@ public class DatabaseManager {
// ─────────────────────────── Mapping ───────────────────────────────────
/**
* Liest eine Zeile aus dem ResultSet und erstellt ein Ticket-Objekt.
* close_comment wird mit try-catch abgesichert, damit ältere Datenbanken
* ohne diese Spalte nicht abstürzen.
*/
private Ticket mapRow(ResultSet rs) throws SQLException {
Ticket t = new Ticket();
t.setId(rs.getInt("id"));
@@ -727,15 +744,10 @@ public class DatabaseManager {
t.setClaimedAt(rs.getTimestamp("claimed_at"));
t.setClosedAt(rs.getTimestamp("closed_at"));
// ── BUGFIX: close_comment mit try-catch absichern ──────────────────
// Wenn die Spalte in einer alten DB noch nicht existiert, wird der
// Fehler ignoriert statt die gesamte Ticket-Liste leer zu lassen.
try {
String closeComment = rs.getString("close_comment");
if (closeComment != null) t.setCloseComment(closeComment);
} catch (SQLException ignored) {
// Spalte existiert noch nicht ensureColumns() ergänzt sie beim nächsten Start
}
} catch (SQLException ignored) { }
String claimerUUID = rs.getString("claimer_uuid");
if (claimerUUID != null) {
@@ -747,6 +759,10 @@ public class DatabaseManager {
t.setForwardedToUUID(UUID.fromString(fwdUUID));
t.setForwardedToName(rs.getString("forwarded_to_name"));
}
// Mapping des Soft Delete Flags
t.setPlayerDeleted(rs.getBoolean("player_deleted"));
return t;
}
@@ -773,6 +789,7 @@ public class DatabaseManager {
if (t.getForwardedToUUID() != null) obj.put("forwardedToUUID", t.getForwardedToUUID().toString());
if (t.getForwardedToName() != null) obj.put("forwardedToName", t.getForwardedToName());
if (t.getCloseComment() != null) obj.put("closeComment", t.getCloseComment());
obj.put("playerDeleted", t.isPlayerDeleted());
return obj;
}
@@ -798,6 +815,7 @@ public class DatabaseManager {
if (obj.get("forwardedToUUID") != null) t.setForwardedToUUID(UUID.fromString((String) obj.get("forwardedToUUID")));
if (obj.get("forwardedToName") != null) t.setForwardedToName((String) obj.get("forwardedToName"));
if (obj.get("closeComment") != null) t.setCloseComment((String) obj.get("closeComment"));
if (obj.containsKey("playerDeleted")) t.setPlayerDeleted((Boolean) obj.get("playerDeleted"));
return t;
} catch (Exception e) {
if (plugin != null) plugin.getLogger().severe("Fehler beim Parsen eines Tickets: " + e.getMessage());