Compare commits

..

19 Commits

Author SHA1 Message Date
niklas.ortmann c62ff5b2c0 refactoring 2026-06-01 22:53:28 +02:00
niklas.ortmann ad422a134d refactoring 2026-06-01 22:52:42 +02:00
niklas.ortmann 9fce9ec8dd refactoring 2026-06-01 22:51:46 +02:00
niklas.ortmann a329137de2 refactoring 2026-06-01 22:48:39 +02:00
caroline.slt 21bdb0d66d Weitere Reviewänderungen 2026-05-31 22:53:58 +02:00
caroline.slt 5db4ad3e63 Weitere Reviewänderungen 2026-05-31 22:49:13 +02:00
caroline.slt 2ce13cef72 Weitere Reviewänderungen 2026-05-31 22:42:16 +02:00
caroline.slt 02551049e0 Weitere Reviewänderungen 2026-05-31 22:38:29 +02:00
caroline.slt 55e9fa6a20 Weitere Reviewänderungen 2026-05-31 22:34:11 +02:00
caroline.slt c82378baa8 Weitere Reviewänderungen 2026-05-31 22:26:39 +02:00
caroline.slt 541d5b4c5e Weitere Reviewänderungen 2026-05-31 22:21:50 +02:00
caroline.slt f9ab3f8db2 session start entfernt 2026-05-31 21:53:30 +02:00
caroline.slt 6c5047be30 Review Changes 2026-05-31 21:42:46 +02:00
caroline.slt 25f6d2bf4a Review Changes 2026-05-31 21:35:54 +02:00
caroline.slt 4d8f338649 DAO Pattern angepasst & Passwörter gehashed 2026-05-27 19:25:58 +02:00
caroline.slt 46a307a5b0 First Implementation 2026-05-26 23:14:12 +02:00
caroline.slt 7706c7dfbf First Implementation 2026-05-26 23:06:22 +02:00
caroline.slt a946cee891 First Implementation 2026-05-26 22:59:48 +02:00
caroline.slt 4d4b8aeb99 First Implementation 2026-05-26 00:20:34 +02:00
43 changed files with 454 additions and 2164 deletions
Generated
+1 -3
View File
@@ -10,9 +10,7 @@
<option name="highlightLevel" value="WARNING" />
<option name="transferred" value="true" />
</component>
<component name="PhpProjectSharedConfiguration" php_language_level="7.0">
<option name="suggestChangeDefaultLanguageLevel" value="false" />
</component>
<component name="PhpProjectSharedConfiguration" php_language_level="8.5" />
<component name="PhpStanOptionsConfiguration">
<option name="transferred" value="true" />
</component>
-118
View File
@@ -1,118 +0,0 @@
<?php
session_start();
?>
<!--
Seite: Beitrag erstellen
Inhalt: Formular für die Erstellung eines neuen Beitrags
-->
<form method="post" action="php/controller/createArticle-controller.php" id="editor-form" class="article-editor-scope.editor-container article-editor-scope editor-container">
<main class="editor-main">
<?php if (isset($_SESSION["message"]) && $_SESSION["message"] == "internal_error"): ?>
<p class="alert-message is-error">
Es ist ein interner Fehler beim Speichern aufgetreten. Bitte versuche es erneut.
</p>
<?php endif; ?>
<?php if (isset($_SESSION["message"]) && $_SESSION["message"] == "missing_parameters"): ?>
<p class="alert-message is-error">
Jeder Beitrag muss einen Titel, Kategorie und Inhalt besitzen.
</p>
<?php endif; ?>
<?php if (isset($_SESSION["message"]) && $_SESSION["message"] == "invalid_title"): ?>
<p class="alert-message is-error">
Der Titel enthält ungültige Zeichen oder erfüllt die Länge von 5-120 Zeichen nicht.
</p>
<?php endif; ?>
<?php if (isset($_SESSION["message"]) && $_SESSION["message"] == "invalid_content"): ?>
<p class="alert-message is-error">
Der Text erlaubt eine Länge von 10 bis maximal 7.000 Zeichen (ca. 1.000 Wörter).
</p>
<?php endif; ?>
<?php if (isset($_SESSION["message"]) && $_SESSION["message"] == "invalid_category"): ?>
<p class="alert-message is-error">
Die ausgewählte Kategorie ist ungültig.
</p>
<?php endif; ?>
<?php if (isset($_SESSION["message"]) && $_SESSION["message"] == "invalid_tags"): ?>
<p class="alert-message is-error">
Ungültige Schlagworte gefunden. Erlaubt sind nur Buchstaben, Zahlen, Leerzeichen und Bindestriche (2-50 Zeichen).
</p>
<?php endif; ?>
<?php if (isset($_SESSION["message"]) && $_SESSION["message"] == "validation_missing"): ?>
<p class="alert-message is-error">
Bei der Validierung deiner Daten ist ein Fehler aufgetreten. Bitte versuche es erneut.
</p>
<?php endif; ?>
<?php
unset($_SESSION["message"]);
?>
<input type="text" id="title" name="title"
value="<?php echo htmlspecialchars($_SESSION['old_title'] ?? ''); unset($_SESSION['old_title']); ?>"
placeholder="Titel hier eingeben" required>
<textarea id="content" name="content" placeholder="Schreibe deinen Beitrag...">
<?php echo htmlspecialchars($_SESSION['old_content'] ?? ''); unset($_SESSION['old_content']); ?>
</textarea>
</main>
<!-- Seitenleiste -->
<aside class="editor-sidebar">
<div class="sidebar-block">
<button type="submit" class="btn-publish">Veröffentlichen</button>
</div>
<div class="sidebar-block">
<label for="category">Kategorie <span class="required">*</span></label>
<select id="category" name="category" required>
<option value="" disabled selected>Kategorie wählen...</option>
<optgroup label="Sprachen">
<option value="deutsch">Deutsch</option>
<option value="englisch">Englisch</option>
<option value="franzoesisch">Französisch</option>
<option value="latein">Latein</option>
<option value="literatur">Literatur</option>
</optgroup>
<optgroup label="MINT">
<option value="mathe">Mathematik</option>
<option value="biologie">Biologie</option>
<option value="chemie">Chemie</option>
<option value="physik">Physik</option>
<option value="informatik">Informatik</option>
<option value="astronomie">Astronomie</option>
</optgroup>
<optgroup label="Gesellschaft & Werte">
<option value="geschichte">Geschichte</option>
<option value="erdkunde">Erdkunde</option>
<option value="sozialkunde">Sozialkunde</option>
<option value="wirtschaft">Wirtschaftskunde</option>
<option value="religion">Religion</option>
<option value="ethik">Ethikunterricht</option>
<option value="philosophie">Philosophie</option>
<option value="psychologie">Psychologie</option>
<option value="kunst">Kunst</option>
<option value="musik">Musik</option>
<option value="theater">Theater</option>
</optgroup>
<optgroup label="Technik & Praxis">
<option value="technik">Technik</option>
<option value="werken">Werken</option>
<option value="hauswirtschaft">Hauswirtschaft</option>
<option value="sport">Sport</option>
</optgroup>
</select>
</div>
<div class="sidebar-block">
<label for="tags">Schlagwörter</label>
<input type="text" id="tags" name="tags"
value="<?php echo htmlspecialchars($_SESSION['old_tags'] ?? ''); unset($_SESSION['old_tags']); ?>"
placeholder="z.B. Technik, IT (mit Komma trennen)">
</div>
</aside>
</form>
+19
View File
@@ -0,0 +1,19 @@
<?php
require_once "php/model/LocalUserDAO.php";
$dao = new LocalUserDAO();
/*
Deregistrierung
Funktion: Entfernt User aus Dummy-Daten und beendet Session
*/
if (isset($_SESSION["user_email"])) {
$dao->deleteUser($_SESSION["user_email"]);
}
$_SESSION = [];
session_destroy();
header("Location: index.php");
exit();
+3 -21
View File
@@ -1,25 +1,8 @@
<?php
include_once 'php/controller/home-controller.php';
?>
<!--
Seite: Home
Inhalt: Beinhaltet den Inhalt der Startseite
-->
<main>
<?php if (isset($_SESSION["message"]) && $_SESSION["message"] == "internal_error"): ?>
<p class="alert-message is-error">
Es ist ein Fehler beim Speichern aufgetreten. Bitte versuche es erneut.
</p>
<?php endif; ?>
<?php if (isset($_SESSION["message"]) && $_SESSION["message"] == "new_article"): ?>
<p class="alert-message is-success">
Dein Beitrag wurde erfolgreich veröffentlicht!
</p>
<?php endif; ?>
<?php
unset($_SESSION["message"]);
?>
<h1>Home</h1>
<p>
@@ -36,23 +19,22 @@ include_once 'php/controller/home-controller.php';
<div class="container">
<a href="index.php?pfad=informatik" class="category-link">Informatik</a>
<div class="article-link">
<a href="index.php?pfad=showArticle&id=<?php echo $dummy3->getId()?>"><?php if(isset($dummy3)){echo $dummy3->getTitle();}else{echo "Fehler: Beitrag nicht gefunden!";} ?></a>
<a href="datenschutzVSdatensicherheit.php">Datenschutz vs. Datensicherheit</a>
</div>
</div>
<div class="container">
<a href="index.php?pfad=mathe" class="category-link">Mathe</a>
<div class="article-link">
<a href="index.php?pfad=showArticle&id=<?php echo $dummy1->getId()?>"><?php if(isset($dummy1)){echo $dummy1->getTitle();}else{echo "Fehler: Beitrag nicht gefunden!";} ?></a>
<a href="pythagoras.php">Satz des Pythagoras</a>
</div>
</div>
<div class="container">
<a href="index.php?pfad=physik" class="category-link">Physik</a>
<div class="article-link">
<a href="index.php?pfad=showArticle&id=<?php echo $dummy2->getId()?>"><?php if(isset($dummy2)){echo $dummy2->getTitle();}else{echo "Fehler: Beitrag nicht gefunden!";} ?></a>
<a href="tunneleffekt.php">Der Tunneleffekt</a>
</div>
</div>
</div>
</main>
+34 -13
View File
@@ -1,32 +1,53 @@
<?php
$error = $error ?? null;
?>
<!--
Form: Login-Bereich
Funktion: Benutzerauthentifizierung und Zugang zum eigenen Profil, Erstellen von Beiträgen, etc.
-->
<main class="login-page">
<div class="login-container">
<h1>Bitte anmelden</h1>
<form>
<label id ="inputEmail" class="screenreader-only">E-Mail Adresse / </label>
<?php if ($error): ?>
<p style="color:red;">
<?php echo htmlspecialchars($error); ?>
</p>
<?php endif; ?>
<form method="post" action="index.php?pfad=login">
<p class="input-label">Benutzername/E-Mail-Adresse:</p>
<input type="email" name="email" class="login-input" placeholder="E-Mail-Adresse" required autofocus>
<input type="email"
name="email"
class="login-input"
placeholder="E-Mail-Adresse"
required
autofocus>
<p class="input-label">Passwort:</p>
<input type="password" name="password" class="login-input" placeholder="Passwort" required>
<input type="password"
name="password"
class="login-input"
placeholder="Passwort"
required>
<div class="checkbox-wrapper">
<label>
<input type="checkbox" name="remember-me" value="1"> angemeldet bleiben
</label>
</div>
<button type="submit" value="anmelden" name="loginSubmit" class="login-button">anmelden</button>
<button type="submit"
value="anmelden"
name="loginSubmit"
class="login-button">
anmelden
</button>
<div class="register-link">
<a href="register.php">Noch keinen Account? Jetzt hier registrieren!</a>
<a href="index.php?pfad=register">
Noch keinen Account? Jetzt hier registrieren!
</a>
</div>
</form>
</div>
</main>
+6
View File
@@ -0,0 +1,6 @@
<?php
$_SESSION = [];
session_destroy();
header("Location: index.php");
exit();
+33 -83
View File
@@ -1,95 +1,45 @@
<!--
Content: Profil
Inhalt: Das eigene Profil, wenn man angemeldet ist. Dort hat man die Möglichkeit seine Angaben zu ändern.
-->
<?php
include_once 'php/controller/profileArticles-controller.php';
include_once 'php/controller/profile-controller.php';
$user = $user ?? null;
?>
<main class="form-page">
<div class="flexbox">
<!-- Linke Spalte: Profildaten -->
<div class="container">
<form>
<label class="input-label">Vorname</label>
<input type="text" name="Vorname" class="login-input" required
placeholder="Vorname"
value="<?php //DB-Daten ?>">
<div class="form-container">
<label class="input-label">Nachname</label>
<input type="text" name="Nachname" class="login-input" required
placeholder="Nachname"
value="<?php //DB-Daten ?>">
<h1>Mein Profil</h1>
<label class="input-label">Email-Adresse</label>
<input type="email" name="Email" class="login-input" required
placeholder="mustermann@web.de"
value="<?php //DB-Daten ?>">
<form>
<label class="input-label">Name</label>
<input type="text"
class="login-input"
readonly
value="<?php echo htmlspecialchars($user["username"] ?? ""); ?>">
<label class="input-label">Passwort</label>
<input type="password" name="Passwort" class="login-input"
required placeholder="Passwort">
<label class="input-label">Email-Adresse</label>
<input type="email"
class="login-input"
readonly
value="<?php echo htmlspecialchars($user["email"] ?? ""); ?>">
<button type="submit" class="login-button">
Speichern
</button>
<label class="input-label">Passwort</label>
<input type="password"
class="login-input"
readonly
value="********">
</form>
<button type="button" class="login-button delete-account-button">
Account löschen
</button>
</form>
</div>
<br>
<!-- Rechte Spalte: Eigene Beiträge -->
<div class="container">
<h2 class="section-title">Meine Beiträge</h2>
<div class="articles-list">
<?php if (isset($_SESSION["message"]) && $_SESSION["message"] == "internal_error"): ?>
<p class="alert-message is-error">
Es ist ein interner Fehler aufgetreten. Bitte versuche es erneut.
</p>
<?php elseif (isset($userArticles) && count($userArticles) > 0): ?>
<?php foreach ($userArticles as $userArticle): ?>
<!-- Ein einzelner Artikel-Eintrag -->
<div class="article-item">
<div class="article-meta">
<span class="article-date"><?php echo htmlspecialchars($userArticle->getCreationDate()); ?></span>
<span class="article-category"><?php echo htmlspecialchars($userArticle->getCategory()); ?></span>
</div>
<h3 class="article-title"><?php echo htmlspecialchars($userArticle->getTitle()); ?></h3>
<?php
$tags = $userArticle->getTags();
if (isset($tags) && !empty($tags)): ?>
<div class="article-view-bottom-section">
<div class="article-view-tags-label">Tags:</div>
<div class="article-view-tags-list">
<?php
$tagArray = is_array($tags) ? $tags : explode(',', $tags);
foreach ($tagArray as $tag):
$trimmedTag = trim($tag);
if (!empty($trimmedTag)):
?>
<span class="article-view-tag-item"><?php echo htmlspecialchars($trimmedTag); ?></span>
<?php
endif;
endforeach;
?>
</div>
</div>
<?php endif; ?>
<a href="index.php?pfad=updateArticle&id=<?php echo $userArticle->getID(); ?>" class="edit-link-button">Bearbeiten</a>
</div>
<?php endforeach; ?>
<?php else: ?>
<p>Du hast noch keine Beiträge erstellt.</p>
<button type="button" class="login-button" onclick="window.location.href='index.php?pfad=createArticle';">
Beitrag erstellen!
</button>
<?php endif; ?>
<?php
unset($_SESSION["message"]);
?>
</div>
</div>
<a href="index.php?pfad=deleteAccount" class="login-button">
Account löschen
</a>
<br><br>
<a href="index.php?pfad=logout" class="login-button">
Abmelden
</a>
</div>
</main>
+41 -11
View File
@@ -1,3 +1,9 @@
<?php
include_once 'php/controller/register-controller.php';
$error = $error ?? null;
?>
<!--
Form: Registrierung
Funktion: Erstellung neuer Benutzerkonten
@@ -7,26 +13,50 @@
<h1>Jetzt Registrieren!</h1>
<form>
<?php if ($error): ?>
<p style="color:red;">
<?php echo htmlspecialchars($error); ?>
</p>
<?php endif; ?>
<form method="post" action="index.php?pfad=register">
<p class="input-label">Email:</p>
<input type="email" name="email" class="login-input" placeholder="mustermann@web.de" required>
<input type="email"
name="email"
class="login-input"
placeholder="mustermann@web.de"
required>
<p class="input-label">Vorname:</p>
<input type="text" name="vorname" class="login-input" placeholder="Max" required>
<input type="text"
name="vorname"
class="login-input"
placeholder="Max"
required>
<p class="input-label">Nachname:</p>
<input type="text" name="nachname" class="login-input" placeholder="Mustermann" required>
<input type="text"
name="nachname"
class="login-input"
placeholder="Mustermann"
required>
<p class="input-label">Passwort:</p>
<input type="password" name="password" class="login-input" placeholder="Passwort" required>
<input type="password"
name="password"
class="login-input"
placeholder="Passwort"
required>
<div class="checkbox-wrapper">
<label>
<input type="checkbox" value="remember-me"> angemeldet bleiben
</label>
</div>
<button type="submit"
value="register"
name="registerSubmit"
class="login-button">
kostenlos registrieren
</button>
<button type="submit" value="anmelden" name="loginSubmit" class="login-button">kostenlos registrieren</button>
</form>
</div>
</main>
-125
View File
@@ -1,125 +0,0 @@
<?php
session_start();
?>
<!--
Seite: Suchergebnisse
Inhalt: Zeigt die Ergebnisse einer Suche an
-->
<div class="s-res-layout-grid">
<!-- Links: Seitenleiste für Filter und Suche -->
<aside class="s-res-sidebar">
<!-- Suchleiste Box -->
<div class="s-res-sidebar-box">
<h3 class="s-res-sidebar-title">Suche anpassen</h3>
<form action="#" method="GET" class="s-res-search-form">
<input type="search" id="site-search" name="q" placeholder="Suchen..." class="nav__search">
<button type="submit" class="nav__search-button">Suchen</button>
</form>
</div>
<!-- Sortierfuntion Box -->
<div class="s-res-sidebar-box">
<h3 class="s-res-sidebar-title">Sortierung</h3>
<div class="s-res-filter-group">
<label class="s-res-filter-option">
<input type="radio" name="sort" value="alphabet" checked>
<span>Alphabetisch</span>
</label>
<label class="s-res-filter-option">
<input type="radio" name="sort" value="likes">
<span>Beliebtheit (Likes)</span>
</label>
<label class="s-res-filter-option">
<input type="radio" name="sort" value="newest">
<span>Neueste Beiträge</span>
</label>
<label class="s-res-filter-option">
<input type="radio" name="sort" value="oldest">
<span>Älteste Beiträge</span>
</label>
</div>
</div>
</aside>
<main class="s-res-main-content">
<div class="s-res-header">
<h1 class="s-res-main-title">Suchergebnisse</h1>
<p class="s-res-meta">3 Treffer für Ihre Suchanfrage</p>
</div>
<!-- Ergebnisliste -->
<div class="s-res-list">
<?php
if(isset($_SESSION['message']) && $_SESSION['message'] == "new_search_results"): ?>
<!-- TODO: Hier die Beiträge ausgeben. -->
<?php elseif (isset($_SESSION["message"]) && $_SESSION["message"] == "missing_parameters"): ?>
<p>
Bitte überprüfe deine Sucheingabe und versuche es erneut!
</p>
<?php endif; ?>
<?php
unset($_SESSION["message"]);
?>
<!-- Beispielbeitrag -->
<div class="s-res-item">
<div class="s-res-content">
<h2 class="s-res-item-title">
<a href="#" class="s-res-link">Pythagoras</a>
</h2>
<p class="s-res-author">Von: <span class="s-res-author-name">Max Mustermann</span></p>
</div>
<div class="s-res-arrow">&rarr;</div>
</div>
<!-- Beispielbeitrag -->
<div class="s-res-item">
<div class="s-res-content">
<h2 class="s-res-item-title">
<a href="#" class="s-res-link">Pythagoras</a>
</h2>
<p class="s-res-author">Von: <span class="s-res-author-name">Max Mustermann</span></p>
</div>
<div class="s-res-arrow">&rarr;</div>
</div>
<!-- Beispielbeitrag -->
<div class="s-res-item">
<div class="s-res-content">
<h2 class="s-res-item-title">
<a href="#" class="s-res-link">Pythagoras</a>
</h2>
<p class="s-res-author">Von: <span class="s-res-author-name">Max Mustermann</span></p>
</div>
<div class="s-res-arrow">&rarr;</div>
</div>
</div>
<div class="s-res-pagination-footer">
<!-- Auswahl der Ergebnisse pro Seite -->
<div class="s-res-limit-selector">
<label for="s-res-per-page" class="s-res-limit-label">Ergebnisse pro Seite:</label>
<select id="s-res-per-page" name="limit" class="s-res-limit-select">
<option value="10" selected>10</option>
<option value="20">20</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
</div>
<div class="s-res-page-navigation">
<button type="button" class="s-res-page-btn" disabled>&laquo;</button>
<button type="button" class="s-res-page-btn s-res-page-btn-active">1</button>
<button type="button" class="s-res-page-btn">&raquo;</button>
</div>
</div>
</main>
</div>
-84
View File
@@ -1,84 +0,0 @@
<?php
include_once 'php/controller/showArticle-controller.php';
?>
<!--
Seite: Anzeige für Beiträge
Funktion: Stellt einen übergebenen Beitrag dar.
-->
<!-- Hauptcontainer für die Beitragsansicht (Ausschließlich der Content-Bereich) -->
<main class="article-view-container">
<?php if (isset($_SESSION["message"]) && $_SESSION["message"] == "internal_error"): ?>
<p class="alert-message is-error">
Es ist ein interner Fehler aufgetreten. Bitte versuche es erneut.
</p>
<?php endif; ?>
<?php if (isset($_SESSION["message"]) && $_SESSION["message"] == "missing_id"): ?>
<p class="alert-message is-error">
Es ist ein Fehler aufgetreten. Die ID konnte nicht ausgelesen werden. Bitte versuche es erneut.
</p>
<?php endif; ?>
<?php if (isset($_SESSION["message"]) && $_SESSION["message"] == "missing_parameters"): ?>
<p class="alert-message is-error">
Jeder Beitrag muss einen Titel, Kategorie und Inhalt besitzen.
</p>
<?php endif; ?>
<?php if (isset($_SESSION["message"]) && $_SESSION["message"] == "article_updated"): ?>
<p class="alert-message is-success">
Dein Beitrag wurde erfolgreich bearbeitet!
</p>
<?php endif; ?>
<?php
unset($_SESSION["message"]);
?>
<!-- Metadaten & Titel -->
<div class="article-view-top-section">
<?php if (isset($category) && !empty($category)): ?>
<span class="article-view-category"><?php echo htmlspecialchars($category); ?></span>
<?php endif; ?>
<h1 class="article-view-title">
<?php if (isset($title)) { echo htmlspecialchars($title); } ?>
</h1>
<div class="article-view-meta">
<?php if (isset($author) && !empty($author)): ?>
<span class="article-view-author">Von: <strong><?php echo htmlspecialchars($author); ?></strong></span>
<?php endif; ?>
</div>
</div>
<!-- Beitrags-Inhalt -->
<div class="article-view-content">
<?php if (isset($content)): ?>
<!-- nl2br für Zeilenumbrüche -->
<div class="article-view-body"><?php echo nl2br(htmlspecialchars($content)); ?></div>
<?php endif; ?>
</div>
<!-- Beitrags-Endbereich (Tags) -->
<?php if (isset($tags) && !empty($tags)): ?>
<div class="article-view-bottom-section">
<div class="article-view-tags-label">Tags:</div>
<div class="article-view-tags-list">
<?php
// Falls $tags ein String ist (z.B. "Web, CSS"), in ein Array umwandeln
$tagArray = is_array($tags) ? $tags : explode(',', $tags);
foreach ($tagArray as $tag):
$trimmedTag = trim($tag);
if (!empty($trimmedTag)):
?>
<span class="article-view-tag-item"><?php echo htmlspecialchars($trimmedTag); ?></span>
<?php
endif;
endforeach;
?>
</div>
</div>
<?php endif; ?>
</main>
-142
View File
@@ -1,142 +0,0 @@
<?php
include_once 'php/controller/showArticle-controller.php';
?>
<!--
Seite: Beitrag erstellen
Inhalt: Formular für die Erstellung eines neuen Beitrags
-->
<form method="post" action="php/controller/updateArticle-controller.php?id=<?php if(isset($id) && !empty($id)){echo htmlspecialchars($id);}else{$_SESSION["message"] = "missing_id";} ?>" id="editor-form" class="article-editor-scope.editor-container article-editor-scope editor-container">
<main class="editor-main">
<?php if (isset($_SESSION["message"]) && $_SESSION["message"] == "internal_error"): ?>
<p class="alert-message is-error">
Es ist ein interner Fehler beim Speichern aufgetreten. Bitte versuche es erneut.
</p>
<?php endif; ?>
<?php if (isset($_SESSION["message"]) && $_SESSION["message"] == "missing_id"): ?>
<p class="alert-message is-error">
Es ist ein Fehler aufgetreten. Die ID konnte nicht ausgelesen werden. Bitte versuche es erneut.
</p>
<?php endif; ?>
<?php if (isset($_SESSION["message"]) && $_SESSION["message"] == "missing_parameters"): ?>
<p class="alert-message is-error">
Jeder Beitrag muss einen Titel, Kategorie und Inhalt besitzen.
</p>
<?php endif; ?>
<?php if (isset($_SESSION["message"]) && $_SESSION["message"] == "invalid_title"): ?>
<p class="alert-message is-error">
Der Titel enthält ungültige Zeichen oder erfüllt die Länge von 5-120 Zeichen nicht.
</p>
<?php endif; ?>
<?php if (isset($_SESSION["message"]) && $_SESSION["message"] == "invalid_content"): ?>
<p class="alert-message is-error">
Der Text erlaubt eine Länge von 10 bis maximal 7.000 Zeichen (ca. 1.000 Wörter).
</p>
<?php endif; ?>
<?php if (isset($_SESSION["message"]) && $_SESSION["message"] == "invalid_category"): ?>
<p class="alert-message is-error">
Die ausgewählte Kategorie ist ungültig.
</p>
<?php endif; ?>
<?php if (isset($_SESSION["message"]) && $_SESSION["message"] == "invalid_tags"): ?>
<p class="alert-message is-error">
Ungültige Schlagworte gefunden. Erlaubt sind nur Buchstaben, Zahlen, Leerzeichen und Bindestriche (2-20 Zeichen).
</p>
<?php endif; ?>
<?php if (isset($_SESSION["message"]) && $_SESSION["message"] == "validation_missing"): ?>
<p class="alert-message is-error">
Bei der Validierung deiner Daten ist ein Fehler aufgetreten. Bitte versuche es erneut.
</p>
<?php endif; ?>
<?php
unset($_SESSION["message"]);
?>
<input type="text" id="title" name="title"
value="<?php
if (isset($title) && !empty($title)){echo htmlspecialchars($title);
}elseif (isset($_SESSION['old_title']) && !empty($_SESSION['old_title'])){
echo htmlspecialchars($_SESSION['old_title']);
unset($_SESSION['old_title']);
}
?>"
placeholder="Titel hier eingeben" required>
<textarea id="content" name="content" placeholder="Schreibe deinen Beitrag...">
<?php
if (isset($content) && !empty($content)){echo htmlspecialchars($content);
}elseif (isset($_SESSION['old_content']) && !empty($_SESSION['old_content'])){
echo htmlspecialchars($_SESSION['old_content']);
unset($_SESSION['old_content']);
}
?>
</textarea>
</main>
<!-- Seitenleiste -->
<aside class="editor-sidebar">
<div class="sidebar-block">
<button type="submit" class="btn-publish">Änderungen speichern</button>
</div>
<div class="sidebar-block">
<label for="category">Kategorie <span class="required">*</span></label>
<select id="category" name="category" required>
<option disabled selected>Kategorie wählen...</option>
<optgroup label="Sprachen">
<option value="deutsch">Deutsch</option>
<option value="englisch">Englisch</option>
<option value="franzoesisch">Französisch</option>
<option value="latein">Latein</option>
<option value="literatur">Literatur</option>
</optgroup>
<optgroup label="MINT">
<option value="mathe">Mathematik</option>
<option value="biologie">Biologie</option>
<option value="chemie">Chemie</option>
<option value="physik">Physik</option>
<option value="informatik">Informatik</option>
<option value="astronomie">Astronomie</option>
</optgroup>
<optgroup label="Gesellschaft & Werte">
<option value="geschichte">Geschichte</option>
<option value="erdkunde">Erdkunde</option>
<option value="sozialkunde">Sozialkunde</option>
<option value="wirtschaft">Wirtschaftskunde</option>
<option value="religion">Religion</option>
<option value="ethik">Ethikunterricht</option>
<option value="philosophie">Philosophie</option>
<option value="psychologie">Psychologie</option>
<option value="kunst">Kunst</option>
<option value="musik">Musik</option>
<option value="theater">Theater</option>
</optgroup>
<optgroup label="Technik & Praxis">
<option value="technik">Technik</option>
<option value="werken">Werken</option>
<option value="hauswirtschaft">Hauswirtschaft</option>
<option value="sport">Sport</option>
</optgroup>
</select>
</div>
<div class="sidebar-block">
<label for="tags">Schlagwörter</label>
<input type="text" id="tags" name="tags"
value="<?php
if (isset($tags) && !empty($tags)){echo htmlspecialchars($tags);
} elseif (isset($_SESSION['old_tags']) && !empty($_SESSION['old_tags'])){
echo htmlspecialchars($_SESSION['old_tags']);
unset($_SESSION['old_tags']);
}
?>"
placeholder="z.B. Technik, IT (mit Komma trennen)">
</div>
</aside>
</form>
-128
View File
@@ -1,128 +0,0 @@
/* editor in Flexbox */
.article-editor-scope.editor-container {
display: flex;
min-height: 100vh;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
color: #1e1e1e;
background-color: #f0f2f5;
box-sizing: border-box;
max-width: 1200px;
margin: 0 auto; /* Zentriert den gesamten Container horizontal */
width: 100%;
}
.article-editor-scope * {
box-sizing: border-box;
margin: 0;
padding: 0;
}
/* Hauptbereich */
.article-editor-scope .editor-main {
flex: 1;
padding: 40px;
display: flex;
flex-direction: column;
gap: 20px;
background: #ffffff;
}
.article-editor-scope #title {
font-size: 2.5rem;
font-weight: 700;
border: none;
outline: none;
width: 100%;
background: transparent;
}
.article-editor-scope #content {
flex: 1;
font-size: 1.1rem;
line-height: 1.6;
border: none;
outline: none;
resize: none;
width: 100%;
background: transparent;
}
/* Seitenleiste */
.article-editor-scope .editor-sidebar {
width: 300px;
background-color: #ffffff;
border-left: 1px solid #e0e0e0;
padding: 20px;
display: flex;
flex-direction: column;
gap: 24px;
}
.article-editor-scope .sidebar-block {
display: flex;
flex-direction: column;
gap: 8px;
}
.article-editor-scope .sidebar-block label {
font-weight: 600;
font-size: 0.9rem;
}
.article-editor-scope .required {
color: #d94f4f;
}
/* Formularelemente innerhalb der Editor-Sidebar */
.article-editor-scope .editor-sidebar select,
.article-editor-scope .editor-sidebar input[type="text"] {
width: 100%;
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 0.9rem;
background: #ffffff;
}
/* Button-Zeugs */
.article-editor-scope .btn-publish {
background-color: #007cba;
color: white;
border: none;
padding: 12px;
border-radius: 4px;
font-weight: 600;
cursor: pointer;
font-size: 1rem;
width: 100%;
}
.article-editor-scope .btn-publish:hover {
background-color: #006ba1;
}
/* Responsive Anpassungen unter 760px (für z.B. Smartphones) */
@media (max-width: 760px) {
.article-editor-scope.editor-container {
/* Sidebar nach unten */
flex-direction: column;
}
.article-editor-scope .editor-main {
/* weniger Innenabstand */
padding: 20px;
}
.article-editor-scope #content {
/* Verhindert, dass das Textfeld auf kleinen Displays kollabiert */
min-height: 300px;
}
.article-editor-scope .editor-sidebar {
width: 100%;
/* Entfernt den linken Rand und setzt ihn nach oben als Trenner */
border-left: none;
border-top: 1px solid #e0e0e0;
}
}
+2
View File
@@ -1,5 +1,7 @@
/* FooterGrundlayout */
footer {
position: fixed;
bottom: 0;
width: 100%;
background: #333d43;
text-align: center;
+1 -20
View File
@@ -3,19 +3,12 @@ main {
max-width:1200px;
margin: 0 auto;
padding: 20px;
width: 100%;
box-sizing: border-box;
}
body {
background-color: #eef2f7;
color: #1f2937;
margin: 0;
min-height: 100vh;
display: grid;
grid-template-rows: auto 1fr auto; /* Header(auto), Inhalt (bekommt Rest), Footer(auto) */
}
a, button, input, select, textarea, label, main{
@@ -24,8 +17,7 @@ a, button, input, select, textarea, label, main{
.flexbox {
display: flex;
flex-direction: row;
flex-wrap: wrap;
flex-direction: column;
gap: 20px;
margin-top: 30px;
}
@@ -37,7 +29,6 @@ a, button, input, select, textarea, label, main{
border: 1px solid #dbe3ec;
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
transition: transform 0.2s, box-shadow 0.2s;
flex: 1 1 300px;
}
.container:hover {
@@ -212,13 +203,3 @@ a, button, input, select, textarea, label, main{
border-radius: 10px;
box-shadow: 0 6px 20px rgba(0,0,0,0.1);
}
.form-container {
flex: 1 1 450px;
padding: 30px;
background-color: white;
border: 1px solid #dbe3ec;
border-radius: 10px;
box-shadow: 0 6px 20px rgba(0,0,0,0.1);
box-sizing: border-box;
}
-29
View File
@@ -1,29 +0,0 @@
.alert-message {
padding: 12px 16px;
margin: 12px 0;
border-radius: 6px;
border: 1px solid transparent;
font-family: sans-serif;
font-size: 14px;
font-weight: 500;
line-height: 1.5;
display: flex;
align-items: center;
gap: 10px;
}
/* Rote Fehlermeldung */
.alert-message.is-error {
color: #ba1a1a;
background-color: #ffeede;
border-color: #ffb4ab;
}
/* Grüne Erfolgsmeldung */
.alert-message.is-success {
color: #006e2c;
background-color: #e8f5e9;
border-color: #b2dfdb;
}
-21
View File
@@ -79,8 +79,6 @@ CSS für die navbar
text-decoration: none;
font-weight: 600;
margin-left: 0.5rem;
white-space: nowrap;
}
.nav__search {
@@ -207,10 +205,6 @@ CSS für die navbar
margin-left: 4px;
}
.nav__search-button:hover {
background-color: #f8f9fa;
}
/* restliche desktop-navbar aus */
.nav__center,
.nav__right .nav__button,
@@ -233,9 +227,6 @@ CSS für die navbar
padding: 2rem 1rem;
box-shadow: 2px 0 10px rgba(0,0,0,0.5);
overflow-y: auto;
/* Genug Abstand oben rechts, damit Links nicht hinter dem X liegen */
padding: 4rem 1.5rem 2rem 1.5rem;
}
.nav__checkbox:checked ~ .nav__mobile-menu {
@@ -246,18 +237,6 @@ CSS für die navbar
left: 0;
}
.nav__close-btn {
position: absolute;
top: 1rem;
right: 1.5rem;
font-size: 2rem;
color: #fff;
cursor: pointer;
line-height: 1;
user-select: none;
transition: color 0.2s ease, transform 0.2s ease;
}
.nav__mobile-menu a {
color: #fff;
text-decoration: none;
-89
View File
@@ -1,89 +0,0 @@
/*
CSS für die Profilseite
*/
/* Roter Button für Account löschen */
.delete-account-button {
background-color: #dc2626;
margin-bottom: 0;
}
.delete-account-button:hover {
background-color: #b91c1c;
}
/* Beitragsliste Styling */
.section-title {
margin-top: 0;
margin-bottom: 25px;
font-size: 1.5rem;
color: #1f2937;
border-bottom: 2px solid #eef2f7;
padding-bottom: 10px;
}
.articles-list {
display: flex;
flex-direction: column;
gap: 20px;
}
.article-item {
padding: 15px;
border: 1px solid #e5e7eb;
border-radius: 8px;
background-color: #f9fafb;
position: relative;
}
.article-meta {
display: flex;
justify-content: space-between;
font-size: 0.85rem;
color: #6b7280;
margin-bottom: 8px;
}
.article-category {
font-weight: bold;
color: #2563eb;
}
.article-title {
margin: 0 0 10px 0;
font-size: 1.2rem;
color: #1f2937;
}
.article-tags {
display: flex;
flex-wrap: wrap;
gap: 6px;
margin-bottom: 15px;
}
.tag {
font-size: 0.75rem;
background-color: #e5e7eb;
color: #374151;
padding: 3px 8px;
border-radius: 4px;
}
/* Bearbeiten-Button als Link deklariert */
.edit-link-button {
display: inline-block;
text-decoration: none;
font-size: 0.9rem;
font-weight: bold;
color: #2563eb;
border: 1px solid #2563eb;
padding: 6px 12px;
border-radius: 6px;
transition: background-color 0.2s, color 0.2s;
}
.edit-link-button:hover {
background-color: #2563eb;
color: white;
}
-263
View File
@@ -1,263 +0,0 @@
/*
CSS für die Suchergebnis-Seite
*/
/* Container und Layout-Schutz vor globalen Styles */
.s-res-layout-grid {
box-sizing: border-box;
max-width: 95%; /* Nutzt jetzt 95% der Bildschirmbreite statt starrer Pixel */
width: 95%; /* Erhöht das Limit für extrem große Monitore von 1200px auf 1600px */
margin: 2rem auto;
padding: 0 1rem;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
color: #212529;
line-height: 1.5;
/* Grid für die Zweispaltigkeit */
display: grid;
grid-template-columns: 320px 1fr; /* Seitenleiste leicht verbreitert, Inhalt nimmt den gesamten Rest ein */
gap: 2.5rem; /* Etwas mehr Abstand zwischen Seitenleiste und Inhalt für das breitere Layout */
}
.s-res-layout-grid * {
box-sizing: border-box;
}
/* --- SEITENLEISTE (FILTER & SUCHE) --- */
.s-res-sidebar {
display: flex;
flex-direction: column;
gap: 1.5rem;
}
.s-res-sidebar-box {
background-color: #ffffff;
border: 1px solid #e2e8f0;
border-radius: 8px;
padding: 1.25rem;
}
.s-res-sidebar-title {
font-size: 1rem;
font-weight: 700;
color: #1a202c;
margin: 0 0 1rem 0;
text-transform: uppercase;
letter-spacing: 0.05em;
}
/* Formular & deine Suchleisten-Klassen */
.s-res-search-form {
display: flex;
align-items: center;
}
/* Filter Radio-Buttons */
.s-res-filter-group {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.s-res-filter-option {
display: flex;
align-items: center;
gap: 0.5rem;
cursor: pointer;
font-size: 0.95rem;
color: #4a5568;
}
.s-res-filter-option input[type="radio"] {
margin: 0;
accent-color: #3182ce;
}
/* --- HAUPTINHALT (ERGEBNISSE) --- */
.s-res-main-content {
min-width: 0;
}
.s-res-header {
margin-bottom: 2rem;
border-bottom: 2px solid #dee2e6;
padding-bottom: 1rem;
}
.s-res-main-title {
font-size: 2rem;
color: #1a202c;
margin: 0 0 0.5rem 0;
font-weight: 700;
}
.s-res-meta {
color: #6c757d;
font-size: 0.95rem;
margin: 0;
}
.s-res-list {
display: flex;
flex-direction: column;
gap: 1rem;
}
/* Einzelner Beitrag */
.s-res-item {
background-color: #ffffff;
border: 1px solid #e2e8f0;
border-radius: 8px;
padding: 1.25rem;
display: flex;
justify-content: space-between;
align-items: center;
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}
.s-res-item:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
border-color: #cbd5e1;
}
.s-res-content {
flex: 1;
}
.s-res-item-title {
font-size: 1.25rem;
margin: 0 0 0.25rem 0;
font-weight: 600;
}
.s-res-link {
color: #3182ce;
text-decoration: none;
transition: color 0.2s ease;
}
.s-res-link:hover {
text-decoration: underline;
color: #2b6cb0;
}
.s-res-author {
font-size: 0.875rem;
color: #4a5568;
margin: 0;
}
.s-res-author-name {
font-weight: 600;
color: #2d3748;
}
.s-res-arrow {
font-size: 1.5rem;
color: #a0aec0;
padding-left: 1rem;
transition: color 0.2s ease, transform 0.2s ease;
}
.s-res-item:hover .s-res-arrow {
color: #3182ce;
transform: translateX(3px);
}
/* ERGEBNISSE PRO SEITE & PAGINIERUNG */
.s-res-pagination-footer {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 2rem;
padding-top: 1.5rem;
border-top: 1px solid #e2e8f0;
}
/* Dropdown-Auswahl */
.s-res-limit-selector {
display: flex;
align-items: center;
gap: 0.5rem;
}
.s-res-limit-label {
font-size: 0.9rem;
color: #4a5568;
}
.s-res-limit-select {
padding: 0.35rem 1.5rem 0.35rem 0.5rem;
font-size: 0.9rem;
color: #2d3748;
background-color: #ffffff;
border: 1px solid #cbd5e1;
border-radius: 4px;
cursor: pointer;
outline: none;
transition: border-color 0.2s;
/* Diskreter nativer Pfeil-Style */
appearance: none;
background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://w3.org' viewBox='0 0 24 24' fill='none' stroke='%234a5568' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 0.4rem center;
background-size: 1em;
}
.s-res-limit-select:focus {
border-color: #3182ce;
}
/* Seitennummern Navigation */
.s-res-page-navigation {
display: flex;
gap: 0.25rem;
}
.s-res-page-btn {
background-color: #ffffff;
border: 1px solid #cbd5e1;
color: #4a5568;
padding: 0.35rem 0.75rem;
font-size: 0.9rem;
font-weight: 500;
border-radius: 4px;
cursor: pointer;
transition: all 0.2s ease;
}
.s-res-page-btn:hover:not(:disabled) {
background-color: #f8f9fa;
border-color: #cbd5e1;
color: #2d3748;
}
.s-res-page-btn-active {
background-color: #3182ce;
border-color: #3182ce;
color: #ffffff;
cursor: default;
}
.s-res-page-btn:disabled {
background-color: #f1f5f9;
border-color: #e2e8f0;
color: #94a3b8;
cursor: not-allowed;
}
/* Responsive Anpassungen unter 760px (für z.B. Smartphones) */
@media (max-width: 768px) {
.s-res-layout-grid {
grid-template-columns: 1fr; /* Stapelt Seitenleiste und Inhalt untereinander */
gap: 1.5rem;
margin: 1rem auto;
}
.s-res-pagination-footer {
flex-direction: column;
gap: 1rem;
align-items: flex-start;
}
}
-118
View File
@@ -1,118 +0,0 @@
/* Container für den gesamten articleikel */
.article-view-container {
box-sizing: border-box;
max-width: 900px; /* Angenehme Lesebreite für längere Texte */
margin: 3rem auto;
padding: 0 2rem;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
color: #212529;
line-height: 1.6;
}
.article-view-container * {
box-sizing: border-box;
}
/* --- KOPFDATEN-BEREICH --- */
.article-view-top-section {
margin-bottom: 2.5rem;
border-bottom: 1px solid #e2e8f0;
padding-bottom: 1.5rem;
}
/* Kategorie-Badge */
.article-view-category {
display: inline-block;
background-color: #ebf8ff;
color: #2b6cb0;
font-size: 0.8rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.05em;
padding: 0.25rem 0.75rem;
border-radius: 4px;
margin-bottom: 0.75rem;
}
/* Hauptüberschrift */
.article-view-title {
font-size: 2.5rem;
color: #1a202c;
line-height: 1.2;
margin: 0 0 0.75rem 0;
font-weight: 800;
}
/* Autoren-Zeile */
.article-view-meta {
font-size: 0.95rem;
color: #4a5568;
}
.article-view-author strong {
color: #2d3748;
}
/* --- INHALT --- */
.article-view-content {
margin-bottom: 3rem;
}
.article-view-body {
font-size: 1.125rem;
color: #2d3748;
white-space: pre-line;
}
/* --- TAG-BEREICH --- */
.article-view-bottom-section {
border-top: 1px solid #e2e8f0;
padding-top: 1.5rem;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.article-view-tags-label {
font-size: 0.9rem;
font-weight: 600;
color: #718096;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.article-view-tags-list {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
/* Einzelner Tag */
.article-view-tag-item {
background-color: #f1f5f9;
color: #475569;
font-size: 0.85rem;
font-weight: 500;
padding: 0.35rem 0.75rem;
border-radius: 6px;
border: 1px solid #e2e8f0;
transition: background-color 0.2s, color 0.2s;
}
.article-view-tag-item:hover {
background-color: #e2e8f0;
color: #1e293b;
cursor: default;
}
/* Responsive Anpassungen unter 760px (für z.B. Smarticlephones) */
@media (max-width: 760px) {
.article-view-container {
margin: 1.5rem auto;
padding: 0 1rem;
}
.article-view-title {
font-size: 1.85rem;
}
}
+1
View File
@@ -0,0 +1 @@
[]
+3 -3
View File
@@ -1,5 +1,5 @@
<footer>
<a href="index.php?pfad=impressum">Impressum</a>
<a href="index.php?pfad=datenschutz">Datenschutz</a>
<a href="index.php?pfad=nutzungsbedingungen">Nutzungsbedingungen</a>
<a href="impressum.php">Impressum</a>
<a href="datenschutz.php">Datenschutz</a>
<a href="nutzungsbedingungen.php">Nutzungsbedingungen</a>
</footer>
+55 -20
View File
@@ -1,27 +1,37 @@
<?php
session_start();
?>
<!--
Globales Menü, wird via PHP später in alle Seiten eingebunden
-->
<nav class="nav">
<div class="nav__left">
<a href="index.php" class="nav__logo">
<img src="images/logos/logo_full.png" alt="Logo">
</a>
<img src="images/logos/logo_full.png" alt="Logo">
</a>
</div>
<!-- Mobile navbar mit Burger-Symbol -->
<input type="checkbox" id="nav-toggle" class="nav__checkbox">
<label for="nav-toggle" id="mobile-nav">
<span></span> <!-- Burger Icon Symbol -->
<span>☰</span>
</label>
<ul id="mobile-nav" class="nav__mobile-menu">
<li>
<label for="nav-toggle" class="nav__close-btn">&times;</label>
</li>
<li><a href="index.php?pfad=profile">Profil</a></li>
<li><a href="index.php?pfad=login">Anmelden</a></li>
<li><a href="index.php?pfad=register">Registrieren</a></li>
<li><a href="index.php?pfad=createArticle">Beitrag erstellen</a></li>
<?php if (isset($_SESSION['user'])): ?>
<li><a href="index.php?pfad=profile">Profil</a></li>
<li><a href="index.php?pfad=logout">Abmelden</a></li>
<?php else: ?>
<li><a href="index.php?pfad=login">Anmelden</a></li>
<li><a href="index.php?pfad=register">Registrieren</a></li>
<?php endif; ?>
<li>
<label class="nav__mobile-label">Sprachen</label>
<ul class="nav__mobile-submenu">
@@ -39,7 +49,7 @@ Globales Menü, wird via PHP später in alle Seiten eingebunden
<li><a href="index.php?pfad=mathe">Mathematik</a></li>
<li><a href="index.php?pfad=biologie">Biologie</a></li>
<li><a href="index.php?pfad=chemie">Chemie</a></li>
<li><a href="index.php?pfad=englisch">Physik</a></li>
<li><a href="index.php?pfad=physik">Physik</a></li>
<li><a href="index.php?pfad=informatik">Informatik</a></li>
<li><a href="index.php?pfad=astronomie">Astronomie</a></li>
</ul>
@@ -85,6 +95,7 @@ Globales Menü, wird via PHP später in alle Seiten eingebunden
<a href="index.php?pfad=literatur">Literatur</a>
</div>
</div>
<div class="nav__item nav__dropdown">
<button class="nav__dropdown-toggle">MINT</button>
<div class="nav__dropdown-menu">
@@ -96,6 +107,7 @@ Globales Menü, wird via PHP später in alle Seiten eingebunden
<a href="index.php?pfad=astronomie">Astronomie</a>
</div>
</div>
<div class="nav__item nav__dropdown">
<button class="nav__dropdown-toggle">Gesellschaft & Werte</button>
<div class="nav__dropdown-menu">
@@ -112,6 +124,7 @@ Globales Menü, wird via PHP später in alle Seiten eingebunden
<a href="index.php?pfad=theater">Theater</a>
</div>
</div>
<div class="nav__item nav__dropdown">
<button class="nav__dropdown-toggle">Technik & Praxis</button>
<div class="nav__dropdown-menu">
@@ -124,14 +137,36 @@ Globales Menü, wird via PHP später in alle Seiten eingebunden
</div>
<div class="nav__right">
<a href="index.php?pfad=profile" class="nav_item nav__link">Profil</a>
<div class="nav__search">
<?php
include_once 'search.php';
?>
</div>
<a href="index.php?pfad=login" class="nav__item nav__button">Anmelden</a>
<a href="index.php?pfad=register" class="nav__item nav__button">Registrieren</a>
<a href="index.php?pfad=createArticle" class="nav__item nav__button">Beitrag erstellen</a>
<?php if (isset($_SESSION['user'])): ?>
<a href="index.php?pfad=profile" class="nav__item nav__link">
Profil
</a>
<div class="nav__search">
<?php include_once 'search.php'; ?>
</div>
<a href="index.php?pfad=logout" class="nav__item nav__button">
Abmelden
</a>
<?php else: ?>
<div class="nav__search">
<?php include_once 'search.php'; ?>
</div>
<a href="index.php?pfad=login" class="nav__item nav__button">
Anmelden
</a>
<a href="index.php?pfad=register" class="nav__item nav__button">
Registrieren
</a>
<?php endif; ?>
</div>
</nav>
+61 -41
View File
@@ -1,52 +1,72 @@
<?php
session_start();
if (!isset($abs_path)) {
require_once "path.php";
ob_start();
$pfad = $_GET["pfad"] ?? "home";
/*
Controller für Aktionen werden vor der HTML-Ausgabe geladen,
damit Weiterleitungen mit header() funktionieren.
*/
if ($pfad === "login") {
include_once "php/controller/login-controller.php";
}
if ($pfad === "register") {
include_once "php/controller/register-controller.php";
}
if ($pfad === "logout") {
include_once "content/logout.php";
exit();
}
if ($pfad === "deleteAccount") {
include_once "content/deleteAccount.php";
exit();
}
require_once $abs_path . "/php/controller/index-controller.php";
?>
<!--
Seite: Index der Lernplattform
Funktion: Webseitengerüst, Anzeigen von Content
-->
<!DOCTYPE html>
<html lang="de">
<!--
Seite: Index der Lernplattform
Funktion: Webseitengerüst, Anzeigen von Content
-->
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="description" content="EduForge">
<meta name="author" content="Niklas Ortmann">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/x-icon" href="images/logos/logo_icon.ico">
<link rel="stylesheet" href="css/main.css">
<link rel="stylesheet" href="css/navbar.css">
<link rel="stylesheet" href="css/footer.css">
<link rel="stylesheet" href="css/search-results.css">
<link rel="stylesheet" href="css/createArticle.css">
<link rel="stylesheet" href="css/profile.css">
<link rel="stylesheet" href="css/showArticle.css">
<link rel="stylesheet" href="css/message.css">
<title>EduForge</title>
</head>
<head>
<meta charset="utf-8">
<meta name="description" content="EduForge">
<meta name="author" content="Niklas Ortmann">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/x-icon" href="images/logos/logo_icon.ico">
<link rel="stylesheet" href="css/main.css">
<link rel="stylesheet" href="css/navbar.css">
<link rel="stylesheet" href="css/footer.css">
<title>EduForge</title>
</head>
<body>
<body>
<?php
include_once 'includes/navbar.php';
//Dynamischer Inhalt:
if (isset($_GET["pfad"])) {
if (file_exists($abs_path . '/content/' . $_GET["pfad"] . '.php')) {
include_once $abs_path . '/content/' . $_GET["pfad"] . '.php';
} else {
include_once $abs_path . '/content/404.php';
}
} else {
include_once $abs_path . '/content/home.php';
}
include_once $abs_path . '/includes/footer.php';
?>
</body>
</html>
/*
Dynamischer Inhalt:
Je nach pfad-Parameter wird die passende Datei aus content geladen.
*/
if (file_exists('content/' . $pfad . '.php')) {
include_once 'content/' . $pfad . '.php';
} else {
include_once 'content/404.php';
}
include_once 'includes/footer.php';
?>
</body>
</html>
<?php
ob_end_flush();
?>
@@ -10,10 +10,10 @@
<meta name="description" content="EduForge">
<meta name="author" content="Niklas Ortmann">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/x-icon" href="../images/logos/logo_icon.ico">
<link rel="stylesheet" href="../css/main.css">
<link rel="stylesheet" href="../css/navbar.css">
<link rel="stylesheet" href="../css/footer.css">
<link rel="icon" type="image/x-icon" href="images/logos/logo_icon.ico">
<link rel="stylesheet" href="css/main.css">
<link rel="stylesheet" href="css/navbar.css">
<link rel="stylesheet" href="css/footer.css">
<title>EduForge</title>
</head>
-4
View File
@@ -1,4 +0,0 @@
<?php
// mit $_SERVER['DOCUMENT_ROOT'] später umbauen?
$abs_path = __DIR__;
?>
@@ -1,86 +0,0 @@
<?php
session_start();
require_once '../model/LocalArticleManager.php';
require_once '../model/ArticleManager.php';
require_once '../validator/article-validator.php';
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$_SESSION["old_title"] = $_POST["title"] ?? '';
$_SESSION["old_content"] = $_POST["content"] ?? '';
$_SESSION["old_category"] = $_POST["category"] ?? '';
$_SESSION["old_tags"] = $_POST["tags"] ?? '';
if(!isset($_POST["title"]) ||!isset($_POST["content"]) || !isset($_POST["category"])){
$_SESSION["message"] = "missing_parameters";
header("location: ../../index.php?pfad=createArticle");
exit();
} else {
$title = $_POST["title"];
$content = $_POST["content"];
$author = "max.mustermann"; // TODO: später aus Session den angemeldeten Nutzer beziehen.
$category = $_POST["category"];
$tags = $_POST['tags'] ?? '';
// -------------------------------- Validierung der Daten: -------------------------
if (!articleAuthorValidator($author)) {
$_SESSION["message"] = "author_not_valid";
header("location: ../../index.php?pfad=createArticle");
exit();
}
if (!articleTitleValidator($title)) {
$_SESSION["message"] = "invalid_title";
header("location: ../../index.php?pfad=createArticle");
exit();
}
if (!articleContentValidator($content)) {
$_SESSION["message"] = "invalid_content";
header("location: ../../index.php?pfad=createArticle");
exit();
}
if (!articleCategoryValidator($category)) {
$_SESSION["message"] = "invalid_category";
header("location: ../../index.php?pfad=createArticle");
exit();
}
if (!articleTagValidator($tags)) {
$_SESSION["message"] = "invalid_tags";
header("location: ../../index.php?pfad=createArticle");
exit();
} else {
$cleanedTags = [];
$rawTags = explode(',', $tags);
foreach ($rawTags as $rawTag) {
// Leerzeichen am Anfang/Ende des einzelnen Tags entfernen:
$tag = trim($rawTag);
$cleanedTags[] = $tag;
}
// Duplikate entfernen:
$cleanedTags = array_unique($cleanedTags);
$cleanedTags = implode(',', $cleanedTags);
}
// ----------------- Übertragung der validierten Daten in ArticleManager: ---------------------------
try {
$articleManager = ArticleManager::getInstance();
$articleManager->addArticle($title, $content, $author, $category, $cleanedTags);
// Formulardaten nach erfolgreichem Erstellen aus der Session löschen
unset($_SESSION["old_title"], $_SESSION["old_content"], $_SESSION["old_category"], $_SESSION["old_tags"]);
} catch (Exception $e){
$_SESSION["message"] = "internal_error";
header("location: ../../index.php?pfad=createArticle");
exit();
}
$_SESSION["message"] = "new_article";
// Weiterleitung zur Homepage
header("location: ../../index.php");
exit();
}
}
?>
-17
View File
@@ -1,17 +0,0 @@
<?php
session_start();
require_once 'php/model/Article.php';
require_once 'php/model/ArticleManager.php';
require_once 'php/model/LocalArticleManager.php';
try {
$articleManager = ArticleManager::getInstance();
// Beziehen der Dummy-Beiträge aus dem ArticleManager:
$dummy1 = $articleManager->getArticle(1);
$dummy2 = $articleManager->getArticle(2);
$dummy3 = $articleManager->getArticle(3);
} catch (Exception $e){
$_SESSION["message"] = "internal_error";
echo "Fehler aufgetreten: " . $e->getMessage();
}
?>
-3
View File
@@ -1,3 +0,0 @@
<?php
?>
+30
View File
@@ -0,0 +1,30 @@
<?php
require_once "php/model/LocalUserDAO.php";
$dao = new LocalUserDAO();
$error = null;
/*
Verarbeitung des Login-Formulars
Funktion: Prüft Benutzerdaten und erstellt Session für eingeloggten Nutzer
*/
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$email = $_POST["email"] ?? "";
$password = $_POST["password"] ?? "";
$user = $dao->findUser($email);
if ($user && password_verify($password, $user["password"])) {
$_SESSION["user"] = $user["username"];
$_SESSION["user_email"] = $user["email"];
header("Location: index.php");
exit();
} else {
$error = "Login fehlgeschlagen. Bitte überprüfe deine Eingaben.";
}
}
+20
View File
@@ -0,0 +1,20 @@
<?php
require_once "php/model/LocalUserDAO.php";
$dao = new LocalUserDAO();
if (!isset($_SESSION["user"])) {
header("Location: index.php?pfad=login");
exit();
}
$user = $dao->findUser($_SESSION["user_email"] ?? "");
if (!$user) {
$_SESSION = [];
session_destroy();
header("Location: index.php?pfad=login");
exit();
}
@@ -1,21 +0,0 @@
<?php
/*
* Controller für die Liste der eigenen Beiträge eines Nutzers auf der eigenen Profilseite
*/
session_start();
require_once 'php/model/Article.php';
require_once 'php/model/ArticleManager.php';
try {
$author = "max.mustermann"; // TODO: später Nutzer aus der Session beziehen.
$articleManager = ArticleManager::getInstance();
$userArticles = $articleManager->getArticlesByAuthor($author);
if(!isset($userArticles)) {
$_SESSION["message"] = "user_has_no_articles";
}
} catch (Exception $e) {
$_SESSION["message"] = "internal_error";
}
?>
+40
View File
@@ -0,0 +1,40 @@
<?php
require_once "php/model/LocalUserDAO.php";
$dao = new LocalUserDAO();
$error = null;
/*
Verarbeitung des Registrierungs-Formulars
Funktion: Erstellt neuen Benutzer und speichert ihn im DAO + Session
*/
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$email = $_POST["email"] ?? "";
$vorname = $_POST["vorname"] ?? "";
$nachname = $_POST["nachname"] ?? "";
$password = password_hash(
$_POST["password"] ?? "",
PASSWORD_DEFAULT
);
if ($dao->findUser($email)) {
$error = "Diese E-Mail-Adresse ist bereits registriert.";
} else {
$dao->addUser(
$email,
$vorname . " " . $nachname,
$password
);
$_SESSION["user"] = $vorname . " " . $nachname;
$_SESSION["user_email"] = $email;
header("Location: index.php");
exit();
}
}
@@ -1,29 +0,0 @@
<?php
session_start();
require_once '../model/LocalArticleManager.php';
require_once '../model/ArticleManager.php';
if ($_SERVER["REQUEST_METHOD"] === "POST") {
if(!isset($_POST["search"])){
$_SESSION["message"] = "missing_parameters";
header("location: ../../index.php?pfad=search-results");
} else {
$search = $_POST["search"];
try {
$articleManager = ArticleManager::getInstance();
$articleManager->search($search); // TODO: Methode implementieren.
} catch (Exception $e){
$_SESSION["message"] = "internal_error";
}
$_SESSION["message"] = "new_search_results";
// TODO: Liste mit Artikeln in der Suchreihenfolge übertragen.
// Weiterleitung zur Suchergebnisanzeige
header("location: ../../index.php?pfad=search-results");
exit();
}
}
?>
-29
View File
@@ -1,29 +0,0 @@
<?php
session_start();
require_once 'php/model/Article.php';
require_once 'php/model/ArticleManager.php';
if (isset($_GET["id"]) && !empty($_GET["id"])){
try {
$id = $_GET["id"];
$articleManager = ArticleManager::getInstance();
$article = $articleManager->getArticle($id);
if($article != null){
$title = $article->getTitle();
$content = $article->getContent();
$category = $article->getCategory();
$author = $article->getAuthor();
$tags = $article->getTags();
}else{
//header("location: index.php?pfad=404");
include_once "content/404.php";
exit();
}
} catch (Exception $e){
$_SESSION["message"] = "internal_error";
exit();
}
}else{
$_SESSION["message"] = "missing_id";
}
?>
@@ -1,95 +0,0 @@
<?php
session_start();
require_once '../model/LocalArticleManager.php';
require_once '../model/ArticleManager.php';
require_once '../model/Article.php';
require_once '../validator/article-validator.php';
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$_SESSION["old_title"] = $_POST["title"] ?? '';
$_SESSION["old_content"] = $_POST["content"] ?? '';
$_SESSION["old_category"] = $_POST["category"] ?? '';
$_SESSION["old_tags"] = $_POST["tags"] ?? '';
if (isset($_GET["id"]) && !empty($_GET["id"])) {
$id = $_GET["id"];
} else {
$_SESSION["message"] = "missing_id";
header("location: ../../index.php?pfad=updateArticle");
exit();
}
if (!isset($_POST["title"]) ||!isset($_POST["content"]) || !isset($_POST["category"])){
$_SESSION["message"] = "missing_parameters";
header("location: ../../index.php?pfad=updateArticle");
exit();
}else{
$title = $_POST["title"];
$content = $_POST["content"];
$author = "max.mustermann"; // TODO: später aus Session den angemeldeten Nutzer beziehen.
$category = $_POST["category"];
$tags = $_POST['tags'] ?? '';
// -------------------------------- Validierung der Daten: -------------------------
if (!articleAuthorValidator($author)) {
$_SESSION["message"] = "author_not_valid";
header("location: ../../index.php?pfad=updateArticle");
exit();
}
if (!articleTitleValidator($title)) {
$_SESSION["message"] = "invalid_title";
header("location: ../../index.php?pfad=updateArticle");
exit();
}
if (!articleContentValidator($content)) {
$_SESSION["message"] = "invalid_content";
header("location: ../../index.php?pfad=updateArticle");
exit();
}
if (!articleCategoryValidator($category)) {
$_SESSION["message"] = "invalid_category";
header("location: ../../index.php?pfad=updateArticle");
exit();
}
if (!articleTagValidator($tags)) {
$_SESSION["message"] = "invalid_tags";
header("location: ../../index.php?pfad=updateArticle");
exit();
} else {
$cleanedTags = [];
$rawTags = explode(',', $tags);
foreach ($rawTags as $rawTag) {
// Leerzeichen am Anfang/Ende des einzelnen Tags entfernen:
$tag = trim($rawTag);
$cleanedTags[] = $tag;
}
// Duplikate entfernen:
$cleanedTags = array_unique($cleanedTags);
$cleanedTags = implode(',', $cleanedTags);
}
// ----------------- Übertragung der validierten Daten in ArticleManager: ---------------------------
try {
$articleManager = ArticleManager::getInstance();
$article = $articleManager->getArticle($id);
$article->setTitle($title);
$article->setContent($content);
$article->setCategory($category);
$article->setTags($cleanedTags);
$articleManager->updateArticle($id ,$article, $author);
} catch (Exception $e){
$_SESSION["message"] = "internal_error";
header("location: ../../index.php?pfad=updateArticle");
exit();
}
$_SESSION["message"] = "article_updated";
// Weiterleitung zur Homepage
header("location: ../../index.php?pfad=showArticle&id=$id");
}
}
?>
-147
View File
@@ -1,147 +0,0 @@
<?php
/**
* Klasse: Artikel
* Diese Klasse stellt alle Daten eines Beitrags (Beitrag) bereit
*
* @author Niklas Ortmann
*/
class Article
{
private $id;
private $title;
private $content;
private $author;
private $creationDate;
private $category;
private $tags;
/**
* Konstruktor
*
* @param $id integer ID des Beitrages
* @param $title string Titel des Beitrags
* @param $content string Inhalt des Beitrags
* @param $author string der Autor des des Beitrages NID
* @param $category string Kategorie des Beitrages
* @param $tags string optionale Schlagworte für eine bessere Suche
* @param $creationDate string Datum der Beitragserstellung
*/
public function __construct(int $id, string $title, string $content, string $author, string $category, string $tags, string $creationDate)
{
$this->id = $id;
$this->title = $title;
$this->content = $content;
$this->author = $author;
$this->creationDate = $creationDate;
$this->category = $category;
$this->tags = $tags;
}
/**
* Gibt die ID eines Beitrags zurück.
* @return int
*/
public function getId(): int
{
return $this->id;
}
/**
* Gibt den Titel eines Beitrags zurück.
* @return string
*/
public function getTitle(): string
{
return $this->title;
}
/**
* Setzt den Titel eines Beitrags
* @param $title
* @return void
*/
public function setTitle($title)
{
$this->title = $title;
}
/**
* Gibt den Content eines Beitrags zurück.
* TODO: Content muss noch definiert werden.
* @return string
*/
public function getContent(): string
{
return $this->content;
}
/**
* Setzt den Content eines Beitrags.
* TODO: Content muss noch definiert werden.
* @param $content
* @return void
*/
public function setContent($content)
{
$this->content = $content;
}
/**
* Gibt den Autor eines Beitrags zurück.
* @return string
*/
public function getAuthor(): string
{
return $this->author;
}
/**
* Gibt das Veröffentlichungsdatum des Beitrags zurück.
* @return string
*/
public function getCreationDate(): string
{
return $this->creationDate;
}
/**
* Gibt die Kategorie eines Beitrags zurück.
* @return string
*/
public function getCategory(): string
{
return $this->category;
}
/**
* Setzt die Kategorie eines Beitrags.
* @param string $category
* @return void
*/
public function setCategory(string $category)
{
$this->category = $category;
}
/**
* Gibt die Schlagworte eines Beitrags zurück.
* @return string
*/
public function getTags(): string
{
return $this->tags;
}
/**
* Setzt die Schlagworte eines Beitrags.
* @param string $tags
*/
public function setTags(string $tags)
{
$this->tags = $tags;
}
}
?>
-47
View File
@@ -1,47 +0,0 @@
<?php
require_once 'LocalArticleManager.php';
require_once 'Article.php';
/**
* Die Klasse beinhaltet alle Methoden für die Operation mit den Artikel-Daten.
*
* @author Niklas Ortmann
*/
class ArticleManager extends LocalArticleManager
{
public static function getInstance()
{
$articleManager = LocalArticleManager::getInstance(); // TODO: später durch DataBaseArticleManager ersetzen.
// Erstellen von Dummy-Beiträgen:
if($articleManager->getArticle(1) == null ){
$articleManager->addArticle(
"Satz des Pythagoras",
"Der Satz des Pythagoras wurde von dem griechischen Philosophen Pythagoras von Samos formuliert und im dritten Jahrhundert vor Christus veröffentlicht. In der beigefügten Abbildung sehen wir ein rechtwinkliges Dreieck...",
"max.mustermann",
"Mathe",
"Dreiecke, Dreiecksseiten berechnen"
);
}
if($articleManager->getArticle(2) == null ){
$articleManager->addArticle(
"Tunneleffekt",
"Der Tunneleffekt ist ein quantenmechanisches Phänomen, bei dem Teilchen...",
"max.mustermann",
"Physik",
"Quantenphysik, Energie"
);
}
if($articleManager->getArticle(3) == null ){
$articleManager->addArticle(
"Datenschutz vs Datensicherheit",
"Datenschutz ist in unserer digital vernetzten Welt allgegenwärtig...",
"max.mustermann",
"Informatik",
"Daten, DSGVO"
);
}
return $articleManager;
}
}
-71
View File
@@ -1,71 +0,0 @@
<?php
require_once "Article.php";
/**
* Die Klasse beinhaltet alle Methoden für die Operation mit den Artikel-Daten.
*
* @author Niklas Ortmann
*/
interface ArticleManagerDAO
{
/**
* Ein angemeldeter Nutzer erstellt einen neuen Beitrag.
* @param $title string Titel des Beitrags
* @param $content string Inhalt des Beitrags
* @param $author string der Autor des des Beitrages NID
* @param $category string Kategorie des Beitrages
* @param $tags string optionale Schlagworte für eine bessere Suche
*
* Mögliche Exceptions:
* TODO Fehlerbeschreibung hinzufügen & tags hinzufügen
*/
public function addArticle($title, $content, $author, $category, $tags);
/**
* Ändert den gespeicherten Beitrag eines übergebenen Beitrags und eines Autors.
* Es wird geprüft, ob der zu änderne Beitrag existiert und ob der übergebene Autor der Autor des originalen
* Beitrages ist.
* @param $id
* @param $article
* @param $author
* @return void
*
* TODO: Fehlerbeschreibung hinzufügen
*/
public function updateArticle($id, $article, $author);
/**
* Löscht einen Beitrag aus übergebener ID.
* @param $id
* @return void
*
* TODO: Fehlerbeschreibung hinzufügen
*/
public function deleteArticle($id);
/**
* Beitrag aufrufen.
* $id ID des Beitrags
*
* @return Article
* Mögliche Exceptions:
* TODO Fehlerbeschreibung hinzufügen
*/
public function getArticle($id);
/**
* Alle Beiträge aufrufen.
*
* Mögliche Exceptions:
* TODO Fehlerbeschreibung hinzufügen
*/
public function getAllArticles();
/**
* Gibt alle Beiträge eines Nutzer mit einer gegebenen ID aus.
* @param $author
* @return Article[]
*/
public function getArticlesByAuthor($author);
}
?>
-172
View File
@@ -1,172 +0,0 @@
<?php
require_once 'ArticleManagerDAO.php';
require_once 'Article.php';
/**
* Klasse: Eine lokale Lösung des ArticleManagerDAO.
* Schreibt zunächst Daten lokal in das Verzeichnis und kann diese wieder auslesen.
*
* @author Niklas Ortmann
*/
class LocalArticleManager implements ArticleManagerDAO {
private $file;
private static $instance = null;
/**
* Konstruktor
*/
public function __construct()
{
$this->file = __DIR__ . '/../../data/articles.json';
}
/**
* Gibt die LocalArticleManager-Instanz zurück.
* @return LocalArticleManager
*/
public static function getInstance()
{
if (self::$instance == null) {
self::$instance = new LocalArticleManager();
}
return self::$instance;
}
/**
* Speichert alle Artikel/Beiträge in der Datei.
* @param $articles
* @return void
*/
public function saveArticle($articles)
{
file_put_contents(
$this->file,
json_encode($articles, JSON_PRETTY_PRINT)
);
}
public function addArticle($title, $content, $author, $category, $tags)
{
$articles = $this->getAllArticles();
$articles[] = [
"id" => count($articles)+1,
"title" => $title,
"content" => $content,
"author" => $author,
"category" => $category,
"tags" => $tags,
"creationDate" => date("Y-m-d H:i:s")
];
$this->saveArticle($articles);
}
public function updateArticle($id, $article, $author)
{
if (empty($article)) {
// TODO: Implement Exception.
return;
}
// Berechtigungsprüfung:
if ($article->getAuthor() !== $author) {
// TODO: Implement Exception.
return;
}
// Beitrag aktualisieren:
$articles = $this->getAllArticles();
$updated = false;
foreach ($articles as $index => $storedArticle) {
if (isset($storedArticle['id']) && $storedArticle['id'] == $id) {
$articles[$index] = [
"id" => $id,
"title" => $article->getTitle(),
"content" => $article->getContent(),
"author" => $author,
"category" => $article->getCategory(),
"tags" => $article->getTags(),
"creationDate" => $article->getCreationDate()
];
$updated = true;
break;
}else{
// TODO: Implement Exception.
return;
}
}
// Nur speichern, wenn Beitrag geändert wurde:
if ($updated) {
$this->saveArticle($articles);
}
}
public function deleteArticle($id)
{
$articles = $this->getAllArticles();
$articleFound = false;
foreach ($articles as $index => $article) {
if (isset($article['id']) && $article['id'] == $id) {
unset($articles[$index]);
$articleFound = true;
break; // Schleife abbrechen, da die ID eindeutig ist
}
}
if ($articleFound) {
// array_values stellt sicher, dass die Array-Keys wieder fortlaufend bei 0 beginnen
$this->saveArticle(array_values($articles));
}
}
public function getArticle($id)
{
$articles = $this->getAllArticles();
foreach ($articles as $article) {
if (isset($article['id']) && $article['id'] == $id) {
return new Article(intval($article['id']), $article['title'], $article['content'], $article['author'], $article['category'], $article['tags'], $article['creationDate']);
}
}
return null;
}
public function getAllArticles(): array
{
if (!file_exists($this->file)) {
return [];
}
$json = file_get_contents($this->file);
$articles = json_decode($json, true);
return is_array($articles) ? $articles : [];
}
public function getArticlesByAuthor($author)
{
$articles = $this->getAllArticles();
$filteredArticles = [];
foreach ($articles as $article) {
if (isset($article['author']) && $article['author'] == $author) {
$filteredArticles[] = new Article(
intval($article['id']),
$article['title'],
$article['content'],
$article['author'],
$article['category'],
$article['tags'],
$article['creationDate']
);
}
}
return $filteredArticles;
}
}
?>
+64
View File
@@ -0,0 +1,64 @@
<?php
require_once "UserDAOInterface.php";
class LocalUserDAO implements UserDAOInterface {
private string $file = "data/users.json";
private function loadUsers() {
if (!file_exists($this->file)) {
return [];
}
$json = file_get_contents($this->file);
$users = json_decode($json, true);
return is_array($users) ? $users : [];
}
private function saveUsers($users) {
file_put_contents(
$this->file,
json_encode($users, JSON_PRETTY_PRINT)
);
}
public function findUser($email) {
$users = $this->loadUsers();
foreach ($users as $user) {
if ($user["email"] === $email) {
return $user;
}
}
return null;
}
public function addUser($email, $username, $password) {
$users = $this->loadUsers();
$users[] = [
"email" => $email,
"username" => $username,
"password" => $password
];
$this->saveUsers($users);
}
public function deleteUser($email) {
$users = $this->loadUsers();
foreach ($users as $i => $user) {
if ($user["email"] === $email) {
unset($users[$i]);
$users = array_values($users);
$this->saveUsers($users);
return true;
}
}
return false;
}
}
+36
View File
@@ -0,0 +1,36 @@
<?php
/**
* Interface für den Zugriff auf Benutzerdaten.
*
* Definiert die Methoden, die jede UserDAO-Implementierung
* bereitstellen muss.
*/
interface UserDAOInterface {
/**
* Sucht einen Benutzer anhand seiner E-Mail-Adresse.
*
* @param string $email E-Mail-Adresse des gesuchten Benutzers
* @return array|null Benutzerdaten als Array oder null
*/
public function findUser($email);
/**
* Fügt einen neuen Benutzer hinzu.
*
* @param string $email E-Mail-Adresse des Benutzers
* @param string $username Benutzername des Benutzers
* @param string $password Passwort des Benutzers
* @return void
*/
public function addUser($email, $username, $password);
/**
* Löscht einen Benutzer anhand seiner E-Mail-Adresse.
*
* @param string $email E-Mail-Adresse des zu löschenden Benutzers
* @return bool true, wenn der Benutzer gelöscht wurde, sonst false
*/
public function deleteUser($email);
}
-107
View File
@@ -1,107 +0,0 @@
<?php
/**
* Prüft, ob der Autor auch der Eigentümer des Beitrags ist.
* @param $author
* @return true
* TODO: Implement this.
*/
function articleAuthorValidator($author)
{
return true;
}
/**
* Prüft, ob der Titel die folgenden Bedingungen erfüllt:
* Buchstaben von a-z; A-Z
* Zahlen von 0-9
* Umlaute äöüÄÖÜß
* Satzeichen .,!?:;()"„“«»_+-
* 5-120 Zeichen
* @param $title
* @return bool
*/
function articleTitleValidator($title)
{
$title = trim($title);
$titlePattern = '/^[a-zA-Z0-9äöüÄÖÜß\s.,!?:;()\'"„“«»_+-]{5,120}$/u';
if (preg_match($titlePattern, $title)) {
return true;
} else {
return false;
}
}
/**
* Prüft, ob der Contenttext 10-7000 Zeichen enthält.
* @param $content
* @return bool
*/
function articleContentValidator($content)
{
$content = trim($content);
$zeichenAnzahl = mb_strlen($content);
if ($zeichenAnzahl <= 7000 && $zeichenAnzahl >= 10) {
return true;
}else{
return false;
}
}
/**
* Prüft, ob die Kategorie eine erlaubt Kategorie ist.
* @param $category
* @return bool
*/
function articleCategoryValidator($category)
{
$allowedCategories = [
'deutsch', 'englisch', 'franzoesisch', 'latein', 'literatur',
'mathe', 'biologie', 'chemie', 'physik', 'informatik', 'astronomie',
'geschichte', 'erdkunde', 'sozialkunde', 'wirtschaft', 'religion',
'ethik', 'philosophie', 'psychologie', 'kunst', 'musik', 'theater',
'technik', 'werken', 'hauswirtschaft', 'sport'
];
if (in_array($category, $allowedCategories, true)) {
return true;
} else {
return false;
}
}
/**
* Prüft, ob die Tags die folgenden Bedingungen erfüllen:
* Buchstaben von a-z; A-Z
* Zahlen von 0-9
* Umlaute äöüÄÖÜß
* Satzeichen -
* 2-50 Zeichen
* @param $tags
* @return bool
*/
function articleTagValidator($tags)
{
if (!isset($tags)) {
$tags = '';
}
$rawTags = explode(',', $tags);
foreach ($rawTags as $rawTag) {
// Leerzeichen am Anfang/Ende des einzelnen Tags entfernen:
$tag = trim($rawTag);
// leere Elemente überspringen:
if ($tag === '') {
continue;
}
// Tag mit Regex prüfen:
$tagPattern = '/^[a-zA-Z0-9äöüÄÖÜß\s-]{2,50}$/u';
if (!preg_match($tagPattern, $tag)) {
return false;
}
}
return true;
}
?>