Skip to content

Commit 2a9b88f

Browse files
committed
feat: deleting final post should delete the thread
1 parent 262fb48 commit 2a9b88f

File tree

9 files changed

+290
-17
lines changed

9 files changed

+290
-17
lines changed

client/css/Forum.css

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@
1313
border: 1px solid var(--color-grey);
1414
}
1515

16-
.forum__category {
1716

18-
}
1917

2018
/**
2119
* Admin features at the bottom of the page
@@ -45,7 +43,6 @@
4543
margin-bottom: 4px;
4644
}
4745

48-
4946
.forum__admin-features .forum__admin-features-title {
5047
font-size: 14px;
5148
font-weight: bold;
@@ -54,6 +51,22 @@
5451
color: var(--color-dark);
5552
}
5653

54+
.forum__delete-thread-link {
55+
display: inline-block;
56+
margin-top: 12px;
57+
padding: 6px 12px;
58+
font-size: 12px;
59+
color: #b91c1c;
60+
border: 1px solid #b91c1c;
61+
border-radius: 4px;
62+
text-decoration: none;
63+
cursor: pointer;
64+
}
65+
66+
.forum__delete-thread-link:hover {
67+
background-color: #b91c1c;
68+
color: #fff;
69+
}
5770

5871
.forum__subscribe-link--hidden {
5972
display: none;
@@ -83,21 +96,27 @@
8396
text-decoration: none;
8497
}
8598

86-
8799
/**
88100
* Preview content
89101
*/
90102
.forum__previous-posts {
91103
margin-bottom: 32px;
92104
margin-top: 32px;
93105
padding: 20px;
94-
border: 1px dashed var(--color-grey, '#d1d2d6');
106+
border: 1px dashed var(--color-grey, "#d1d2d6");
95107
border-radius: 12px;
96108
}
97-
.forum__previous-posts .forum__post {
98-
padding-left: 12px;
99-
}
109+
.forum__previous-posts .forum__post {
110+
padding-left: 12px;
111+
}
100112

113+
.forum__previous-posts h2 {
114+
margin-top: 0;
115+
margin-bottom: 12px;
116+
font-size: 18px;
117+
line-height: 24px;
118+
color: var(--color-dark);
119+
}
101120

102121
/**
103122
* Post list
@@ -114,7 +133,7 @@
114133
}
115134

116135
.forum__features tbody tr:nth-child(even) {
117-
background-color:#f4f4f4;
136+
background-color: #f4f4f4;
118137
}
119138

120139
/**
@@ -160,5 +179,3 @@
160179
display: flex;
161180
justify-content: space-between;
162181
}
163-
164-

client/javascript/Forum.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,25 @@
202202
});
203203
});
204204

205+
/**
206+
* Delete Thread link.
207+
*
208+
* Confirm before deleting the entire thread and all its posts.
209+
* Uses native navigation (like ban/ghost) so the server redirect works cleanly.
210+
*/
211+
var deleteThreadLinks = document.querySelectorAll("a.deleteThreadLink");
212+
deleteThreadLinks.forEach(function (link) {
213+
link.addEventListener("click", function (e) {
214+
if (
215+
!confirm(
216+
"Are you sure you want to delete this entire thread?\nAll posts in this thread will be permanently removed."
217+
)
218+
) {
219+
e.preventDefault();
220+
}
221+
});
222+
});
223+
205224
/**
206225
* Ban / Ghost member confirmation
207226
*/

src/Form/PostMessageForm.php

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,13 @@ class PostMessageForm extends Form
2323
{
2424
protected ?Post $post = null;
2525

26+
protected ?ForumThread $thread = null;
27+
2628
public function __construct($controller, $name)
2729
{
2830
$fields = FieldList::create([
2931
TextField::create("Title", _t('Forum.FORUMTHREADTITLE', 'Title')),
30-
TextareaField::create("Content", _t('Forum.FORUMREPLYCONTENT', 'Content')),
32+
TextareaField::create("Content", _t('Forum.FORUMREPLYCONTENT', 'Message')),
3133
HiddenField::create('ThreadID', 'ThreadID'),
3234
HiddenField::create('ID', 'ID'),
3335
CheckboxField::create(
@@ -50,7 +52,21 @@ public function __construct($controller, $name)
5052
}
5153

5254

53-
public function setPost(Post $post)
55+
public function setThread(?ForumThread $thread = null)
56+
{
57+
$this->loadDataFrom([
58+
'ThreadID' => $thread ? $thread->ID : null,
59+
'Title' => $thread ? $thread->Title : null,
60+
]);
61+
62+
$this->thread = $thread;
63+
$this->fields->makeFieldReadonly('Title');
64+
65+
return $this;
66+
}
67+
68+
69+
public function setPost(?Post $post = null)
5470
{
5571
$this->loadDataFrom($post);
5672

src/PageTypes/Forum.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
use SilverStripe\Forms\HeaderField;
2424
use SilverStripe\Model\List\ArrayList;
2525
use SilverStripe\Model\List\PaginatedList;
26-
use SilverStripe\ORM\DB;
2726
use SilverStripe\Security\Group;
2827
use SilverStripe\Security\Member;
2928
use SilverStripe\Security\Permission;

src/PageTypes/ForumController.php

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use FullscreenInteractive\SilverStripe\Forum\Form\PostMessageForm;
88
use FullscreenInteractive\SilverStripe\Forum\Model\ForumThread;
99
use PageController;
10+
use SilverStripe\Control\Controller;
1011
use SilverStripe\View\Requirements;
1112
use FullscreenInteractive\SilverStripe\Forum\Model\ForumThreadSubscription;
1213
use FullscreenInteractive\SilverStripe\Forum\Model\PostAttachment;
@@ -34,6 +35,7 @@ class ForumController extends PageController
3435
'AdminFormFeatures',
3536
'deleteAttachment',
3637
'deletePost',
38+
'deletethread',
3739
'editpost',
3840
'markasspam',
3941
'PostMessageForm',
@@ -265,6 +267,7 @@ public function ban()
265267
return ($request->isAjax()) ? true : $this->redirectBack();
266268
}
267269

270+
268271
public function ghost()
269272
{
270273
$request = $this->getRequest();
@@ -401,6 +404,7 @@ public function filterLanguage(string $content): string
401404
return $content;
402405
}
403406

407+
404408
/**
405409
* Get the link for the reply action
406410
*
@@ -411,6 +415,26 @@ public function ReplyLink()
411415
return self::join_links($this->Link(), 'reply', $this->urlParams['ID']);
412416
}
413417

418+
419+
public function reply()
420+
{
421+
$thread = $this->getForumThread();
422+
423+
if (!$thread) {
424+
return $this->httpError(404);
425+
}
426+
427+
$form = $this->PostMessageForm();
428+
$form->setThread($thread);
429+
430+
return [
431+
'Thread' => $thread,
432+
'PostMessageForm' => $form,
433+
'Title' => DBField::create_field('HTMLText', _t('Forum.REPLYTO', 'Replying to: %s', $thread->Title))
434+
];
435+
}
436+
437+
414438
/**
415439
* Show will get the selected thread to the user. Also increments the forums view count.
416440
*/
@@ -576,12 +600,83 @@ public function deletePost()
576600
return $this->httpError(403);
577601
}
578602

603+
$thread = $post->Thread();
579604
$post->delete();
580605

606+
$remainingPosts = Post::get()->filter('ThreadID', $thread->ID)->count();
607+
608+
if ($remainingPosts === 0) {
609+
$thread->delete();
610+
611+
return $this->redirect($this->Link());
612+
}
613+
581614
return $this->redirectBack();
582615
}
583616

584617

618+
/**
619+
* Delete an entire thread and all its posts.
620+
*
621+
* Requires moderator permissions and a valid security token.
622+
*/
623+
public function deletethread()
624+
{
625+
$request = $this->getRequest();
626+
627+
if (!SecurityToken::inst()->checkRequest($request)) {
628+
return $this->httpError(400);
629+
}
630+
631+
$id = $request->param('ID');
632+
633+
if (!$id) {
634+
return $this->httpError(400);
635+
}
636+
637+
$thread = ForumThread::get()->byID($id);
638+
639+
if (!$thread) {
640+
return $this->httpError(404);
641+
}
642+
643+
if (!$thread->canDelete()) {
644+
return $this->httpError(403);
645+
}
646+
647+
$currentUser = Security::getCurrentUser();
648+
649+
Injector::inst()->get(LoggerInterface::class)->info(sprintf(
650+
'Deleted thread "%s" (#%d), by moderator %s (#%d)',
651+
$thread->Title,
652+
$thread->ID,
653+
$currentUser->Email ?? 'Unknown',
654+
$currentUser->ID ?? 0
655+
));
656+
657+
$thread->delete();
658+
659+
return ($request->isAjax()) ? true : $this->redirect($this->Link());
660+
}
661+
662+
663+
/**
664+
* Returns a tokenised URL for deleting the current thread, if the user can moderate.
665+
*/
666+
public function DeleteThreadLink(): ?string
667+
{
668+
$thread = $this->getForumThread();
669+
670+
if (!$thread || !$thread->canDelete()) {
671+
return null;
672+
}
673+
674+
$url = Controller::join_links($this->Link('deletethread'), $thread->ID);
675+
676+
return SecurityToken::inst()->addToUrl($url);
677+
}
678+
679+
585680
/**
586681
* Forum Admin Features form.
587682
* Handles the dropdown to select the new forum category and the checkbox for stickyness

src/PageTypes/ForumHolderController.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
use SilverStripe\Model\List\PaginatedList;
1212
use SilverStripe\ORM\FieldType\DBField;
1313
use SilverStripe\View\Requirements;
14-
use SilverStripe\Security\Member;
1514
use SilverStripe\Security\Security;
1615

1716
class ForumHolderController extends PageController
@@ -27,7 +26,7 @@ class ForumHolderController extends PageController
2726

2827
public function init()
2928
{
30-
Requirements::javascript("fullscreeninteractive/silverstripe-forum:client/javascript/forum.js");
29+
Requirements::javascript("fullscreeninteractive/silverstripe-forum:client/javascript/Forum.js");
3130
Requirements::css("fullscreeninteractive/silverstripe-forum:client/css/Forum.css");
3231

3332
parent::init();

templates/FullscreenInteractive/SilverStripe/Forum/PageTypes/Layout/Forum_reply.ss

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,18 @@
33
$PostMessageForm
44

55
<div id="forum__previous-posts" class="forum__previous-posts">
6+
<h2>Replying to: $Topic.Title</h2>
7+
68
<ul id="forum__posts" class="forum__posts">
7-
<% loop $Posts('DESC') %>
9+
<% loop $Posts('DESC').Limit(3) %>
810
<li class="$EvenOdd">
911
<% include SinglePost %>
1012
</li>
1113
<% end_loop %>
1214
</ul>
15+
<p>
16+
<a href="{$Thread.Link}" class="btn btn-secondary" target="_blank">View topic</a>
17+
</p>
1318
</div>
1419

1520
<% include ForumFooter %>

templates/FullscreenInteractive/SilverStripe/Forum/PageTypes/Layout/Forum_show.ss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@
8383
<div class="forum__admin-features">
8484
<h3 class="forum__admin-features-title">Forum Admin Features</h3>
8585
$AdminFormFeatures
86+
87+
<% if $DeleteThreadLink %>
88+
<a href="$DeleteThreadLink" class="forum__delete-thread-link deleteThreadLink"><%t Forum.DELETETHREAD "Delete Thread" %></a>
89+
<% end_if %>
8690
</div>
8791
<% end_if %>
8892

0 commit comments

Comments
 (0)