Completed
Push — master ( 9c742a...1858b1 )
by Fèvre
14s
created

src/Controller/ConversationsController.php (4 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
namespace App\Controller;
3
4
use App\Event\Notifications;
5
use Cake\Core\Configure;
6
use Cake\Database\Expression\QueryExpression;
7
use Cake\Event\Event;
8
use Cake\I18n\Time;
9
use Cake\Network\Exception\NotFoundException;
10
use Cake\Routing\Router;
11
12
class ConversationsController extends AppController
13
{
14
15
    /**
16
     * Initialization hook method.
17
     *
18
     * @return void
19
     */
20
    public function initialize()
21
    {
22
        parent::initialize();
23
24
        $this->loadComponent('RequestHandler');
25
    }
26
27
    /**
28
     * BeforeFilter handle.
29
     *
30
     * @param Event $event The beforeFilter event that was fired.
31
     *
32
     * @return void
33
     */
34
    public function beforeFilter(Event $event)
35
    {
36
        parent::beforeFilter($event);
37
38
        $this->Auth->deny();
39
40
        if (Configure::read('Conversations.enabled') === false && $this->request->action != 'maintenance') {
41
            $this->redirect(['action' => 'maintenance']);
42
        } elseif (Configure::read('Conversations.enabled') === true && $this->request->action == 'maintenance') {
43
            $this->redirect(['action' => 'index']);
44
        }
45
    }
46
47
    /**
48
     * Display all conversations for the user.
49
     *
50
     * @return void
51
     */
52
    public function index()
53
    {
54
        $this->ConversationsUsers = $this->loadModel('ConversationsUsers');
55
56
        $this->paginate = [
57
            'maxLimit' => Configure::read('Conversations.conversations_per_page')
58
        ];
59
        $conversations = $this->ConversationsUsers
60
            ->find()
61
            ->contain([
62
                'Users',
63
                'Conversations',
64
                'Conversations.Users' => function ($q) {
65
                    return $q->find('medium');
66
                },
67
                'Conversations.LastMessage',
68
                'Conversations.LastMessageUser'
69
            ])
70
            ->where([
71
                'ConversationsUsers.user_id' => $this->Auth->user('id'),
72
                'Conversations.conversation_open <>' => 2
73
            ])
74
            ->order([
75
                'ConversationsUsers.is_read' => 'ASC',
76
                'ConversationsUsers.is_star' => 'DESC',
77
                'Conversations.last_message_date' => 'DESC',
78
            ]);
79
80
        $conversations = $this->paginate($conversations);
81
82
        $this->set(compact('conversations'));
83
    }
84
85
    /**
86
     * Function to do an action when a user select a/many conversations.
87
     *
88
     * Action list :
89
     *      star : Conversations Important
90
     *      normal : Make normal conversation
91
     *      exit : Exit conversations
92
     *
93
     * @return void
94
     *
95
     * @throws NotFoundException
96
     */
97
    public function action()
98
    {
99
        if (!$this->request->is('ajax')) {
100
            throw new NotFoundException();
101
        }
102
103
        $actionAllowed = ['star', 'normal', 'exit'];
104
105
        if (!array_key_exists('action', $this->request->data) || !in_array($this->request->data['action'], $actionAllowed)) {
106
            $json = [];
107
            $json['error'] = '1';
108
            $json['message'] = __d('conversations', 'Action unknown.');
109
110
            $this->set(compact('json'));
111
            $this->set('_serialize', 'json');
112
        }
113
114
        if (!array_key_exists('conversations', $this->request->data)) {
115
            $json = [];
116
            $json['error'] = '1';
117
            $json['message'] = __d('conversations', 'You have not chosen any conversations.');
118
119
            $this->set(compact('json'));
120
            $this->set('_serialize', 'json');
121
        }
122
123
        $this->loadModel('ConversationsUsers');
124
125
        $action = $this->request->data['action'];
126
        $array = $this->request->data['conversations'];
127
128
        switch ($action) {
129 View Code Duplication
            case "star":
130
                foreach ($array as $conversationId) {
131
                    $this->ConversationsUsers->updateAll(
132
                        ['is_star' => 1],
133
                        [
134
                            'conversation_id' => $conversationId,
135
                            'user_id' => $this->Auth->user('id')
136
                        ]
137
                    );
138
                }
139
140
                $json['message'] = __d('conversations', 'Your conversation(s) has been Stared.');
141
                $json['error'] = '0';
142
                $json['redirect'] = Router::url(['action' => 'index']);
143
144
                $this->set(compact('json'));
145
146
                break;
147
148 View Code Duplication
            case "normal":
149
                foreach ($array as $conversationId) {
150
                    $this->ConversationsUsers->updateAll(
151
                        ['is_star' => 0],
152
                        [
153
                            'conversation_id' => $conversationId,
154
                            'user_id' => $this->Auth->user('id')
155
                        ]
156
                    );
157
                }
158
159
                $json['message'] = __d('conversations', 'Your conversation(s) has been set normal.');
160
                $json['error'] = '0';
161
                $json['redirect'] = Router::url(['action' => 'index']);
162
163
                $this->set(compact('json'));
164
                break;
165
166
            case "exit":
167
                foreach ($array as $conversationId) {
168
                    $user = $this->ConversationsUsers
169
                        ->find()
170
                        ->contain([
171
                            'Conversations'
172
                        ])
173
                        ->where([
174
                            'ConversationsUsers.user_id' => $this->Auth->user('id'),
175
                            'ConversationsUsers.conversation_id' => $conversationId
176
                        ])
177
                        ->first();
178
179
                    //Check if the user is the owner of the conversation.
180
                    if ($user->conversation->user_id == $this->Auth->user('id')) {
181
                        $conversation = $this->Conversations->get($conversationId);
182
                        $conversation->conversation_open = 2;
183
                        $this->Conversations->save($conversation);
184
                    } else {
185
                        $this->ConversationsUsers->delete($user);
186
187
                        $conversation = $this->Conversations->get($conversationId);
188
                        $conversation->recipient_count = $user->conversation->recipient_count - 1;
189
                        $this->Conversations->save($conversation);
190
                    }
191
                }
192
193
                $json['message'] = __d('conversations', 'You have left your conversation(s) successfully.');
194
                $json['error'] = '0';
195
                $json['redirect'] = Router::url(['action' => 'index']);
196
197
                $this->set(compact('json'));
198
                break;
199
200
            default:
201
                $json['message'] = __d('conversations', 'Action unknown.');
202
                $json['error'] = '1';
203
204
                $this->set(compact('json'));
205
                break;
206
        }
207
208
        $this->set('_serialize', 'json');
209
    }
210
211
    /**
212
     * Create a new conversation.
213
     *
214
     * @return void
215
     */
216
    public function create()
217
    {
218
        $this->loadModel('Conversations');
219
        $conversation = $this->Conversations->newEntity($this->request->data, ['validate' => 'create']);
220
221
        if ($this->request->is('post')) {
222
            $users = str_replace(",", "", trim(strtolower($this->request->data['users'])));
223
            $users = explode(" ", $users);
224
225
            //Check max users.
226
            if (!(count($users) <= Configure::read('Conversations.max_users_per_conversation'))) {
227
                $this->Flash->error(__d('conversations', 'You cannot invite more than {0} user(s) in this conversation.', Configure::read('Conversations.max_users_per_conversation')));
228
                $this->set(compact('conversation'));
229
230
                return;
231
            }
232
233
            $userMiniCount = false;
234
            $this->loadModel('Users');
235
236
            //We check if at least one user in all list exist.
237
            foreach ($users as $user) {
238
                $userCheck = $this->Users
239
                    ->find()
240
                    ->where([
241
                        'LOWER(Users.username)' => $user
242
                    ])
243
                    ->first();
244
245
                //If an user exist and if the user is not the own of the conversation.
246
                if ($userCheck && $userCheck->id != $this->Auth->user('id')) {
247
                    $userMiniCount = true;
248
                    break;
249
                }
250
            }
251
252
            if ($userMiniCount === false) {
253
                $this->Flash->error(__d('conversations', 'Please enter at least one valid recipient.'));
254
                $this->set(compact('conversation'));
255
256
                return;
257
            }
258
259
            $conversation->user_id = $this->Auth->user('id');
260
            $conversation->reply_count = 1;
261
            $conversation->recipient_count = 1;
262
            $conversation->last_message_user_id = $this->Auth->user('id');
263
            $conversation->last_message_date = new Time();
264
265
            if ($conversation = $this->Conversations->save($conversation)) {
266
                $this->loadModel('ConversationsMessages');
267
                $this->loadModel('ConversationsUsers');
268
269
                $data = [];
270
                $data['message'] = $this->request->data['message'];
271
                $data['conversation_id'] = $conversation->id;
272
                $data['user_id'] = $this->Auth->user('id');
273
274
                $entity = $this->ConversationsMessages->newEntity($data);
275
                $message = $this->ConversationsMessages->save($entity);
276
277
                $data = [];
278
                $data['conversation_id'] = $conversation->id;
279
                $data['user_id'] = $this->Auth->user('id');
280
281
                $entity = $this->ConversationsUsers->newEntity($data);
282
                $user = $this->ConversationsUsers->save($entity);
283
284
                $this->Conversations->updateAll(
285
                    [
286
                        'first_message_id' => $message->id,
287
                        'last_message_id' => $message->id
288
                    ],
289
                    [
290
                        'id' => $conversation->id
291
                    ]
292
                );
293
294
                //Save all invited users.
295
                foreach ($users as $user) {
296
                    $userExist = $this->Users
297
                        ->find()
298
                        ->where([
299
                            'LOWER(Users.username)' => $user
300
                        ])
301
                        ->first();
302
303
                    //If the user exist.
304
                    if (is_null($userExist)) {
305
                        break;
306
                    }
307
308
                    //Check if the user is not already in the conversation.
309
                    $conversUserCheck = $this->ConversationsUsers
310
                        ->find()
311
                        ->where([
312
                            'ConversationsUsers.conversation_id' => $conversation->id,
313
                            'ConversationsUsers.user_id' => $userExist->id
314
                        ])
315
                        ->first();
316
317
                    if (!is_null($conversUserCheck)) {
318
                        break;
319
                    }
320
321
                    $data = [];
322
                    $data['conversation_id'] = $conversation->id;
323
                    $data['user_id'] = $userExist->id;
324
325
                    $entity = $this->ConversationsUsers->newEntity($data);
326
                    $user = $this->ConversationsUsers->save($entity);
327
328
                    $expression = new QueryExpression('recipient_count = recipient_count + 1');
329
                    $this->Conversations->updateAll(
330
                        [$expression],
331
                        [
332
                            'id' => $conversation->id
333
                        ]
334
                    );
335
336
                    //Notifications Event.
337
                    $this->eventManager()->attach(new Notifications());
338
                    $event = new Event('Model.Notifications.dispatch', $this, [
339
                        'sender_id' => $this->Auth->user('id'),
340
                        'conversation_id' => $conversation->id,
341
                        'type' => 'conversation.reply'
342
                    ]);
343
                    $this->eventManager()->dispatch($event);
344
                }
345
346
                $this->Flash->success(__d('conversations', 'Your conversation has been created successfully !'));
347
                $this->redirect([
348
                    '_name' => 'conversations-view',
349
                    'slug' => $conversation->title,
350
                    'id' => $conversation->id
351
                ]);
352
            }
353
        }
354
355
        $this->set(compact('conversation'));
356
    }
357
358
    /**
359
     * Display a conversation.
360
     *
361
     * @return void|\Cake\Network\Response
362
     */
363
    public function view()
364
    {
365
        $this->loadModel('ConversationsUsers');
366
367
        $conversation = $this->ConversationsUsers
368
            ->find()
369
            ->contain([
370
                'Users',
371
                'Conversations',
372
                'Conversations.LastMessage',
373
                'Conversations.LastMessageUser'
374
            ])
375
            ->where([
376
                'ConversationsUsers.conversation_id' => $this->request->id,
377
                'ConversationsUsers.user_id' => $this->Auth->user('id'),
378
                'Conversations.conversation_open <>' => 2
379
            ])
380
            ->first();
381
382
        if (is_null($conversation)) {
383
            $this->Flash->error(__d('conversations', "This conversation doesn't exist or has been deleted."));
384
385
            return $this->redirect(['action' => 'index']);
386
        }
387
388
        $this->loadModel('ConversationsMessages');
389
390
        $this->paginate = [
391
            'maxLimit' => Configure::read('Conversations.messages_per_page')
392
        ];
393
394
        $messages = $this->ConversationsMessages
395
            ->find()
396
            ->contain([
397
                'Users' => function ($q) {
398
                    return $q->find('full')->formatResults(function ($users) {
399
                        return $users->map(function ($user) {
400
                            $user->online = $this->SessionsActivity->getOnlineStatus($user);
401
402
                            return $user;
403
                        });
404
                    });
405
                },
406
                'Users.Groups',
407
                'LastEditUsers' => function ($q) {
408
                    return $q->find('short');
409
                },
410
            ])
411
            ->where([
412
                'ConversationsMessages.conversation_id' => $this->request->id
413
            ])
414
            ->order([
415
                'ConversationsMessages.created' => 'ASC'
416
            ]);
417
418
        $messages = $this->paginate($messages);
419
420
        //Update "is_read" for the current user.
421
        $user = $this->ConversationsUsers->get($conversation->id);
422
        $user->is_read = 1;
423
        $this->ConversationsUsers->save($user);
424
425
        //Current user.
426
        $this->loadModel('Users');
427
        $currentUser = $this->Users
428
            ->find()
429
            ->contain([
430
                'Groups' => function ($q) {
431
                    return $q->select(['id', 'is_staff']);
432
                }
433
            ])
434
            ->where([
435
                'Users.id' => $this->Auth->user('id')
436
            ])
437
            ->select(['id', 'group_id'])
438
            ->first();
439
440
        //Build the newEntity for the comment form.
441
        $messageForm = $this->ConversationsMessages->newEntity();
442
443
        $this->set(compact('conversation', 'messages', 'currentUser', 'messageForm'));
444
    }
445
446
    /**
447
     * Action to search some users when adding an user in a conversation.
448
     *
449
     * @return void
450
     *
451
     * @throws \Cake\Network\Exception\NotFoundException
452
     */
453
    public function inviteMember()
454
    {
455
        if (!$this->request->is('ajax')) {
456
            throw new NotFoundException();
457
        }
458
        $keyword = strtolower($this->request->data['query']);
459
460
        $this->loadModel('Users');
461
        $users = $this->Users
462
            ->find()
463
            ->where(function ($q) use ($keyword) {
464
                    return $q
465
                        ->like('LOWER(Users.username)', "%$keyword%");
466
            })
467
            ->limit(12)
468
            ->toArray();
469
470
        foreach ($users as $user) {
471
            $json[] = h($user->username);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$json was never initialized. Although not strictly required by PHP, it is generally a good practice to add $json = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
472
        }
473
474
        $this->set(compact('json'));
475
        $this->set('_serialize', 'json');
476
    }
477
478
    /**
479
     * Quote a post.
480
     *
481
     * @throws \Cake\Network\Exception\NotFoundException
482
     *
483
     * @return mixed
484
     */
485
    public function quote()
486
    {
487
        if (!$this->request->is('ajax')) {
488
            throw new NotFoundException();
489
        }
490
491
        $this->loadModel('ConversationsMessages');
492
493
        $message = $this->ConversationsMessages
494
            ->find()
495
            ->where([
496
                'ConversationsMessages.id' => $this->request->id
497
            ])
498
            ->contain([
499
                'Users' => function ($q) {
500
                        return $q->find('short');
501
                }
502
            ])
503
            ->first();
504
505
        $json = [];
506
507
        if (!is_null($message)) {
508
            $message->toArray();
509
510
            $url = Router::url(['action' => 'go', $message->id]);
511
            $text = __d('conversations', 'has said :');
512
513
            //Build the quote.
514
            $json['message'] = <<<EOT
515
<div>
516
    <div>
517
        <a href="{$url}">
518
            <strong>{$message->user->full_name} {$text}</strong>
519
        </a>
520
    </div>
521
    <blockquote>
522
        $message->message
523
    </blockquote>
524
</div><p>&nbsp;</p><p>&nbsp;</p>
525
EOT;
526
527
            $json['error'] = false;
528
529
            $this->set(compact('json'));
530
        } else {
531
            $json['post'] = __d('conversations', "This message doesn't exist.");
532
            $json['error'] = true;
533
534
            $this->set(compact('json'));
535
        }
536
537
        //Send response in JSON.
538
        $this->set('_serialize', 'json');
539
    }
540
541
    /**
542
     * Get the form to edit a message.
543
     *
544
     * @throws \Cake\Network\Exception\NotFoundException When it's not an AJAX request.
545
     *
546
     * @return void
547
     */
548
    public function getEditMessage()
549
    {
550
        if (!$this->request->is('ajax')) {
551
            throw new NotFoundException();
552
        }
553
554
        $this->loadModel('ConversationsMessages');
555
        $this->viewBuilder()->layout(false);
556
557
        $message = $this->ConversationsMessages
558
            ->find()
559
            ->where([
560
                'ConversationsMessages.id' => $this->request->data['id']
561
            ])
562
            ->first();
563
564
        $json = [
565
            'error' => false,
566
            'errorMessage' => ''
567
        ];
568
569
        if (is_null($message)) {
570
            $json['error'] = true;
571
            $json['errorMessage'] = __d('conversations', "This message doesn't exist or has been deleted !");
572
573
            $this->set(compact('json'));
574
575
            return;
576
        }
577
578
        //Current user.
579
        $this->loadModel('Users');
580
        $currentUser = $this->Users
581
            ->find()
582
            ->contain([
583
                'Groups' => function ($q) {
584
                    return $q->select(['id', 'is_staff']);
585
                }
586
            ])
587
            ->where([
588
                'Users.id' => $this->Auth->user('id')
589
            ])
590
            ->select(['id', 'group_id'])
591
            ->first();
592
593
        if ($message->user_id != $this->Auth->user('id') && !$currentUser->group->is_staff) {
594
            $json['error'] = true;
595
            $json['errorMessage'] = __d('conversations', "You don't have the authorization to edit this message !");
596
597
            $this->set(compact('json'));
598
599
            return;
600
        }
601
602
        $this->set(compact('json', 'message'));
603
    }
604
605
    /**
606
     * Edit a message.
607
     *
608
     * @param int $id Id of the message.
609
     *
610
     * @return \Cake\Network\Response
611
     */
612
    public function messageEdit($id = null)
613
    {
614
        if (!$this->request->is(['post', 'put'])) {
615
            throw new NotFoundException();
616
        }
617
618
        $this->loadModel('ConversationsMessages');
619
620
        $message = $this->ConversationsMessages
621
            ->find()
622
            ->where([
623
                'ConversationsMessages.id' => $id
624
            ])
625
            ->first();
626
627
        if (is_null($message)) {
628
            $this->Flash->error(__d('conversations', "This post doesn't exist or has been deleted !"));
629
630
            return $this->redirect($this->referer());
631
        }
632
633
        //Current user.
634
        $this->loadModel('Users');
635
        $currentUser = $this->Users
636
            ->find()
637
            ->contain([
638
                'Groups' => function ($q) {
639
                    return $q->select(['id', 'is_staff']);
640
                }
641
            ])
642
            ->where([
643
                'Users.id' => $this->Auth->user('id')
644
            ])
645
            ->select(['id', 'group_id'])
646
            ->first();
647
648
        if ($message->user_id != $this->Auth->user('id') && !$currentUser->group->is_staff) {
649
            $this->Flash->error(__d('conversations', "You don't have the authorization to edit this post !"));
650
651
            return $this->redirect($this->referer());
652
        }
653
654
        $this->ConversationsMessages->patchEntity($message, $this->request->data());
655
        $message->last_edit_date = new Time();
656
        $message->last_edit_user_id = $this->Auth->user('id');
657
        $message->edit_count++;
658
659
        if ($this->ConversationsMessages->save($message)) {
660
            $this->Flash->success(__d('conversations', 'This message has been edited successfully !'));
661
        }
662
663
        return $this->redirect(['action' => 'go', $message->id]);
664
    }
665
666
    /**
667
     * Redirect an user to a conversation, page and message.
668
     *
669
     * @param int $messageId Id of the message.
670
     *
671
     * @return \Cake\Network\Response
672
     */
673 View Code Duplication
    public function go($messageId = null)
674
    {
675
        $this->loadModel('ConversationsMessages');
676
677
        $message = $this->ConversationsMessages
678
            ->find()
679
            ->contain([
680
                'Conversations'
681
            ])
682
            ->where([
683
                'ConversationsMessages.id' => $messageId
684
            ])
685
            ->first();
686
687
        if (is_null($message)) {
688
            $this->Flash->error(__d('conversations', "This message doesn't exist or has been deleted."));
689
690
            return $this->redirect(['controller' => 'conversations', 'action' => 'index']);
691
        }
692
693
        $message->toArray();
694
695
        //Count the number of messages before this message.
696
        $messagesBefore = $this->ConversationsMessages
697
            ->find()
698
            ->where([
699
                'ConversationsMessages.conversation_id' => $message->conversation_id,
700
                'ConversationsMessages.created <' => $message->created
701
            ])
702
            ->count();
703
704
        //Get the number of messages per page.
705
        $messagesPerPage = Configure::read('Conversations.messages_per_page');
706
707
        //Calculate the page.
708
        $page = ceil($messagesBefore / $messagesPerPage);
709
710
        $page = ($page > 1) ? $page : 1;
711
712
        //Redirect the user.
713
        return $this->redirect([
714
            '_name' => 'conversations-view',
715
            'slug' => $message->conversation->title,
716
            'id' => $message->conversation->id,
717
            '?' => ['page' => $page],
718
            '#' => 'message-' . $messageId
719
        ]);
720
    }
721
722
    /**
723
     * Function to kick an user from a conversation.
724
     *
725
     * @return void
726
     */
727
    public function kick()
728
    {
729
        if (!$this->request->is('ajax')) {
730
            throw new NotFoundException();
731
        }
732
733
        $this->loadModel('ConversationsUsers');
734
735
        $currentUser = $this->ConversationsUsers
736
            ->find()
737
            ->contain([
738
                'Conversations',
739
                'Users' => function ($q) {
740
                    return $q->find('short');
741
                },
742
                'Users.Groups' => function ($q) {
743
                    return $q->select(['id', 'is_staff']);
744
                }
745
            ])
746
            ->where([
747
                'ConversationsUsers.user_id' => $this->Auth->user('id'),
748
                'ConversationsUsers.conversation_id' => $this->request->id
749
            ])
750
            ->first();
751
752
        //Check if the current user is the owner of this conversation or if he is not a staff member.
753
        if ($currentUser->user_id != $currentUser->conversation->user_id && !$currentUser->user->group->is_staff) {
754
            $json['message'] = __d('conversations', 'You cannot kick this user from this conversation.');
0 ignored issues
show
Coding Style Comprehensibility introduced by
$json was never initialized. Although not strictly required by PHP, it is generally a good practice to add $json = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
755
            $json['error'] = true;
756
757
            $this->set(compact('json'));
758
            $this->set('_serialize', 'json');
759
760
            return;
761
        }
762
763
        $user = $this->ConversationsUsers
764
            ->find()
765
            ->contain([
766
                'Conversations',
767
                'Users' => function ($q) {
768
                    return $q->find('short');
769
                },
770
                'Users.Groups' => function ($q) {
771
                    return $q->select(['id', 'is_staff']);
772
                }
773
            ])
774
            ->where([
775
                'ConversationsUsers.user_id' => $this->request->user_id,
776
                'ConversationsUsers.conversation_id' => $this->request->id
777
            ])
778
            ->first();
779
780
        //Check if the user to kick is in the conversation and if he is not owner of this conversation and if he is not a staff member.
781
        if (is_null($user) || $this->request->user_id == $currentUser->conversation->user_id || $user->user->group->is_staff) {
782
            $json['message'] = __d('conversations', 'You cannot kick this user from this conversation.');
0 ignored issues
show
Coding Style Comprehensibility introduced by
$json was never initialized. Although not strictly required by PHP, it is generally a good practice to add $json = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
783
            $json['error'] = true;
784
785
            $this->set(compact('json'));
786
            $this->set('_serialize', 'json');
787
788
            return;
789
        }
790
791
        $this->ConversationsUsers->delete($user);
792
793
        $expression = new QueryExpression('recipient_count = recipient_count - 1');
794
        $this->Conversations->updateAll(
795
            [$expression],
796
            [
797
                'id' => $this->request->id
798
            ]
799
        );
800
801
        $json['message'] = __d('conversations', 'This user has been kicked successfully.');
0 ignored issues
show
Coding Style Comprehensibility introduced by
$json was never initialized. Although not strictly required by PHP, it is generally a good practice to add $json = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
802
        $json['error'] = false;
803
        $json['id'] = $this->request->user_id;
804
        $json['recipients'] = $currentUser->conversation->recipient_count - 1;
805
806
        $this->set(compact('json'));
807
        $this->set('_serialize', 'json');
808
    }
809
810
    /**
811
     * Reply to a conversation.
812
     *
813
     * @return void|\Cake\Network\Response
814
     */
815
    public function reply()
816
    {
817
        $this->loadModel('ConversationsMessages');
818
819
        if ($this->request->is('post')) {
820
            $conversation = $this->Conversations
821
                ->find()
822
                ->where(['Conversations.id' => $this->request->id])
823
                ->first();
824
825
            $this->loadModel('ConversationsUsers');
826
            $user = $this->ConversationsUsers
827
                ->find()
828
                ->where([
829
                    'ConversationsUsers.conversation_id' => $this->request->id,
830
                    'ConversationsUsers.user_id' => $this->Auth->user('id')
831
                ])
832
                ->first();
833
834
            //Check if the conversation is found.
835
            if (is_null($user) || is_null($conversation) || $conversation->conversation_open == 2) {
836
                $this->Flash->error(__d('conversations', "This conversation doesn't exist or has been deleted !"));
837
838
                return $this->redirect($this->referer());
839
            }
840
841
            //Check if the conversation is open.
842 View Code Duplication
            if ($conversation->conversation_open == false) {
843
                $this->Flash->error(__d('conversations', 'This conversation is closed, you cannot reply.'));
844
845
                return $this->redirect($this->referer());
846
            }
847
848
            //Build the newEntity for the post form.
849
            $this->request->data['conversation']['id'] = $this->request->id;
850
            $this->request->data['conversation']['last_post_date'] = new Time();
851
            $this->request->data['conversation']['last_post_user_id'] = $this->Auth->user('id');
852
            $this->request->data['user_id'] = $this->Auth->user('id');
853
            $this->request->data['conversation_id'] = $this->request->id;
854
855
            $message = $this->ConversationsMessages->newEntity($this->request->data, [
856
                'associated' => ['Conversations'],
857
                'validate' => 'create'
858
            ]);
859
860
            //Handle validation errors (Due to the redirect)
861
            if (!empty($message->errors())) {
862
                $this->Flash->conversationsReply('Validation errors', [
863
                    'key' => 'ConversationsReply',
864
                    'params' => [
865
                        'errors' => $message->errors()
866
                    ]
867
                ]);
868
869
                return $this->redirect($this->referer());
870
            }
871
872
            if ($message->conversation->isNew() === true) {
873
                $message->conversation->isNew(false);
874
            }
875
876
            if ($message = $this->ConversationsMessages->save($message)) {
877
                //Update the last message id for the conversation.
878
                $this->loadModel('Conversations');
879
                $conversation = $this->Conversations->get($this->request->id);
880
                $conversation->last_message_id = $message->id;
881
                $conversation->last_message_date = new Time();
882
                $conversation->last_message_user_id = $this->Auth->user('id');
883
                $this->Conversations->save($conversation);
884
885
                //Notifications Event.
886
                $this->eventManager()->attach(new Notifications());
887
                $event = new Event('Model.Notifications.dispatch', $this, [
888
                    'sender_id' => $this->Auth->user('id'),
889
                    'conversation_id' => $conversation->id,
890
                    'type' => 'conversation.reply'
891
                ]);
892
                $this->eventManager()->dispatch($event);
893
894
                $conversationOpen = isset($this->request->data['conversation']['conversation_open']) ? $this->request->data['conversation']['conversation_open'] : true;
895
896
                if ($conversationOpen == false) {
897
                    $this->Flash->success(__d('conversations', 'Your reply has been posted successfully and the conversation has been closed !'));
898
                } else {
899
                    $this->Flash->success(__d('conversations', 'Your reply has been posted successfully !'));
900
                }
901
902
                //Redirect the user to the last page of the article.
903
                return $this->redirect([
904
                    'controller' => 'conversations',
905
                    'action' => 'go',
906
                    $message->id
907
                ]);
908
            }
909
        }
910
911
        $this->redirect($this->referer());
912
    }
913
914
    /**
915
     * Edit a conversation.
916
     *
917
     * @return \Cake\Network\Response
918
     */
919
    public function edit()
920
    {
921
        $this->loadModel('Conversations');
922
923
        if ($this->request->is('put')) {
924
            $conversation = $this->Conversations
925
                ->find()
926
                ->where([
927
                    'Conversations.id' => $this->request->id
928
                ])
929
                ->first();
930
931
            //Check if the conversation is found.
932 View Code Duplication
            if (is_null($conversation)) {
933
                $this->Flash->error(__d('conversations', "This conversation doesn't exist or has been deleted !"));
934
935
                return $this->redirect($this->referer());
936
            }
937
938
            //Check if the user has the permission to edit it.
939 View Code Duplication
            if ($this->Auth->isAuthorized() === false) {
940
                $this->Flash->error(__d('conversations', "You don't have the authorization to edit this conversation !"));
941
942
                return $this->redirect([
943
                    'controller' => 'conversations',
944
                    'action' => 'go',
945
                    $conversation->last_message_id
946
                ]);
947
            }
948
949
950
            $this->Conversations->patchEntity($conversation, $this->request->data, ['validate' => 'edit']);
951
952
            if ($this->Conversations->save($conversation)) {
953
                if ($conversation->conversation_open == false) {
954
                    $this->Flash->success(__d('conversations', 'Your conversation has been edited and closed successfully !'));
955
                } else {
956
                    $this->Flash->success(__d('conversations', 'Your conversation has been edited successfully !'));
957
                }
958
959
                return $this->redirect([
960
                    'controller' => 'conversations',
961
                    'action' => 'go',
962
                    $conversation->last_message_id
963
                ]);
964
            }
965
        }
966
967
        $this->redirect($this->referer());
968
    }
969
970
    /**
971
     * Function to invite user(s) in a conversation.
972
     *
973
     * @return void|\Cake\Network\Response
974
     */
975
    public function invite()
976
    {
977
        $this->loadModel('ConversationsUsers');
978
979
        $conversation = $this->ConversationsUsers
980
            ->find()
981
            ->contain([
982
                'Conversations',
983
                'Users',
984
                'Users.Groups'
985
            ])
986
            ->where([
987
                'ConversationsUsers.conversation_id' => $this->request->id,
988
                'ConversationsUsers.user_id' => $this->Auth->user('id')
989
            ])
990
            ->first();
991
992 View Code Duplication
        if (is_null($conversation) || $conversation->conversation->conversation_open != 1) {
993
            $this->Flash->error(__d('conversations', 'This conversation is closed or has been deleted !'));
994
995
            return $this->redirect($this->referer());
996
        }
997
998
        if (!$conversation->conversation->open_invite && $conversation->conversation->user_id != $this->Auth->user('id') && !$conversation->user->group->is_staff) {
999
            $this->Flash->error(__d('conversations', "You don't have the authorization to invite in this conversation !"));
1000
1001
            return $this->redirect($this->referer());
1002
        }
1003
1004
        if ($this->request->is(['post', 'put'])) {
1005
            $users = str_replace(",", "", trim(strtolower($this->request->data['users'])));
1006
            $users = explode(" ", $users);
1007
1008
            $maxUsersCheck = $this->ConversationsUsers
1009
                ->find()
1010
                ->where([
1011
                    'ConversationsUsers.conversation_id' => $this->request->id
1012
                ])
1013
                ->count();
1014
1015
            //Check max users.
1016
            if (count($users) + $maxUsersCheck >= Configure::read('Conversations.max_users_per_conversation')) {
1017
                $this->Flash->error(__d('conversations', 'You cannot invite more than {0} user(s) in this conversation.', Configure::read('Conversations.max_users_per_conversation')));
1018
1019
                return $this->redirect($this->referer());
1020
            }
1021
1022
            $this->loadModel('Users');
1023
            $this->loadModel('Conversations');
1024
1025
            foreach ($users as $user) {
1026
                $user = $this->Users
1027
                    ->find()
1028
                    ->where([
1029
                        'LOWER(Users.username)' => $user
1030
                    ])
1031
                    ->first();
1032
1033
                if (!is_null($user)) {
1034
                    $check = $this->ConversationsUsers
1035
                        ->find()
1036
                        ->where([
1037
                            'ConversationsUsers.conversation_id' => $this->request->id,
1038
                            'ConversationsUsers.user_id' => $user->id
1039
                        ])
1040
                        ->first();
1041
1042
                    if (is_null($check)) {
1043
                        $data = [];
1044
                        $data['conversation_id'] = $this->request->id;
1045
                        $data['user_id'] = $user->id;
1046
1047
                        $entity = $this->ConversationsUsers->newEntity($data);
1048
                        $this->ConversationsUsers->save($entity);
1049
1050
                        $expression = new QueryExpression('recipient_count = recipient_count + 1');
1051
                        $this->Conversations->updateAll(
1052
                            [$expression],
1053
                            [
1054
                                'id' => $this->request->id
1055
                            ]
1056
                        );
1057
                    }
1058
                }
1059
            }
1060
1061
            $this->Flash->success(__d('conversations', 'Your user(s) has been added successfully.'));
1062
        }
1063
1064
        return $this->redirect([
1065
            'controller' => 'conversations',
1066
            'action' => 'go',
1067
            $conversation->conversation->last_message_id
1068
        ]);
1069
    }
1070
1071
    /**
1072
     * Function to leave a conversation.
1073
     *
1074
     * @return void|\Cake\Network\Response
1075
     */
1076
    public function leave()
1077
    {
1078
        $this->loadModel('ConversationsUsers');
1079
1080
        $user = $this->ConversationsUsers
1081
            ->find()
1082
            ->contain([
1083
                'Conversations'
1084
            ])
1085
            ->where([
1086
                'ConversationsUsers.conversation_id' => $this->request->id,
1087
                'ConversationsUsers.user_id' => $this->Auth->user('id')
1088
            ])
1089
            ->first();
1090
1091
        if (is_null($user)) {
1092
            $this->Flash->error(__d('conversations', 'You are not in this conversation.'));
1093
1094
            return $this->redirect($this->referer());
1095
        }
1096
1097
        if ($user->conversation->user_id != $this->Auth->user('id')) {
1098
            $this->loadModel('Conversations');
1099
1100
            $this->ConversationsUsers->delete($user);
1101
1102
            $expression = new QueryExpression('recipient_count = recipient_count - 1');
1103
            $this->Conversations->updateAll(
1104
                [$expression],
1105
                [
1106
                    'id' => $this->request->id
1107
                ]
1108
            );
1109
1110
            $this->Flash->success(__d('conversations', 'You have left the conversation successfully.'));
1111
1112
            return $this->redirect(['controller' => 'conversations', 'action' => 'index']);
1113 View Code Duplication
        } else {
1114
            $this->Flash->error(__d('conversations', 'You can not leave your own conversation.'));
1115
1116
            return $this->redirect([
1117
                'controller' => 'conversations',
1118
                'action' => 'go',
1119
                $user->conversation->last_message_id
1120
            ]);
1121
        }
1122
    }
1123
1124
    /**
1125
     * Search conversations.
1126
     *
1127
     * @return void
1128
     */
1129
    public function search()
1130
    {
1131
        $this->loadModel('ConversationsUsers');
1132
1133
        //Check the keyword to search. (For pagination)
1134 View Code Duplication
        if (!empty($this->request->data['search'])) {
1135
            $keyword = $this->request->data['search'];
1136
            $this->request->session()->write('Search.Conversations.Keyword', $keyword);
1137
        } else {
1138
            if ($this->request->session()->read('Search.Conversations.Keyword')) {
1139
                $keyword = $this->request->session()->read('Search.Conversations.Keyword');
1140
            } else {
1141
                $keyword = '';
1142
            }
1143
        }
1144
1145
        //Pagination
1146
        $this->paginate = [
1147
            'maxLimit' => Configure::read('Conversations.conversations_per_page')
1148
        ];
1149
1150
        $conversations = $this->ConversationsUsers
1151
            ->find()
1152
            ->contain([
1153
                'Users',
1154
                'Conversations',
1155
                'Conversations.Users' => function ($q) {
1156
                    return $q->find('medium');
1157
                },
1158
                'Conversations.LastMessage',
1159
                'Conversations.LastMessageUser'
1160
            ])
1161
            ->where([
1162
                'ConversationsUsers.user_id' => $this->Auth->user('id'),
1163
                'Conversations.conversation_open <>' => 2
1164
            ])
1165
            ->andWhere(function ($q) use ($keyword) {
1166
                    return $q
1167
                        ->like('Conversations.title', "%$keyword%");
1168
            })
1169
            ->order([
1170
                'ConversationsUsers.is_read' => 'ASC',
1171
                'ConversationsUsers.is_star' => 'DESC',
1172
                'Conversations.last_message_date' => 'DESC',
1173
            ]);
1174
1175
        $conversations = $this->paginate($conversations);
1176
1177
        $this->set(compact('conversations', 'keyword'));
1178
    }
1179
1180
    /**
1181
     * Action to rendre the maintenance page.
1182
     *
1183
     * @return void
1184
     */
1185
    public function maintenance()
1186
    {
1187
    }
1188
}
1189