MessagesController   A
last analyzed

Complexity

Total Complexity 36

Size/Duplication

Total Lines 345
Duplicated Lines 9.28 %

Coupling/Cohesion

Components 2
Dependencies 8

Importance

Changes 0
Metric Value
wmc 36
lcom 2
cbo 8
dl 32
loc 345
rs 9.52
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 1
A index() 0 12 1
A show() 0 25 2
B create() 0 25 6
A store() 0 39 3
A update() 0 36 3
A read() 16 16 4
A unread() 16 16 4
A delete() 0 10 3
A unreadCount() 0 6 1
A inboxData() 0 23 4
A threadMessagesData() 0 19 4

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace ReliQArts\Mardin\Http\Controllers;
4
5
use Carbon\Carbon;
6
use League\Fractal;
7
use Illuminate\Http\Request;
8
use ReliQArts\Mardin\Contracts\User;
9
use ReliQArts\Mardin\Contracts\Thread;
10
use ReliQArts\Mardin\Contracts\Message;
11
use ReliQArts\Mardin\Events\NewMessage;
12
// use ReliQArts\Mardin\Events\NewMessage;
13
use ReliQArts\Mardin\Contracts\Participant;
14
use Illuminate\Routing\Controller as BaseController;
15
use ReliQArts\Mardin\Transformers\ThreadTransformer;
16
use ReliQArts\Mardin\Transformers\MessageTransformer;
17
use Illuminate\Foundation\Validation\ValidatesRequests;
18
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
19
20
class MessagesController extends BaseController
21
{
22
    use AuthorizesRequests, ValidatesRequests;
23
24
    /**
25
     * Thread model.
26
     * @var Thread
27
     */
28
    protected $threads;
29
30
    /**
31
     * Message model.
32
     * @var Message
33
     */
34
    protected $messages;
35
36
    /**
37
     * Participant model.
38
     * @var Participant
39
     */
40
    protected $participants;
41
42
    /**
43
     * User model.
44
     * @var User
45
     */
46
    protected $users;
47
48
    /**
49
     * Fractal manager instance.
50
     * @var Fractal\Manager
51
     */
52
    protected $fractal;
53
54
    /**
55
     * Constructor.
56
     */
57
    public function __construct(Thread $threads, Message $messages, User $users, Participant $participants)
58
    {
59
        $this->threads = $threads;
60
        $this->messages = $messages;
61
        $this->users = $users;
62
        $this->participants = $participants;
63
        $this->fractal = new Fractal\Manager;
64
    }
65
66
    /**
67
     * Show all of the message threads to the user.
68
     *
69
     * @return mixed
70
     */
71
    public function index()
72
    {
73
        $this->authorize('receive', resolve(Message::class));
74
75
        $currentUserId = auth()->user()->id;
76
        $title = 'Inbox';
77
78
        // All threads that user is participating in
79
        $threads = $this->threads->forUser($currentUserId)->get();
0 ignored issues
show
Bug introduced by
The method forUser() does not seem to exist on object<ReliQArts\Mardin\Contracts\Thread>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
80
81
        return view(config('mardin.views.wrappers.index'), compact('threads', 'currentUserId', 'title'));
82
    }
83
84
    /**
85
     * Shows a message thread.
86
     *
87
     * @param Thread $thread
88
     * @return mixed
89
     */
90
    public function show(Thread $thread)
91
    {
92
        $this->authorize('receive', resolve(Message::class));
93
94
        // don't show the current user in list
95
        $userId = auth()->user()->id;
96
        $otherUsersIds = array_except($thread->participantsUserIds(), [$userId]);
97
        $users = $this->users->whereIn('id', $otherUsersIds)->get();
0 ignored issues
show
Bug introduced by
The method whereIn() does not seem to exist on object<ReliQArts\Mardin\Contracts\User>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
98
        $title = "{$thread->subject} &mdash; Inbox";
0 ignored issues
show
Bug introduced by
Accessing subject on the interface ReliQArts\Mardin\Contracts\Thread suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
99
100
        if (! $users->count()) {
101
            $errorMessage = 'Could not load thread. Participants error.';
102
103
            return redirect()->back()->with([
104
                'message' => $errorMessage,
105
                'error' => $errorMessage,
106
                'status' => $errorMessage,
107
            ]);
108
        }
109
110
        $thread->markAsRead($userId);
111
        unset($thread->deleted_at);
112
113
        return view(config('mardin.views.wrappers.show'), compact('thread', 'users', 'title'));
114
    }
115
116
    /**
117
     * Creates a new message thread.
118
     *
119
     * @return mixed
120
     */
121
    public function create(Request $request)
122
    {
123
        $this->authorize('send', resolve(Message::class));
124
125
        $users = $this->users->where('id', '!=', auth()->id())->get();
0 ignored issues
show
Bug introduced by
The method where() does not seem to exist on object<ReliQArts\Mardin\Contracts\User>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
126
        $title = $request->subject ?: 'New Conversation';
127
        $subject = $request->subject ?: 'New Conversation';
128
        $recipients = $request->recipients ?: [];
129
        $infoLine = 'New Conversation';
130
131
        if (count($recipients)) {
132
            $recipientNames = $this->users->whereIn('id', $recipients)->get()->map(function ($r) {
0 ignored issues
show
Bug introduced by
The method whereIn() does not seem to exist on object<ReliQArts\Mardin\Contracts\User>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
133
                return $r->name;
134
            })->toArray();
135
            $recipientNames = implode(', ', $recipientNames);
136
137
            if ($request->isOffer) {
138
                $infoLine = "Offer to $recipientNames";
139
            } else {
140
                $infoLine = "Between $recipientNames and You";
141
            }
142
        }
143
144
        return view(config('mardin.views.wrappers.show'), compact('users', 'title', 'recipients', 'subject', 'infoLine'));
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 122 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
145
    }
146
147
    /**
148
     * Stores a new message thread.
149
     *
150
     * @param  Illuminate\Http\Request $request
0 ignored issues
show
Documentation introduced by
Should the type for parameter $request not be Request?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
151
     * @return mixed
152
     */
153
    public function store(Request $request)
154
    {
155
        if (! $request->ajax()) {
156
            abort(404);
157
        }
158
159
        $this->authorize('send', resolve(Message::class));
160
161
        $thread = $this->threads->create([
0 ignored issues
show
Bug introduced by
The method create() does not seem to exist on object<ReliQArts\Mardin\Contracts\Thread>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
162
            'subject' => $request->subject,
163
        ]);
164
165
        // Message
166
        $message = $this->messages->create(
0 ignored issues
show
Bug introduced by
The method create() does not seem to exist on object<ReliQArts\Mardin\Contracts\Message>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
167
            [
168
                'thread_id' => $thread->id,
169
                'user_id'   => auth()->user()->id,
170
                'body'      => $request->message,
171
            ]
172
        );
173
174
        // Sender
175
        $this->participants->create([
0 ignored issues
show
Bug introduced by
The method create() does not seem to exist on object<ReliQArts\Mardin\Contracts\Participant>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
176
            'thread_id' => $thread->id,
177
            'user_id'   => auth()->user()->id,
178
            'last_read' => new Carbon,
179
        ]);
180
181
        // Recipients
182
        if ($request->has('recipients')) {
183
            $thread->addParticipant($request->recipients);
184
        }
185
186
        event(new NewMessage($message));
187
        $resource = new Fractal\Resource\Item($message, new MessageTransformer);
188
        $this->fractal->parseIncludes('thread');
189
190
        return $this->fractal->createData($resource)->toArray();
191
    }
192
193
    /**
194
     * Adds a new message to a current thread.
195
     *
196
     * @param  Illuminate\Http\Request $request
0 ignored issues
show
Documentation introduced by
Should the type for parameter $request not be Request?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
197
     * @param $id
198
     * @return mixed
199
     */
200
    public function update(Request $request, Thread $thread)
201
    {
202
        if (! $request->ajax()) {
203
            abort(404);
204
        }
205
206
        $this->authorize('send', resolve(Message::class));
207
208
        $thread->activateAllParticipants();
209
210
        // Message
211
        $message = $this->messages->create([
0 ignored issues
show
Bug introduced by
The method create() does not seem to exist on object<ReliQArts\Mardin\Contracts\Message>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
212
            'thread_id' => $thread->id,
0 ignored issues
show
Bug introduced by
Accessing id on the interface ReliQArts\Mardin\Contracts\Thread suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
213
            'user_id'   => auth()->id(),
214
            'body'      => $request->message,
215
        ]);
216
217
        // Add replier as a participant
218
        $participant = $this->participants->firstOrCreate([
0 ignored issues
show
Bug introduced by
The method firstOrCreate() does not seem to exist on object<ReliQArts\Mardin\Contracts\Participant>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
219
            'thread_id' => $thread->id,
0 ignored issues
show
Bug introduced by
Accessing id on the interface ReliQArts\Mardin\Contracts\Thread suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
220
            'user_id'   => auth()->user()->id,
221
        ]);
222
        $participant->last_read = new Carbon;
223
        $participant->save();
224
225
        // Recipients
226
        if ($request->has('recipients')) {
227
            $thread->addParticipant($request->recipients);
228
        }
229
230
        event(new NewMessage($message));
231
        $resource = new Fractal\Resource\Item($message, new MessageTransformer);
232
        $this->fractal->parseIncludes('thread');
233
234
        return $this->fractal->createData($resource)->toArray();
235
    }
236
237
    /**
238
     * Mark a specific thread as read, for ajax use.
239
     *
240
     * @param $id
241
     */
242 View Code Duplication
    public function read(Request $request)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
243
    {
244
        if (! $request->ajax()) {
245
            abort(404);
246
        }
247
248
        if ($threadIds = $request->threads) {
249
            $threads = $this->threads->whereIn('id', $threadIds)->get();
0 ignored issues
show
Bug introduced by
The method whereIn() does not seem to exist on object<ReliQArts\Mardin\Contracts\Thread>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
250
            foreach ($threads as $thread) {
251
                $thread->markAsRead(auth()->id());
252
            }
253
            $collection = new Fractal\Resource\Collection($threads, new ThreadTransformer);
254
255
            return $this->fractal->createData($collection)->toArray();
256
        }
257
    }
258
259
    /**
260
     * Mark a specific thread as unread, for ajax use.
261
     *
262
     * @param $id
263
     */
264 View Code Duplication
    public function unread(Request $request)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
265
    {
266
        if (! $request->ajax()) {
267
            abort(404);
268
        }
269
270
        if ($threadIds = $request->threads) {
271
            $threads = $this->threads->whereIn('id', $threadIds)->get();
0 ignored issues
show
Bug introduced by
The method whereIn() does not seem to exist on object<ReliQArts\Mardin\Contracts\Thread>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
272
            foreach ($threads as $thread) {
273
                $thread->markAsUnread(auth()->id());
274
            }
275
            $collection = new Fractal\Resource\Collection($threads, new ThreadTransformer);
276
277
            return $this->fractal->createData($collection)->toArray();
278
        }
279
    }
280
281
    /**
282
     * Delete a thread, for ajax use.
283
     *
284
     * @param $id
285
     */
286
    public function delete(Request $request)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
287
    {
288
        if (! $request->ajax()) {
289
            abort(404);
290
        }
291
292
        if ($threadIds = $request->threads) {
293
            return $threads = $this->threads->whereIn('id', $threadIds)->delete();
0 ignored issues
show
Bug introduced by
The method whereIn() does not seem to exist on object<ReliQArts\Mardin\Contracts\Thread>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Unused Code introduced by
$threads is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
294
        }
295
    }
296
297
    /**
298
     * Get the number of unread threads, for ajax use.
299
     *
300
     * @return array
301
     */
302
    public function unreadCount()
303
    {
304
        $count = auth()->user()->newMessagesCount();
305
306
        return ['msg_count' => $count];
307
    }
308
309
    /**
310
     * Get threads for user. (inbox).
311
     *
312
     * @param Illuminate\Http\Request $request
0 ignored issues
show
Documentation introduced by
Should the type for parameter $request not be Request?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
313
     * @param string $filter Filter messages for inbox.
314
     */
315
    public function inboxData(Request $request, $filter = 'all')
316
    {
317
        if (! $request->ajax()) {
318
            abort(404);
319
        }
320
321
        $userId = $request->user()->id;
322
        $threads = $this->threads;
323
324
        switch ($filter) {
325
            case 'new':
326
            case 'unread':
327
                $threads = $threads->forUserWithNewMessages($userId)->latest('updated_at')->get();
0 ignored issues
show
Bug introduced by
The method forUserWithNewMessages() does not seem to exist on object<ReliQArts\Mardin\Contracts\Thread>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
328
                break;
329
            default:
330
                $threads = $threads->forUser($userId)->latest('updated_at')->get();
0 ignored issues
show
Bug introduced by
The method forUser() does not seem to exist on object<ReliQArts\Mardin\Contracts\Thread>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
331
                break;
332
        }
333
334
        $collection = new Fractal\Resource\Collection($threads, new ThreadTransformer);
335
336
        return $this->fractal->createData($collection)->toArray();
337
    }
338
339
    /**
340
     * Get messgges for thread. (inbox).
341
     *
342
     * @param  Illuminate\Http\Request $request
0 ignored issues
show
Documentation introduced by
Should the type for parameter $request not be Request?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
343
     * @param string $thread Thread to get messages for.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $thread not be Thread?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
344
     */
345
    public function threadMessagesData(Request $request, Thread $thread)
346
    {
347
        if (! $request->ajax()) {
348
            abort(404);
349
        }
350
351
        $userId = $request->user()->id;
0 ignored issues
show
Unused Code introduced by
$userId is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
352
        $limit = $request->limit ?: 200;
353
        $page = $request->p ?: 1;
354
355
        $messages = $thread->messages()->skip($page - 1)->take($limit)->get();
356
        $thread = new Fractal\Resource\Item($thread, new ThreadTransformer);
357
        $messages = new Fractal\Resource\Collection($messages, new MessageTransformer);
358
359
        return [
360
            'messages' => $this->fractal->createData($messages)->toArray(),
361
            'thread' => $this->fractal->createData($thread)->toArray(),
362
        ];
363
    }
364
}
365