• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

marscoin / martianrepublic / 23823524774

31 Mar 2026 11:03PM UTC coverage: 10.419%. Remained the same
23823524774

push

github

Martian Congress
refactor: A1 — split ApiController (1,147 lines) into 5 controllers

The god controller is dead. Long live focused controllers:

- FeedApiController (287 lines) — allPublic, allCitizen, allApplicants,
  allFeed, showCitizen, scitizen
- AuthApiController (260 lines) — marsAuth, checkAuth, wauth, token
- ForumApiController (205 lines) — threads, comments, categories
- ContentApiController (230 lines) — pinpic, pinvideo, pinjson (IPFS)
- UserManagementController (95 lines) — blockUser, deleteUser, eula

ApiController.php is now 18 lines (empty shell with migration notes).
All routes updated to array notation pointing to new controllers.
Zero method logic changed — pure structural refactor.

127 tests, 0 PHPStan errors, API endpoints verified.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

31 of 637 new or added lines in 5 files covered. (4.87%)

599 of 5749 relevant lines covered (10.42%)

1.47 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/app/Http/Controllers/ForumApiController.php
1
<?php
2

3
namespace App\Http\Controllers;
4

5
use App\Models\Posts;
6
use App\Models\Threads;
7
use Illuminate\Http\Request;
8
use Illuminate\Support\Facades\Auth;
9
use Illuminate\Support\Facades\DB;
10

