Passed
Push — master ( 5aa5e3...07d8b3 )
by Darko
09:19
created

AdminInvitationController::index()   D

Complexity

Conditions 15
Paths 252

Size

Total Lines 100
Code Lines 70

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
eloc 70
dl 0
loc 100
rs 4.4333
c 2
b 1
f 0
cc 15
nc 252
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace App\Http\Controllers\Admin;
4
5
use App\Http\Controllers\BasePageController;
6
use App\Models\Invitation;
7
use App\Models\User;
8
use App\Services\InvitationService;
9
use Illuminate\Http\RedirectResponse;
10
use Illuminate\Http\Request;
11
12
class AdminInvitationController extends BasePageController
13
{
14
    protected InvitationService $invitationService;
15
16
    public function __construct(InvitationService $invitationService)
17
    {
18
        parent::__construct();
19
        $this->invitationService = $invitationService;
20
    }
21
22
    /**
23
     * Display all invitations statistics and management page
24
     */
25
    public function index(Request $request): void
26
    {
27
        $this->setAdminPrefs();
28
29
        $meta_title = $title = 'Invitation Management';
30
31
        // Get filter parameters
32
        $status = $request->get('status', '');
33
        $invited_by = $request->get('invited_by', '');
34
        $email = $request->get('email', '');
35
        $orderBy = $request->get('ob', 'created_at_desc');
36
        $page = $request->get('page', 1);
0 ignored issues
show
Unused Code introduced by
The assignment to $page is dead and can be removed.
Loading history...
37
38
        // Build query
39
        $query = Invitation::with(['invitedBy', 'usedBy']);
40
41
        // Apply filters
42
        if ($status) {
43
            switch ($status) {
44
                case 'pending':
45
                    $query->valid(); // Active, not expired, not used
46
                    break;
47
                case 'used':
48
                    $query->used(); // Has used_at timestamp
49
                    break;
50
                case 'expired':
51
                    $query->expired(); // expires_at is in the past
52
                    break;
53
                case 'cancelled':
54
                    $query->where('is_active', false)
55
                        ->whereNull('used_at'); // Inactive but not used = cancelled
56
                    break;
57
            }
58
        }
59
60
        if ($invited_by) {
61
            $user = User::where('username', 'like', '%'.$invited_by.'%')->first();
62
            if ($user) {
63
                $query->where('invited_by', $user->id);
64
            }
65
        }
66
67
        if ($email) {
68
            $query->where('email', 'like', '%'.$email.'%');
69
        }
70
71
        // Apply ordering
72
        switch ($orderBy) {
73
            case 'created_at_asc':
74
                $query->orderBy('created_at', 'asc');
75
                break;
76
            case 'created_at_desc':
77
                $query->orderBy('created_at', 'desc');
78
                break;
79
            case 'expires_at_asc':
80
                $query->orderBy('expires_at', 'asc');
81
                break;
82
            case 'expires_at_desc':
83
                $query->orderBy('expires_at', 'desc');
84
                break;
85
            case 'email_asc':
86
                $query->orderBy('email', 'asc');
87
                break;
88
            case 'email_desc':
89
                $query->orderBy('email', 'desc');
90
                break;
91
            default:
92
                $query->orderBy('created_at', 'desc');
93
        }
94
95
        // Paginate results
96
        $invitations = $query->paginate(config('nntmux.items_per_page', 25));
97
98
        // Get overall statistics
99
        $stats = $this->getOverallStats();
100
101
        // Get user statistics (top inviters)
102
        $topInviters = $this->getTopInviters();
103
104
        $this->smarty->assign([
105
            'invitations' => $invitations,
106
            'stats' => $stats,
107
            'topInviters' => $topInviters,
108
            'status' => $status,
109
            'invited_by' => $invited_by,
110
            'email' => $email,
111
            'orderBy' => $orderBy,
112
            'statusOptions' => [
113
                '' => 'All',
114
                'pending' => 'Pending',
115
                'used' => 'Used',
116
                'expired' => 'Expired',
117
                'cancelled' => 'Cancelled',
118
            ],
119
        ]);
120
121
        $content = $this->smarty->fetch('admin-invitation-list.tpl');
122
        $this->smarty->assign(compact('title', 'meta_title', 'content'));
123
124
        $this->adminrender();
125
    }
126
127
    /**
128
     * Get overall invitation statistics
129
     */
130
    private function getOverallStats(): array
131
    {
132
        return [
133
            'total' => Invitation::count(),
134
            'pending' => Invitation::valid()->count(),
135
            'used' => Invitation::used()->count(),
136
            'expired' => Invitation::expired()->count(),
137
            'cancelled' => Invitation::where('is_active', false)->whereNull('used_at')->count(),
138
            'today' => Invitation::whereDate('created_at', today())->count(),
139
            'this_week' => Invitation::whereBetween('created_at', [
140
                now()->startOfWeek(),
141
                now()->endOfWeek(),
142
            ])->count(),
143
            'this_month' => Invitation::whereMonth('created_at', now()->month)
144
                ->whereYear('created_at', now()->year)
145
                ->count(),
146
        ];
147
    }
148
149
    /**
150
     * Get top inviters statistics
151
     */
152
    private function getTopInviters(int $limit = 10): array
153
    {
154
        return User::select('users.*')
155
            ->selectRaw('COUNT(invitations.id) as total_invitations')
156
            ->selectRaw('COUNT(CASE WHEN invitations.used_at IS NOT NULL THEN 1 END) as successful_invitations')
157
            ->leftJoin('invitations', 'users.id', '=', 'invitations.invited_by')
158
            ->groupBy('users.id')
159
            ->having('total_invitations', '>', 0)
160
            ->orderBy('total_invitations', 'desc')
161
            ->limit($limit)
162
            ->get()
163
            ->toArray();
164
    }
165
166
    /**
167
     * Cancel an invitation
168
     */
169
    public function cancel(Request $request): RedirectResponse
170
    {
171
        try {
172
            $id = $request->route('id');
173
            $this->invitationService->cancelInvitation($id);
174
175
            return redirect()->back()->with('success', 'Invitation cancelled successfully');
176
        } catch (\Exception $e) {
177
            return redirect()->back()->with('error', 'Failed to cancel invitation: '.$e->getMessage());
178
        }
179
    }
180
181
    /**
182
     * Resend an invitation
183
     */
184
    public function resend(Request $request): RedirectResponse
185
    {
186
        try {
187
            $id = $request->route('id');
188
            $this->invitationService->resendInvitation($id);
189
190
            return redirect()->back()->with('success', 'Invitation resent successfully');
191
        } catch (\Exception $e) {
192
            return redirect()->back()->with('error', 'Failed to resend invitation: '.$e->getMessage());
193
        }
194
    }
195
196
    /**
197
     * Cleanup expired invitations
198
     */
199
    public function cleanup(Request $request): RedirectResponse
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

199
    public function cleanup(/** @scrutinizer ignore-unused */ Request $request): RedirectResponse

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
200
    {
201
        try {
202
            $cleanedCount = $this->invitationService->cleanupExpiredInvitations();
203
204
            return redirect()->back()->with('success', "Cleaned up {$cleanedCount} expired invitations");
205
        } catch (\Exception $e) {
206
            return redirect()->back()->with('error', 'Failed to cleanup invitations: '.$e->getMessage());
207
        }
208
    }
209
210
    /**
211
     * View detailed invitation
212
     */
213
    public function show(Request $request): void
214
    {
215
        $this->setAdminPrefs();
216
217
        $id = $request->route('id');
218
        $invitation = Invitation::with(['invitedBy', 'usedBy'])->findOrFail($id);
219
220
        $meta_title = $title = 'Invitation Details';
221
222
        $this->smarty->assign([
223
            'invitation' => $invitation,
224
        ]);
225
226
        $content = $this->smarty->fetch('admin-invitation-show.tpl');
227
        $this->smarty->assign(compact('title', 'meta_title', 'content'));
228
229
        $this->adminrender();
230
    }
231
232
    /**
233
     * Bulk actions on invitations
234
     */
235
    public function bulkAction(Request $request): RedirectResponse
236
    {
237
        $action = $request->get('bulk_action');
238
        $invitationIds = $request->get('invitation_ids', []);
239
240
        if (empty($invitationIds)) {
241
            return redirect()->back()->with('error', 'No invitations selected');
242
        }
243
244
        try {
245
            $count = 0;
246
            switch ($action) {
247
                case 'cancel':
248
                    foreach ($invitationIds as $id) {
249
                        $this->invitationService->cancelInvitation($id);
250
                        $count++;
251
                    }
252
253
                    return redirect()->back()->with('success', "Cancelled {$count} invitations");
254
255
                case 'resend':
256
                    foreach ($invitationIds as $id) {
257
                        $this->invitationService->resendInvitation($id);
258
                        $count++;
259
                    }
260
261
                    return redirect()->back()->with('success', "Resent {$count} invitations");
262
263
                case 'delete':
264
                    Invitation::whereIn('id', $invitationIds)->delete();
265
                    $count = count($invitationIds);
266
267
                    return redirect()->back()->with('success', "Deleted {$count} invitations");
268
269
                default:
270
                    return redirect()->back()->with('error', 'Invalid bulk action');
271
            }
272
        } catch (\Exception $e) {
273
            return redirect()->back()->with('error', 'Bulk action failed: '.$e->getMessage());
274
        }
275
    }
276
}
277