From fe0f414dc0211a4014581dc03fcfd514ed7ed02d Mon Sep 17 00:00:00 2001
From: Jonas Kohl
Date: Thu, 17 Oct 2024 10:56:01 +0200
Subject: Transition templating to Twig
---
src/application/actions/_default/get.php | 10 +-
src/application/actions/auth/get.php | 9 +-
src/application/actions/deletepost/post.php | 21 +-
src/application/actions/deletetopic/post.php | 7 +-
src/application/actions/newtopic/get.php | 9 +-
src/application/actions/pwreset/get.php | 16 +-
src/application/actions/register/get.php | 9 +-
src/application/actions/search/get.php | 19 +-
src/application/actions/viewtopic/get.php | 37 +--
src/application/actions/viewuser/get.php | 15 +-
src/application/messages/de.msg | 5 +
.../mystic/forum/utils/RequestUtils.php | 13 +-
src/application/templates/bootstrap-3/base.twig | 250 +++++++++++++++
.../bootstrap-3/components/alert_error.twig | 8 +
.../bootstrap-3/components/alert_info.twig | 8 +
.../bootstrap-3/components/alert_success.twig | 8 +
.../templates/bootstrap-3/components/post.twig | 168 ++++++++++
.../bootstrap-3/components/topic_log.twig | 62 ++++
.../templates/bootstrap-3/delete_post.twig | 36 +++
.../templates/bootstrap-3/delete_topic.twig | 32 ++
.../templates/bootstrap-3/error_page.twig | 12 +
.../templates/bootstrap-3/info_page.twig | 12 +
src/application/templates/bootstrap-3/login.twig | 50 +++
.../templates/bootstrap-3/new_password.twig | 42 +++
.../templates/bootstrap-3/new_topic.twig | 58 ++++
.../templates/bootstrap-3/password_reset.twig | 42 +++
.../templates/bootstrap-3/register.twig | 89 ++++++
src/application/templates/bootstrap-3/search.twig | 63 ++++
.../templates/bootstrap-3/view_topic.twig | 353 +++++++++++++++++++++
.../templates/bootstrap-3/view_topics.twig | 25 ++
.../templates/bootstrap-3/view_user.twig | 201 ++++++++++++
src/application/views/alert_error.php | 10 -
src/application/views/alert_info.php | 9 -
src/application/views/alert_success.php | 9 -
src/application/views/form_addpost.php | 53 ----
src/application/views/form_delete_post_confirm.php | 26 --
.../views/form_delete_topic_confirm.php | 24 --
src/application/views/form_login.php | 51 ---
src/application/views/form_new_password.php | 38 ---
src/application/views/form_newtopic.php | 60 ----
src/application/views/form_password_reset.php | 41 ---
src/application/views/form_register.php | 88 -----
src/application/views/form_search.php | 30 --
src/application/views/nav_guest.php | 23 --
src/application/views/nav_logged_in.php | 12 -
src/application/views/template_end.php | 165 ----------
src/application/views/template_navigation.php | 9 -
src/application/views/template_navigation_end.php | 4 -
.../views/template_navigation_start.php | 15 -
src/application/views/template_start.php | 30 --
src/application/views/view_logintoreply.php | 7 -
src/application/views/view_post.php | 150 ---------
src/application/views/view_search_results.php | 35 --
src/application/views/view_topic_end.php | 0
src/application/views/view_topic_locked.php | 4 -
src/application/views/view_topic_start.php | 254 ---------------
src/application/views/view_topiclog.php | 67 ----
src/application/views/view_topics.php | 24 --
src/application/views/view_user.php | 209 ------------
src/composer.json | 3 +-
src/composer.lock | 236 +++++++++++++-
src/index.php | 104 ++++--
62 files changed, 1887 insertions(+), 1592 deletions(-)
create mode 100644 src/application/templates/bootstrap-3/base.twig
create mode 100644 src/application/templates/bootstrap-3/components/alert_error.twig
create mode 100644 src/application/templates/bootstrap-3/components/alert_info.twig
create mode 100644 src/application/templates/bootstrap-3/components/alert_success.twig
create mode 100644 src/application/templates/bootstrap-3/components/post.twig
create mode 100644 src/application/templates/bootstrap-3/components/topic_log.twig
create mode 100644 src/application/templates/bootstrap-3/delete_post.twig
create mode 100644 src/application/templates/bootstrap-3/delete_topic.twig
create mode 100644 src/application/templates/bootstrap-3/error_page.twig
create mode 100644 src/application/templates/bootstrap-3/info_page.twig
create mode 100644 src/application/templates/bootstrap-3/login.twig
create mode 100644 src/application/templates/bootstrap-3/new_password.twig
create mode 100644 src/application/templates/bootstrap-3/new_topic.twig
create mode 100644 src/application/templates/bootstrap-3/password_reset.twig
create mode 100644 src/application/templates/bootstrap-3/register.twig
create mode 100644 src/application/templates/bootstrap-3/search.twig
create mode 100644 src/application/templates/bootstrap-3/view_topic.twig
create mode 100644 src/application/templates/bootstrap-3/view_topics.twig
create mode 100644 src/application/templates/bootstrap-3/view_user.twig
delete mode 100644 src/application/views/alert_error.php
delete mode 100644 src/application/views/alert_info.php
delete mode 100644 src/application/views/alert_success.php
delete mode 100644 src/application/views/form_addpost.php
delete mode 100644 src/application/views/form_delete_post_confirm.php
delete mode 100644 src/application/views/form_delete_topic_confirm.php
delete mode 100644 src/application/views/form_login.php
delete mode 100644 src/application/views/form_new_password.php
delete mode 100644 src/application/views/form_newtopic.php
delete mode 100644 src/application/views/form_password_reset.php
delete mode 100644 src/application/views/form_register.php
delete mode 100644 src/application/views/form_search.php
delete mode 100644 src/application/views/nav_guest.php
delete mode 100644 src/application/views/nav_logged_in.php
delete mode 100644 src/application/views/template_end.php
delete mode 100644 src/application/views/template_navigation.php
delete mode 100644 src/application/views/template_navigation_end.php
delete mode 100644 src/application/views/template_navigation_start.php
delete mode 100644 src/application/views/template_start.php
delete mode 100644 src/application/views/view_logintoreply.php
delete mode 100644 src/application/views/view_post.php
delete mode 100644 src/application/views/view_search_results.php
delete mode 100644 src/application/views/view_topic_end.php
delete mode 100644 src/application/views/view_topic_locked.php
delete mode 100644 src/application/views/view_topic_start.php
delete mode 100644 src/application/views/view_topiclog.php
delete mode 100644 src/application/views/view_topics.php
delete mode 100644 src/application/views/view_user.php
diff --git a/src/application/actions/_default/get.php b/src/application/actions/_default/get.php
index cd0c21c..616589f 100644
--- a/src/application/actions/_default/get.php
+++ b/src/application/actions/_default/get.php
@@ -1,11 +1,7 @@
RequestUtils::getAuthorizedUser($db)]);
-_view("template_navigation_end");
-_view("view_topics", ["topics" => $db->fetchCustom(Topic::class, "ORDER BY creation_date DESC")]);
-_view("template_end", [...getThemeAndLangInfo()]);
+render("view_topics.twig", [
+ "topics" => $db->fetchCustom(Topic::class, "ORDER BY creation_date DESC"),
+]);
diff --git a/src/application/actions/auth/get.php b/src/application/actions/auth/get.php
index 2ff38ff..dfeb837 100644
--- a/src/application/actions/auth/get.php
+++ b/src/application/actions/auth/get.php
@@ -1,10 +1,3 @@
__("Log in")]);
-_view("template_navigation_start");
-_view("template_navigation", ["user" => RequestUtils::getAuthorizedUser($db)]);
-_view("template_navigation_end");
-_view("form_login");
-_view("template_end", [...getThemeAndLangInfo()]);
+render("login.twig");
diff --git a/src/application/actions/deletepost/post.php b/src/application/actions/deletepost/post.php
index b711021..4cd9872 100644
--- a/src/application/actions/deletepost/post.php
+++ b/src/application/actions/deletepost/post.php
@@ -24,11 +24,11 @@ if (!$db->fetch($item) || $item->deleted) {
exit;
}
-$topicAuthor = new User();
-$topicAuthor->id = $item->authorId;
+$postAuthor = new User();
+$postAuthor->id = $item->authorId;
-if (!$db->fetch($topicAuthor))
- $topicAuthor = null;
+if (!$db->fetch($postAuthor))
+ $postAuthor = null;
$topic = new Topic();
$topic->id = $item->topicId;
@@ -36,10 +36,10 @@ $topic->id = $item->topicId;
if (!$db->fetch($topic))
$topic = null;
-$canEdit = ($currentUser->id === $topicAuthor?->id && $topicAuthor?->hasPermission(UserPermissions::DELETE_OWN_POST))
+$canDelete = ($currentUser->id === $postAuthor?->id && $postAuthor?->hasPermission(UserPermissions::DELETE_OWN_POST))
|| ($currentUser->hasPermission(UserPermissions::DELETE_OTHER_POST));
-if (!$canEdit) {
+if (!$canDelete) {
http_response_code(403);
msg_error("You don't have permission to delete this post");
exit;
@@ -75,16 +75,11 @@ if ($confirm !== null) {
header("Location: ?_action=viewtopic&topic=" . urlencode($item->topicId));
} else {
- _view("template_start", ["_title" => __("Delete post")]);
- _view("template_navigation_start");
- _view("template_navigation", ["user" => RequestUtils::getAuthorizedUser($db)]);
- _view("template_navigation_end");
- _view("form_delete_post_confirm", [
+ render("delete_post.twig", [
"post" => $item,
- "postAuthor" => $topicAuthor,
+ "postAuthor" => $postAuthor,
"topicAuthor" => null,
"attachments" => $attachments,
"topic" => $topic,
]);
- _view("template_end", [...getThemeAndLangInfo()]);
}
diff --git a/src/application/actions/deletetopic/post.php b/src/application/actions/deletetopic/post.php
index e67cadf..8683c0f 100644
--- a/src/application/actions/deletetopic/post.php
+++ b/src/application/actions/deletetopic/post.php
@@ -55,13 +55,8 @@ if ($confirm !== null) {
header("Location: .");
} else {
- _view("template_start", ["_title" => "Delete topic"]);
- _view("template_navigation_start");
- _view("template_navigation", ["user" => RequestUtils::getAuthorizedUser($db)]);
- _view("template_navigation_end");
- _view("form_delete_topic_confirm", [
+ render("delete_topic.twig", [
"topic" => $topic,
"topicAuthor" => $topicAuthor,
]);
- _view("template_end", [...getThemeAndLangInfo()]);
}
diff --git a/src/application/actions/newtopic/get.php b/src/application/actions/newtopic/get.php
index 366caac..621cd18 100644
--- a/src/application/actions/newtopic/get.php
+++ b/src/application/actions/newtopic/get.php
@@ -1,10 +1,3 @@
__("New topic")]);
-_view("template_navigation_start");
-_view("template_navigation", ["user" => RequestUtils::getAuthorizedUser($db)]);
-_view("template_navigation_end");
-_view("form_newtopic");
-_view("template_end", [...getThemeAndLangInfo()]);
+render("new_topic.twig");
diff --git a/src/application/actions/pwreset/get.php b/src/application/actions/pwreset/get.php
index c66b28d..35b93f0 100644
--- a/src/application/actions/pwreset/get.php
+++ b/src/application/actions/pwreset/get.php
@@ -11,19 +11,7 @@ if ($token !== null && $signature !== null) {
exit;
}
- _view("template_start", [ "_title" => __("Reset password") ]);
- _view("template_navigation_start");
- _view("template_navigation_end");
- _view("form_new_password", [
- "token" => $token,
- "signature" => $signature,
- ]);
- _view("template_end", [...getThemeAndLangInfo()]);
+ render("new_password.twig");
} else {
- _view("template_start", [ "_title" => __("Reset password") ]);
- _view("template_navigation_start");
- _view("template_navigation", ["user" => null]);
- _view("template_navigation_end");
- _view("form_password_reset");
- _view("template_end", [...getThemeAndLangInfo()]);
+ render("password_reset.twig");
}
diff --git a/src/application/actions/register/get.php b/src/application/actions/register/get.php
index 914ea4e..d1df1b6 100644
--- a/src/application/actions/register/get.php
+++ b/src/application/actions/register/get.php
@@ -1,10 +1,3 @@
__("Register")]);
-_view("template_navigation_start");
-_view("template_navigation", ["user" => RequestUtils::getAuthorizedUser($db)]);
-_view("template_navigation_end");
-_view("form_register");
-_view("template_end", [...getThemeAndLangInfo()]);
+render("register.twig");
diff --git a/src/application/actions/search/get.php b/src/application/actions/search/get.php
index d3de970..bc1bdba 100644
--- a/src/application/actions/search/get.php
+++ b/src/application/actions/search/get.php
@@ -41,25 +41,14 @@ if ($query !== null) {
}
$end_time = microtime(true);
$search_duration = $end_time - $start_time;
-
- _view("template_start", ["_title" => __("Search results for “%query%”", [ "query" => $query ])]);
- _view("template_navigation_start");
- _view("template_navigation", ["user" => RequestUtils::getAuthorizedUser($db)]);
- _view("template_navigation_end");
- _view("form_search", [ "query" => $query ]);
- _view("view_search_results", [
+
+ render("search.twig", [
"posts" => &$posts,
"topics" => &$topicLookup,
"users" => &$userLookup,
"attachments" => &$attachmentLookup,
"search_duration" => $search_duration,
]);
- _view("template_end", [...getThemeAndLangInfo()]);
} else {
- _view("template_start", ["_title" => __("Search")]);
- _view("template_navigation_start");
- _view("template_navigation", ["user" => RequestUtils::getAuthorizedUser($db)]);
- _view("template_navigation_end");
- _view("form_search");
- _view("template_end", [...getThemeAndLangInfo()]);
-}
\ No newline at end of file
+ render("search.twig");
+}
diff --git a/src/application/actions/viewtopic/get.php b/src/application/actions/viewtopic/get.php
index 45dc824..636d791 100644
--- a/src/application/actions/viewtopic/get.php
+++ b/src/application/actions/viewtopic/get.php
@@ -6,7 +6,6 @@ use mystic\forum\orm\Attachment;
use mystic\forum\orm\Post;
use mystic\forum\orm\TopicLogMessage;
use mystic\forum\orm\User;
-use mystic\forum\utils\RequestUtils;
$posts = $db->fetchCustom(Post::class, 'WHERE topic_id = $1 ORDER BY post_date', [ $topicId ]);
/** @var TopicLogMessage[] $logMessages */
@@ -25,13 +24,7 @@ if ($topic->createdBy !== null) {
$allItems = [...$posts, ...$logMessages];
usort($allItems, fn(Post|TopicLogMessage $a, Post|TopicLogMessage $b): int => $a->postDate <=> $b->postDate);
-_view("template_start", ["_title" => $topic->title]);
-_view("template_navigation_start");
-_view("template_navigation", ["user" => RequestUtils::getAuthorizedUser($db)]);
-_view("template_navigation_end");
-_view("view_topic_start", ["topic" => $topic, "topicAuthor" => $topicAuthor]);
-
-foreach ($allItems as $item) {
+$allItems = array_map(function(Post|TopicLogMessage $item) use (&$db, &$topicAuthor, &$topic): array {
/** @var ?User $postAuthor */
$postAuthor = null;
if ($item->authorId !== null && !isset($userCache[$item->authorId])) {
@@ -46,31 +39,27 @@ foreach ($allItems as $item) {
if ($item instanceof Post) {
$attachments = $db->fetchCustom(Attachment::class, 'WHERE post_id = $1', [ $item->id ]);
- _view("view_post", [
+ return [
+ "type" => "post",
"post" => $item,
"postAuthor" => $postAuthor,
"topicAuthor" => $topicAuthor,
"attachments" => $attachments,
"topic" => $topic,
- ]);
+ ];
} else {
- _view("view_topiclog", [
+ return [
+ "type" => "logMessage",
"logMessage" => $item,
"postAuthor" => $postAuthor,
"topicAuthor" => $topicAuthor,
"topic" => $topic,
- ]);
+ ];
}
-}
-
-_view("view_topic_end");
-
-if ($topic->isLocked) {
- _view("view_topic_locked");
-} elseif ($currentUser) {
- _view("form_addpost");
-} else {
- _view("view_logintoreply");
-}
+}, $allItems);
-_view("template_end", [...getThemeAndLangInfo()]);
+render("view_topic.twig", [
+ "topic" => $topic,
+ "topicAuthor" => $topicAuthor,
+ "allItems" => &$allItems,
+]);
diff --git a/src/application/actions/viewuser/get.php b/src/application/actions/viewuser/get.php
index c98df16..e6dac43 100644
--- a/src/application/actions/viewuser/get.php
+++ b/src/application/actions/viewuser/get.php
@@ -17,18 +17,15 @@ foreach ($posts as $item) {
$attachs = $db->fetchCustom(Attachment::class, 'WHERE post_id = $1', [ $item->id ]);
$attachments[$item->id] = $attachs;
}
-_view("template_start", ["_title" => $user->displayName]);
-_view("template_navigation_start");
-_view("template_navigation", [
- "user" => $currentUser,
- "isViewingOwnProfile" => $isOwnProfile,
-]);
-_view("template_navigation_end");
-_view("view_user", [
+
+$dateJoined = DateTime::createFromImmutable($user->created);
+$dateJoined->setTime(0, 0, 0, 0);
+
+render("view_user.twig", [
"user" => $user,
"posts" => $posts,
"topics" => $topics,
"attachments" => $attachments,
"lastNameChangeTooRecent" => $lastNameChangeTooRecent,
+ "dateJoined" => $dateJoined,
]);
-_view("template_end", [...getThemeAndLangInfo()]);
diff --git a/src/application/messages/de.msg b/src/application/messages/de.msg
index d77f2eb..b6fb3d6 100644
--- a/src/application/messages/de.msg
+++ b/src/application/messages/de.msg
@@ -525,3 +525,8 @@ metadata({
: "Spoiler"
= "Spoiler"
+: "View profile"
+= "Profil ansehen"
+
+: "Log out"
+= "Abmelden"
diff --git a/src/application/mystic/forum/utils/RequestUtils.php b/src/application/mystic/forum/utils/RequestUtils.php
index 5c6a485..11253aa 100644
--- a/src/application/mystic/forum/utils/RequestUtils.php
+++ b/src/application/mystic/forum/utils/RequestUtils.php
@@ -40,9 +40,10 @@ final class RequestUtils {
return $fieldValue;
}
- public static function storeForm(): void {
+ public static function storeForm(string $formId): void {
$_SESSION["lastForm"] = $_POST ?? [];
$_SESSION["lastForm_uri"] = $_SERVER["REQUEST_URI"];
+ $_SESSION["lastForm_id"] = $formId;
}
public static function setFormErrorDestination(?string $dest): ?string {
@@ -55,7 +56,7 @@ final class RequestUtils {
$next ??= self::$formErrorDestination ?? $_SERVER["REQUEST_URI"];
$_SESSION["formError/$formId"] = $message;
// store last form submission
- self::storeForm();
+ self::storeForm($formId);
header("Location: $next");
exit;
}
@@ -66,14 +67,20 @@ final class RequestUtils {
return $err;
}
- public static function getLastForm(string &$lastFormUri): ?array {
+ public static function getLastForm_legacy(string &$lastFormUri): ?array {
$lastFormUri = $_SESSION["lastForm_uri"] ?? "";
return $_SESSION["lastForm"] ?? null;
}
+ public static function getLastForm(string &$lastFormId): ?array {
+ $lastFormId = $_SESSION["lastForm_id"] ?? "";
+ return $_SESSION["lastForm"] ?? null;
+ }
+
public static function clearLastForm(): void {
unset($_SESSION["lastForm"]);
unset($_SESSION["lastForm_uri"]);
+ unset($_SESSION["lastForm_id"]);
}
public static function getAuthorizedUser(Database &$db): ?User {
diff --git a/src/application/templates/bootstrap-3/base.twig b/src/application/templates/bootstrap-3/base.twig
new file mode 100644
index 0000000..5e003b9
--- /dev/null
+++ b/src/application/templates/bootstrap-3/base.twig
@@ -0,0 +1,250 @@
+{%- if title -%}
+ {%- set title = title ~ " | " -%}
+{%- endif -%}
+{%- set title = title ~ (g.env.MYSTIC_FORUM_TITLE|default("Forum")) -%}
+{%- set nextParam = "" -%}
+{%- if g.globals.action in ["login", "register"] -%}
+ {%- set nextParam = g.get.next|default("") -%}
+{%- else -%}
+ {%- set nextParam = g.server.REQUEST_URI -%}
+{%- endif -%}
+
+
+
+
+
+
+
+
+
+
+ {{ title }}
+
+
+
+
+
+
+ {% block head_after %}{% endblock %}
+
+
+
+{% block nav %}
+
+
+
+
+ {% block navbar %}
+ {% if currentUser %}
+
+ {% else %}
+
+ {% endif %}
+ {% endblock %}
+
+
+
+{% endblock %}
+
+{% block main %}
+
+ {% block content %}{% endblock %}
+
+{% endblock %}
+
+{% block footer %}
+
+{% endblock %}
+
+{% block scripts %}
+
+
+
+{% endblock %}
+
+
+
diff --git a/src/application/templates/bootstrap-3/components/alert_error.twig b/src/application/templates/bootstrap-3/components/alert_error.twig
new file mode 100644
index 0000000..f3f759b
--- /dev/null
+++ b/src/application/templates/bootstrap-3/components/alert_error.twig
@@ -0,0 +1,8 @@
+
+
+ {% if message starts with "?!HTML::" %}
+ {{ message|slice(8)|raw }}
+ {% else %}
+ {{ message }}
+ {% endif %}
+
diff --git a/src/application/templates/bootstrap-3/components/alert_info.twig b/src/application/templates/bootstrap-3/components/alert_info.twig
new file mode 100644
index 0000000..099d091
--- /dev/null
+++ b/src/application/templates/bootstrap-3/components/alert_info.twig
@@ -0,0 +1,8 @@
+
+
+ {% if message starts with "?!HTML::" %}
+ {{ message|slice(8)|raw }}
+ {% else %}
+ {{ message }}
+ {% endif %}
+
diff --git a/src/application/templates/bootstrap-3/components/alert_success.twig b/src/application/templates/bootstrap-3/components/alert_success.twig
new file mode 100644
index 0000000..1c8f403
--- /dev/null
+++ b/src/application/templates/bootstrap-3/components/alert_success.twig
@@ -0,0 +1,8 @@
+
+
+ {% if message starts with "?!HTML::" %}
+ {{ message|slice(8)|raw }}
+ {% else %}
+ {{ message }}
+ {% endif %}
+
diff --git a/src/application/templates/bootstrap-3/components/post.twig b/src/application/templates/bootstrap-3/components/post.twig
new file mode 100644
index 0000000..ac969c0
--- /dev/null
+++ b/src/application/templates/bootstrap-3/components/post.twig
@@ -0,0 +1,168 @@
+{%- set fileAttachments = attachments|filter(a => not (a.mimeType starts with "image/" or a.mimeType starts with "video/")) -%}
+{%- set imageAttachments = attachments|filter(a => a.mimeType starts with "image/" or a.mimeType starts with "video/") -%}
+
+{%- set canReply =
+ not post.deleted
+ and not topic.isLocked
+ and currentUser is not null
+ and currentUser.hasPermission(permission("CREATE_OWN_POST"))
+-%}
+
+{%- set canEdit =
+ not post.deleted
+ and not topic.isLocked
+ and currentUser is not null
+ and (
+ (
+ postAuthor is not null
+ and postAuthor.hasPermission(permission("EDIT_OWN_POST"))
+ )
+ or currentUser.hasPermission(permission("EDIT_OTHER_POST"))
+ ) -%}
+
+{%- set canDelete =
+ not post.deleted
+ and currentUser is not null
+ and (
+ (
+ postAuthor is not null
+ and postAuthor.id == currentUser.id
+ and postAuthor.hasPermission(permission("DELETE_OWN_POST"))
+ )
+ or currentUser.hasPermission(permission("DELETE_OTHER_POST"))
+ ) -%}
+
+{%- set canViewAttachments = currentUser is not null -%}
+
+{%- set your_are_the_author =
+ currentUser is not null
+ and postAuthor is not null
+ and currentUser.id == postAuthor.id
+-%}
+
+{%- set is_op =
+ topicAuthor is not null
+ and postAuthor is not null
+ and postAuthor.id == topicAuthor.id
+-%}
+
+{% if post.deleted %}
+
+
+
+
+
+ {{ __("This post has been deleted") }}
+
+
+
+{% else %}
+
+ {% if not hide_pfp %}
+
+ {% endif %}
+
+
+
+
+ {% if not hide_actions %}
+
+
{{ __("Permalink") }}
+ {% if canReply %}
+
{{ __("Reply to post") }}
+ {% endif %}
+ {% if canEdit %}
+
{{ __("Edit post") }}
+ {% endif %}
+ {% if canDelete %}
+
+ {% endif %}
+
+ {% endif %}
+ {% if postAuthor %}
+ {% if hide_actions %}
+ {{ postAuthor.displayName }}
+ {% else %}
+
{{ postAuthor.displayName }}
+ {% if is_op %}
+
+ {% endif %}
+ {% endif %}
+ {% if your_are_the_author %}
+
{{ __("You") }}
+ {% endif %}
+ {% else %}
+
{{ __("(deleted)") }}
+ {% endif %}
+
+
{{ post.postDate.format("c") }}
+ {% if post.edited %}
+
{{ __("(edited)") }}
+ {% endif %}
+
+
+
{{ renderPost(post.content) }}
+ {% if imageAttachments|length > 0 %}
+
+ {% for attachment in imageAttachments %}
+ {% if hide_actions %}
+
+
+
+ {% else %}
+
+
+ {% if not canViewAttachments %}
+
+ {% elseif attachment.mimeType starts with "video/" %}
+
+ {% endif %}
+
+ {% endif %}
+ {% endfor %}
+
+ {% endif %}
+
+ {% if fileAttachments|length > 0 %}
+
+ {% endif %}
+
+
+
+{% endif %}
diff --git a/src/application/templates/bootstrap-3/components/topic_log.twig b/src/application/templates/bootstrap-3/components/topic_log.twig
new file mode 100644
index 0000000..9364cd1
--- /dev/null
+++ b/src/application/templates/bootstrap-3/components/topic_log.twig
@@ -0,0 +1,62 @@
+{%- set user = "" -%}
+{%- if postAuthor is null -%}
+ {%- set user = __("deleted")|e("html") -%}
+{%- else -%}
+ {%- set user =
+ ''
+ ~ postAuthor.displayName|e("html")
+ ~ ' '
+ -%}
+{%- endif -%}
+
+
+
+
+ {% if logMessage.type == constant("mystic\\forum\\orm\\TopicLogMessage::LOCKED") %}
+
+
+ {{ __("%user% locked this topic", {
+ "user": user,
+ }) }}
+
+ {{ logMessage.postDate.format("c") }}
+
+ {% elseif logMessage.type == constant("mystic\\forum\\orm\\TopicLogMessage::UNLOCKED") %}
+
+
+ {{ __("%user% unlocked this topic", {
+ "user": user,
+ }) }}
+
+ {{ logMessage.postDate.format("c") }}
+
+ {% elseif logMessage.type == constant("mystic\\forum\\orm\\TopicLogMessage::TITLE_CHANGED") %}
+
+
+ {{ __("%user% changed the title of this topic from %old_title% to %new_title%", {
+ "user": user,
+ "old_title": '' ~ logMessage.params.old_value|default(__("unknown"))|e("html") ~ ' ',
+ "new_title": '' ~ logMessage.params.new_value|default(__("unknown"))|e("html") ~ ' ',
+ }) }}
+
+ {{ logMessage.postDate.format("c") }}
+
+ {% else %}
+ {{ __("unknown") }}
+ {% endif %}
+
+
diff --git a/src/application/templates/bootstrap-3/delete_post.twig b/src/application/templates/bootstrap-3/delete_post.twig
new file mode 100644
index 0000000..90eaf09
--- /dev/null
+++ b/src/application/templates/bootstrap-3/delete_post.twig
@@ -0,0 +1,36 @@
+{% set title = __("Delete post") %}
+
+{% extends "base.twig" %}
+
+{% block content %}
+
+
+
+
{{ __("Do you want to delete this post?") }}
+
+
+ {{ __("Are you sure you want to delete the following post:") }}
+ {% include "components/post.twig" with {
+ post: ctx.post,
+ postAuthor: ctx.postAuthor,
+ attachments: ctx.attachments,
+ hide_actions: true,
+ } %}
+
+
+
+
+{% endblock %}
diff --git a/src/application/templates/bootstrap-3/delete_topic.twig b/src/application/templates/bootstrap-3/delete_topic.twig
new file mode 100644
index 0000000..3107c89
--- /dev/null
+++ b/src/application/templates/bootstrap-3/delete_topic.twig
@@ -0,0 +1,32 @@
+{% set title = __("Delete topic") %}
+
+{% extends "base.twig" %}
+
+{% block content %}
+
+
+
+
{{ __("Do you want to delete this topic?") }}
+
+
+ {{ __("Are you sure you want to delete the topic %topic% including all posts and attachments ?", {
+ "topic": ctx.topic.title|e("html"),
+ }) }}
+
+
+
+
+{% endblock %}
diff --git a/src/application/templates/bootstrap-3/error_page.twig b/src/application/templates/bootstrap-3/error_page.twig
new file mode 100644
index 0000000..dde4057
--- /dev/null
+++ b/src/application/templates/bootstrap-3/error_page.twig
@@ -0,0 +1,12 @@
+{% set title = __("Error") %}
+{% extends "base.twig" %}
+
+{% block navbar %}
+ {% if not ctx.skipLoginCheck %}
+ {{ parent() }}
+ {% endif %}
+{% endblock %}
+
+{% block content %}
+ {% include "components/alert_error.twig" with { message: ctx.message } %}
+{% endblock %}
diff --git a/src/application/templates/bootstrap-3/info_page.twig b/src/application/templates/bootstrap-3/info_page.twig
new file mode 100644
index 0000000..e243b36
--- /dev/null
+++ b/src/application/templates/bootstrap-3/info_page.twig
@@ -0,0 +1,12 @@
+{% set title = __("Information") %}
+{% extends "base.twig" %}
+
+{% block navbar %}
+ {% if not ctx.skipLoginCheck %}
+ {{ parent() }}
+ {% endif %}
+{% endblock %}
+
+{% block content %}
+ {% include "components/alert_info.twig" with { message: ctx.message } %}
+{% endblock %}
diff --git a/src/application/templates/bootstrap-3/login.twig b/src/application/templates/bootstrap-3/login.twig
new file mode 100644
index 0000000..63b9867
--- /dev/null
+++ b/src/application/templates/bootstrap-3/login.twig
@@ -0,0 +1,50 @@
+{% set title = __("Log in") %}
+{% set formId = "login" %}
+{% set formError = getAndClearFormError(formId) %}
+
+{% extends "base.twig" %}
+
+{% block content %}
+
+
+
+
+
+
+ {% if formError %}
+ {% include "components/alert_error.twig" with { message: formError } %}
+ {% endif %}
+
+
+
+
+
+{% endblock %}
diff --git a/src/application/templates/bootstrap-3/new_password.twig b/src/application/templates/bootstrap-3/new_password.twig
new file mode 100644
index 0000000..55a4b79
--- /dev/null
+++ b/src/application/templates/bootstrap-3/new_password.twig
@@ -0,0 +1,42 @@
+{% set title = __("Reset password") %}
+{% set formId = "pwnew" %}
+{% set formError = getAndClearFormError(formId) %}
+
+{% extends "base.twig" %}
+
+{% block content %}
+
+
+
+
+
+
+ {% if formError %}
+ {% include "components/alert_error.twig" with { message: formError } %}
+ {% endif %}
+
+
+
+
+
+{% endblock %}
diff --git a/src/application/templates/bootstrap-3/new_topic.twig b/src/application/templates/bootstrap-3/new_topic.twig
new file mode 100644
index 0000000..74be156
--- /dev/null
+++ b/src/application/templates/bootstrap-3/new_topic.twig
@@ -0,0 +1,58 @@
+{% set title = __("New topic") %}
+{% set formId = "newtopic" %}
+{% set formError = getAndClearFormError(formId) %}
+
+{% extends "base.twig" %}
+
+{% block content %}
+
+
+
+{% if formError %}
+ {% include "components/alert_error.twig" with { message: formError } %}
+{% endif %}
+
+
+{% endblock %}
diff --git a/src/application/templates/bootstrap-3/password_reset.twig b/src/application/templates/bootstrap-3/password_reset.twig
new file mode 100644
index 0000000..f633106
--- /dev/null
+++ b/src/application/templates/bootstrap-3/password_reset.twig
@@ -0,0 +1,42 @@
+{% set title = __("Reset password") %}
+{% set formId = "pwreset" %}
+{% set formError = getAndClearFormError(formId) %}
+
+{% extends "base.twig" %}
+
+{% block content %}
+
+
+
+
+
+
+ {% if formError %}
+ {% include "components/alert_error.twig" with { message: formError } %}
+ {% endif %}
+
+
+
+
+ {{ __("Email address:") }}
+
+
+
+
+ {{ __("Reset password") }}
+
+
+
+
+
+
+
+
+{% endblock %}
diff --git a/src/application/templates/bootstrap-3/register.twig b/src/application/templates/bootstrap-3/register.twig
new file mode 100644
index 0000000..1e4cd92
--- /dev/null
+++ b/src/application/templates/bootstrap-3/register.twig
@@ -0,0 +1,89 @@
+{% set title = __("Register") %}
+{% set formId = "register" %}
+{% set formError = getAndClearFormError(formId) %}
+
+{% extends "base.twig" %}
+
+{% block content %}
+
+
+
+
+
+
+
+
+
+
+
+{% endblock %}
diff --git a/src/application/templates/bootstrap-3/search.twig b/src/application/templates/bootstrap-3/search.twig
new file mode 100644
index 0000000..c8f6315
--- /dev/null
+++ b/src/application/templates/bootstrap-3/search.twig
@@ -0,0 +1,63 @@
+{% set title = __("Search") %}
+{% set formId = "search" %}
+{% set formError = getAndClearFormError(formId) %}
+
+{% extends "base.twig" %}
+
+{% block content %}
+
+
+
+{% if formError %}
+ {% include "components/alert_error.twig" with { message: formError } %}
+{% endif %}
+
+
+
+
+
+
+
+{% if g.get.query is defined and g.get.query is not null and g.get.query != "" %}
+ {% if ctx.posts|length > 0 %}
+ {{ __("%result_count% result(s) in %search_duration% second(s)", {
+ "result_count": ctx.posts|length,
+ "search_duration": ctx.search_duration|number_format(2, __(".", context: "Number formatting"), __(",", context: "Number formatting")),
+ }) }}
+
+ {% else %}
+
+
+ {{ __("No results for this search") }}
+
+ {% endif %}
+{% endif %}
+
+{% endblock %}
diff --git a/src/application/templates/bootstrap-3/view_topic.twig b/src/application/templates/bootstrap-3/view_topic.twig
new file mode 100644
index 0000000..008c336
--- /dev/null
+++ b/src/application/templates/bootstrap-3/view_topic.twig
@@ -0,0 +1,353 @@
+{% set canReply =
+ not ctx.topic.isLocked
+ and currentUser is not null
+ and currentUser.hasPermission(permission("CREATE_OWN_POST")) %}
+
+{% set canEdit =
+ currentUser is not null and (
+ (
+ ctx.topicAuthor is not null
+ and currentUser.id == ctx.topicAuthor.id
+ and ctx.topicAuthor.hasPermission(permission("EDIT_OWN_TOPIC"))
+ )
+ or currentUser.hasPermission(permission("EDIT_OTHER_TOPIC"))
+ ) %}
+
+{% set canDelete =
+ currentUser is not null and (
+ (
+ ctx.topicAuthor is not null
+ and currentUser.id == ctx.topicAuthor.id
+ and ctx.topicAuthor.hasPermission(permission("DELETE_OWN_TOPIC"))
+ )
+ or currentUser.hasPermission(permission("DELETE_OTHER_TOPIC"))
+ ) %}
+
+{% set title = ctx.topic.title %}
+{% extends "base.twig" %}
+
+{% block content %}
+
+{% if canEdit %}
+
+
+
+
+
+
+
{{ __("Message:") }}
+
+
+
+
+
+
+{% endif %}
+{% if currentUser is null %}
+
+
+
+
+
+ {{ __("You must be logged in to view attachments") }}
+
+
+
+
+
+
+{% else %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% endif %}
+
+{% set formError = getAndClearFormError("updateTopic") %}
+{% if formError %}
+ {% include "components/alert_error.twig" with { message: formError } %}
+{% endif %}
+{% set formError = getAndClearFormError("lockTopic") %}
+{% if formError %}
+ {% include "components/alert_error.twig" with { message: formError } %}
+{% endif %}
+{% set formError = null %}
+
+
+
+
+{% for item in ctx.allItems %}
+ {% if item.type == "post" %}
+ {% include "components/post.twig" with {
+ post: item.post,
+ postAuthor: item.postAuthor,
+ topic: item.topic,
+ attachments: item.attachments,
+ hide_actions: false,
+ hide_pfp: false,
+ } %}
+ {% elseif item.type == "logMessage" %}
+ {% include "components/topic_log.twig" with {
+ type: item.type,
+ logMessage: item.logMessage,
+ postAuthor: item.postAuthor,
+ topicAuthor: item.topicAuthor,
+ topic: item.topic,
+ hide_actions: false,
+ hide_pfp: false,
+ } %}
+ {% endif %}
+{% endfor %}
+
+{% if ctx.topic.isLocked %}
+
+
+ {{ __("This topic has been locked") }}
+
+{% elseif currentUser is not null %}
+ {% set formId = "addpost" %}
+
+ {% set formError = getAndClearFormError(formId) %}
+ {% if formError %}
+ {% include "components/alert_error.twig" with { message: formError } %}
+ {% endif %}
+
+
+
+
+ {{ __("Attachments: (max. %max_attachment_count% files, max. %max_attachment_size% MiB each) ", {
+ "max_attachment_count": constant("MAX_ATTACHMENT_COUNT"),
+ "max_attachment_size": constant("MAX_ATTACHMENT_SIZE") // (2**20),
+ }) }}
+
+
+ {{ __("Post reply") }}
+
+{% else %}
+
+
{{ __("Log in to reply to this topic") }}
+
+
+ {{ __("Log in") }}
+
+
+{% endif %}
+
+
+{% endblock %}
diff --git a/src/application/templates/bootstrap-3/view_topics.twig b/src/application/templates/bootstrap-3/view_topics.twig
new file mode 100644
index 0000000..899ebe7
--- /dev/null
+++ b/src/application/templates/bootstrap-3/view_topics.twig
@@ -0,0 +1,25 @@
+{% extends "base.twig" %}
+
+{% block content %}
+
+{% if currentUser.hasPermission(permission("CREATE_OWN_TOPIC")) %}
+
+ {{ __("New topic") }}
+
+{% endif %}
+
+
+
+{% endblock %}
diff --git a/src/application/templates/bootstrap-3/view_user.twig b/src/application/templates/bootstrap-3/view_user.twig
new file mode 100644
index 0000000..b4c936c
--- /dev/null
+++ b/src/application/templates/bootstrap-3/view_user.twig
@@ -0,0 +1,201 @@
+{% set canEdit =
+ currentUser is not null
+ and (
+ (
+ ctx.user.id == currentUser.id
+ and currentUser.hasPermission(permission("EDIT_OWN_USER"))
+ )
+ or currentUser.hasPermission(permission("EDIT_OTHER_USER"))
+ ) %}
+
+{% set isOwnProfile =
+ currentUser is not null
+ and currentUser.id == ctx.user.id %}
+
+{% set sUserPossessive = isOwnProfile ? "Your Posts" : "%display_name%'s posts" %}
+
+{% set emailPending = isOwnProfile and ctx.user.pendingEmail is not null %}
+
+{% set title = ctx.user.displayName %}
+
+{% extends "base.twig" %}
+
+{% block content %}
+
+
+
+{% if canEdit %}
+
+
+{% endif %}
+
+
{{ __(sUserPossessive, {
+ "display_name": ctx.user.displayName|e("html"),
+}) }}
+
+{% if ctx.posts|length > 0 %}
+
+
+
+
+ {{ __("Show all posts") }}
+
+
+{% else %}
+
+
+ {{ __("This user has not posted anything yet") }}
+
+{% endif %}
+
+{% if canEdit %}
+
+
+
+
+{% endif %}
+
+
+
+{% endblock %}
diff --git a/src/application/views/alert_error.php b/src/application/views/alert_error.php
deleted file mode 100644
index e3b48ba..0000000
--- a/src/application/views/alert_error.php
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-= $message; ?>
-
diff --git a/src/application/views/alert_info.php b/src/application/views/alert_info.php
deleted file mode 100644
index 7bf2e7b..0000000
--- a/src/application/views/alert_info.php
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-= $message; ?>
-
diff --git a/src/application/views/alert_success.php b/src/application/views/alert_success.php
deleted file mode 100644
index de3e023..0000000
--- a/src/application/views/alert_success.php
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-= $message; ?>
-
diff --git a/src/application/views/form_addpost.php b/src/application/views/form_addpost.php
deleted file mode 100644
index b2fb2f2..0000000
--- a/src/application/views/form_addpost.php
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
- $_formError]);
-}
-?>
-#form" method="post" enctype="multipart/form-data">
-
-
-
- = __("Attachments: (max. %max_attachment_count% files, max. %max_attachment_size% MiB each) ", [
- "max_attachment_count" => strval(MAX_ATTACHMENT_COUNT),
- "max_attachment_size" => strval(MAX_ATTACHMENT_SIZE >> 20)
- ]) ?>
-
-
-= __("Post reply") ?>
-
diff --git a/src/application/views/form_delete_post_confirm.php b/src/application/views/form_delete_post_confirm.php
deleted file mode 100644
index e127235..0000000
--- a/src/application/views/form_delete_post_confirm.php
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
= __("Do you want to delete this post?") ?>
-
-
- = __("Are you sure you want to delete the following post:") ?>
- true
- ]) ?>
-
-
-
diff --git a/src/application/views/form_delete_topic_confirm.php b/src/application/views/form_delete_topic_confirm.php
deleted file mode 100644
index 4f9deec..0000000
--- a/src/application/views/form_delete_topic_confirm.php
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
= __("Do you want to delete this topic?") ?>
-
-
- = __("Are you sure you want to delete the topic %topic% including all posts and attachments ?", [
- "topic" => htmlentities($topic->title),
- ]) ?>
-
-
-
diff --git a/src/application/views/form_login.php b/src/application/views/form_login.php
deleted file mode 100644
index 5fa79ad..0000000
--- a/src/application/views/form_login.php
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-
-
-
diff --git a/src/application/views/form_new_password.php b/src/application/views/form_new_password.php
deleted file mode 100644
index 7431bd5..0000000
--- a/src/application/views/form_new_password.php
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-
-
-
diff --git a/src/application/views/form_newtopic.php b/src/application/views/form_newtopic.php
deleted file mode 100644
index e7050c7..0000000
--- a/src/application/views/form_newtopic.php
+++ /dev/null
@@ -1,60 +0,0 @@
-
-
- $_formError]);
-}
-?>
-#form" method="post" enctype="multipart/form-data">
-
-
- = __("Topic title:") ?>
- " required autofocus>
-
-
-
- = __("Attachments: (max. %max_attachment_count% files, max. %max_attachment_size% MiB each) ", [
- "max_attachment_count" => strval(MAX_ATTACHMENT_COUNT),
- "max_attachment_size" => strval(MAX_ATTACHMENT_SIZE >> 20)
- ]) ?>
-
-
-= __("Create topic") ?>
-
diff --git a/src/application/views/form_password_reset.php b/src/application/views/form_password_reset.php
deleted file mode 100644
index 57d8ed2..0000000
--- a/src/application/views/form_password_reset.php
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
- $_formError]);
-}
-?>
-
" method="post">
-
-
- = __("Email address:") ?>
- " required autofocus>
-
-
-
- = __("Reset password") ?>
-
-
-
-
-
-
diff --git a/src/application/views/form_register.php b/src/application/views/form_register.php
deleted file mode 100644
index 54da2c4..0000000
--- a/src/application/views/form_register.php
+++ /dev/null
@@ -1,88 +0,0 @@
-
-
-
-
-
-
-
diff --git a/src/application/views/form_search.php b/src/application/views/form_search.php
deleted file mode 100644
index 394a0e7..0000000
--- a/src/application/views/form_search.php
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
- $_formError]);
-}
-?>
-
-
-
-
-
diff --git a/src/application/views/nav_guest.php b/src/application/views/nav_guest.php
deleted file mode 100644
index 95c236e..0000000
--- a/src/application/views/nav_guest.php
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
\ No newline at end of file
diff --git a/src/application/views/nav_logged_in.php b/src/application/views/nav_logged_in.php
deleted file mode 100644
index 8dbb325..0000000
--- a/src/application/views/nav_logged_in.php
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
diff --git a/src/application/views/template_end.php b/src/application/views/template_end.php
deleted file mode 100644
index b162def..0000000
--- a/src/application/views/template_end.php
+++ /dev/null
@@ -1,165 +0,0 @@
-
-
-
-
-
-
-
-