11
class ForumApiController extends Controller
12
{
NEW
13
    public function getThreadsByCategory($categoryId)
×
14
    {
NEW
15
        $threads = $this->fetchThreads($categoryId);
×
16

NEW
17
        return response()->json(['threads' => $threads]);
×
18
    }
19

NEW
20
    public function getThreadComments($threadId)
×
21
    {
22
        // Assume $threadId is passed correctly to the function
NEW
23
        $comments = $this->fetchCommentsByThread($threadId);
×
24

NEW
25
        return response()->json(['comments' => $comments]);
×
26
    }
27

NEW
28
    public function getAllCategoriesWithThreads()
×
29
    {
NEW
30
        $userId = Auth::id();
×
31

NEW
32
        $categories = DB::table('forum_categories')->get();
×
33

34
        // Fetch all threads in a single query instead of N+1
NEW
35
        $threads = DB::table('forum_threads')
×
NEW
36
            ->leftJoin('users', 'forum_threads.author_id', '=', 'users.id')
×
NEW
37
            ->leftJoin('profile', 'users.id', '=', 'profile.userid')
×
NEW
38
            ->leftJoin('user_blocks as ub', function ($join) use ($userId) {
×
NEW
39
                $join->on('forum_threads.author_id', '=', 'ub.blocked_user_id')
×
NEW
40
                    ->where('ub.user_id', '=', $userId);
×
NEW
41
            })
×
NEW
42
            ->select(
×
NEW
43
                'forum_threads.id',
×
NEW
44
                'forum_threads.category_id',
×
NEW
45
                'forum_threads.title',
×
NEW
46
                'forum_threads.created_at',
×
NEW
47
                'forum_threads.reply_count',
×
NEW
48
                'users.fullname as author_name',
×
NEW
49
                DB::raw('IF(ub.blocked_user_id IS NOT NULL, true, false) as is_blocked')
×
NEW
50
            )
×
NEW
51
            ->orderBy('forum_threads.created_at', 'desc')
×
NEW
52
            ->get()
×
NEW
53
            ->groupBy('category_id');
×
54

NEW
55
        foreach ($categories as $category) {
×
NEW
56
            $category->threads = $threads->get($category->id, collect());
×
57
        }
58

NEW
59
        return response()->json(['categories' => $categories]);
×
60
    }
61

NEW
62
    public function createThread(Request $request)
×
63
    {
NEW
64
        $request->validate([
×
NEW
65
            'category_id' => 'required|exists:forum_categories,id',
×
NEW
66
            'title' => 'required|string|max:255',
×
NEW
67
            'content' => 'required|string',
×
NEW
68
        ]);
×
69

NEW
70
        $thread = new Threads;
×
NEW
71
        $thread->category_id = $request->category_id;
×
NEW
72
        $thread->author_id = Auth::id();
×
NEW
73
        $thread->title = $request->title;
×
NEW
74
        $thread->save();
×
75

NEW
76
        $post = new Posts;
×
NEW
77
        $post->thread_id = $thread->id;
×
NEW
78
        $post->author_id = Auth::id();
×
NEW
79
        $post->content = $request->content;
×
NEW
80
        $post->save();
×
81

NEW
82
        $thread->first_post_id = $post->id;
×
NEW
83
        $thread->last_post_id = $post->id;
×
NEW
84
        $thread->reply_count = 0;
×
NEW
85
        $thread->save();
×
86

NEW
87
        return response()->json([
×
NEW
88
            'message' => 'Thread created successfully',
×
NEW
89
            'thread_id' => $thread->id,
×
NEW
90
            'post_id' => $post->id,
×
NEW
91
        ], 201);
×
92
    }
93

NEW
94
    public function createComment(Request $request, $threadId)
×
95
    {
NEW
96
        $request->validate([
×
NEW
97
            'content' => 'required|string',
×
NEW
98
            'post_id' => 'nullable|exists:forum_posts,id',
×
NEW
99
        ]);
×
100

NEW
101
        $thread = Threads::findOrFail($threadId);
×
102

NEW
103
        $post = new Posts;
×
NEW
104
        $post->thread_id = $threadId;
×
NEW
105
        $post->author_id = Auth::id();
×
NEW
106
        $post->content = $request->content;
×
NEW
107
        $post->post_id = $request->post_id; // This will be null for top-level comments
×
NEW
108
        $post->save();
×
109

NEW
110
        $thread->last_post_id = $post->id;
×
NEW
111
        $thread->reply_count += 1;
×
NEW
112
        $thread->save();
×
113

NEW
114
        return response()->json([
×
NEW
115
            'message' => 'Comment created successfully',
×
NEW
116
            'post_id' => $post->id,
×
NEW
117
        ], 201);
×
118
    }
119

NEW
120
    private function fetchThreads($categoryId)
×
121
    {
NEW
122
        $userId = Auth::id();
×
123

NEW
124
        $threads = DB::table('forum_threads')
×
NEW
125
            ->where('forum_threads.category_id', $categoryId)
×
NEW
126
            ->leftJoin('users', 'forum_threads.author_id', '=', 'users.id')
×
NEW
127
            ->leftJoin('profile', 'users.id', '=', 'profile.userid')
×
NEW
128
            ->leftJoin('user_blocks as ub', function ($join) use ($userId) {
×
NEW
129
                $join->on('forum_threads.author_id', '=', 'ub.blocked_user_id')
×
NEW
130
                    ->where('ub.user_id', '=', $userId);
×
NEW
131
            })
×
NEW
132
            ->select(
×
NEW
133
                'forum_threads.id',
×
NEW
134
                'forum_threads.title',
×
NEW
135
                'forum_threads.created_at',
×
NEW
136
                'forum_threads.reply_count',
×
NEW
137
                'users.fullname as author_name',
×
NEW
138
                DB::raw('IF(ub.blocked_user_id IS NOT NULL, true, false) as is_blocked')
×
NEW
139
            )
×
NEW
140
            ->orderBy('forum_threads.created_at', 'desc')
×
NEW
141
            ->get();
×
142

NEW
143
        return $threads;
×
144
    }
145

NEW
146
    private function fetchCommentsByThread($threadId)
×
147
    {
NEW
148
        $userId = Auth::id();
×
149

NEW
150
        $query = '
×
151
            WITH RECURSIVE CommentTree AS (
152
                SELECT
153
                    p.id,
154
                    p.thread_id,
155
                    p.author_id,
156
                    p.content,
157
                    p.post_id as pid,
158
                    p.created_at,
159
                    CHAR_LENGTH(p.content) as char_length_sum
160
                FROM
161
                    forum_posts p
162
                WHERE
163
                    p.thread_id = ? AND p.post_id IS NULL
164

165
                UNION ALL
166

167
                SELECT
168
                    p.id,
169
                    p.thread_id,
170
                    p.author_id,
171
                    p.content,
172
                    p.post_id,
173
                    p.created_at,
174
                    ct.char_length_sum + CHAR_LENGTH(p.content)
175
                FROM
176
                    forum_posts p
177
                INNER JOIN
178
                    CommentTree ct ON p.post_id = ct.id
179
            )
180
            SELECT
181
                ct.id,
182
                ct.thread_id,
183
                ct.author_id,
184
                u.fullname,
185
                ct.content,
186
                ct.created_at,
187
                ct.pid,
188
                CHAR_LENGTH(ct.content) as char_length_sum,
189
                IF(ub.blocked_user_id IS NOT NULL, true, false) as is_blocked
190
            FROM
191
                CommentTree ct
192
            LEFT JOIN users u ON ct.author_id = u.id
193
            LEFT JOIN profile pr ON ct.author_id = pr.userid
194
            LEFT JOIN user_blocks ub ON ub.blocked_user_id = ct.author_id AND ub.user_id = ?
195
            ORDER BY
196
                ct.pid ASC,
197
                ct.created_at ASC;
NEW
198
        ';
×
199

NEW
200
        $comments = DB::select($query, [$threadId, $userId]);
×
NEW
201
        $commentsCollection = collect($comments);
×
202

NEW
203
        return response()->json(['comments' => $commentsCollection]);
×
204
    }
205
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc