Passed
Push — master ( e717c7...e31763 )
by
unknown
08:28 queued 13s
created

TicketManager::insertMessage()   B

Complexity

Conditions 8
Paths 12

Size

Total Lines 75
Code Lines 44

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 44
nc 12
nop 7
dl 0
loc 75
rs 7.9715
c 0
b 0
f 0

How to fix   Long Method   

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
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\Ticket;
6
use Chamilo\CoreBundle\Entity\TicketMessage;
7
use Chamilo\CoreBundle\Entity\TicketMessageAttachment;
8
use Chamilo\CoreBundle\Entity\TicketPriority;
9
use Chamilo\CoreBundle\Entity\TicketProject;
10
use Chamilo\CoreBundle\Entity\TicketRelUser;
11
use Chamilo\CoreBundle\Entity\TicketStatus;
12
use Chamilo\CoreBundle\Entity\User;
13
use Chamilo\CoreBundle\Entity\ValidationToken;
14
use Chamilo\CoreBundle\Framework\Container;
15
use Chamilo\CoreBundle\ServiceHelper\ValidationTokenHelper;
16
use Chamilo\CourseBundle\Entity\CLp;
17
use Symfony\Component\HttpFoundation\File\UploadedFile;
18
use Chamilo\CoreBundle\Component\Utils\ObjectIcon;
19
use Chamilo\CoreBundle\Component\Utils\StateIcon;
20
21
/**
22
 * Class TicketManager.
23
 */
24
class TicketManager
25
{
26
    public const PRIORITY_NORMAL = 'NRM';
27
    public const PRIORITY_HIGH = 'HGH';
28
    public const PRIORITY_LOW = 'LOW';
29
30
    public const SOURCE_EMAIL = 'MAI';
31
    public const SOURCE_PHONE = 'TEL';
32
    public const SOURCE_PLATFORM = 'PLA';
33
    public const SOURCE_PRESENTIAL = 'PRE';
34
35
    public const STATUS_NEW = 'NAT';
36
    public const STATUS_PENDING = 'PND';
37
    public const STATUS_UNCONFIRMED = 'XCF';
38
    public const STATUS_CLOSE = 'CLS';
39
    public const STATUS_FORWARDED = 'REE';
40
41
    public function __construct()
42
    {
43
    }
44
45
    /**
46
     * Get categories of tickets.
47
     *
48
     * @param int    $projectId
49
     * @param string $order
50
     *
51
     * @return array
52
     */
53
    public static function get_all_tickets_categories($projectId, $order = '')
54
    {
55
        $table_support_category = Database::get_main_table(TABLE_TICKET_CATEGORY);
56
        $table_support_project = Database::get_main_table(TABLE_TICKET_PROJECT);
57
58
        $order = empty($order) ? 'category.total_tickets DESC' : $order;
59
        $order = Database::escape_string($order);
60
        $projectId = (int) $projectId;
61
62
        $sql = "SELECT
63
                    category.*,
64
                    category.id category_id,
65
                    project.other_area,
66
                    project.email
67
                FROM
68
                $table_support_category category
69
                INNER JOIN $table_support_project project
70
                ON project.id = category.project_id
71
                WHERE project.id  = $projectId
72
                ORDER BY $order";
73
        $result = Database::query($sql);
74
        $types = [];
75
        while ($row = Database::fetch_assoc($result)) {
76
            $types[] = $row;
77
        }
78
79
        return $types;
80
    }
81
82
    /**
83
     * @param $from
84
     * @param $numberItems
85
     * @param $column
86
     * @param $direction
87
     *
88
     * @return array
89
     */
90
    public static function getCategories($from, $numberItems, $column, $direction)
91
    {
92
        $table = Database::get_main_table(TABLE_TICKET_CATEGORY);
93
        $sql = "SELECT id, title, description, total_tickets
94
                FROM $table";
95
96
        if (!in_array($direction, ['ASC', 'DESC'])) {
97
            $direction = 'ASC';
98
        }
99
        $column = (int) $column;
100
        $from = (int) $from;
101
        $numberItems = (int) $numberItems;
102
103
        //$sql .= " ORDER BY col$column $direction ";
104
        $sql .= " LIMIT $from,$numberItems";
105
106
        $result = Database::query($sql);
107
        $types = [];
108
        while ($row = Database::fetch_array($result)) {
109
            $types[] = $row;
110
        }
111
112
        return $types;
113
    }
114
115
    /**
116
     * @param int $id
117
     *
118
     * @return array|mixed
119
     */
120
    public static function getCategory($id)
121
    {
122
        $table = Database::get_main_table(TABLE_TICKET_CATEGORY);
123
        $id = (int) $id;
124
        $sql = "SELECT id, title, description, total_tickets
125
                FROM $table WHERE id = $id";
126
127
        $result = Database::query($sql);
128
        $category = Database::fetch_array($result);
129
130
        return $category;
131
    }
132
133
    /**
134
     * @return int
135
     */
136
    public static function getCategoriesCount()
137
    {
138
        $table = Database::get_main_table(TABLE_TICKET_CATEGORY);
139
140
        $sql = "SELECT count(id) count
141
                FROM $table ";
142
143
        $result = Database::query($sql);
144
        $category = Database::fetch_array($result);
145
146
        return $category['count'];
147
    }
148
149
    /**
150
     * @param int   $id
151
     * @param array $params
152
     */
153
    public static function updateCategory($id, $params)
154
    {
155
        $table = Database::get_main_table(TABLE_TICKET_CATEGORY);
156
        $id = (int) $id;
157
        Database::update($table, $params, ['id = ?' => $id]);
158
    }
159
160
    /**
161
     * @param array $params
162
     */
163
    public static function addCategory($params)
164
    {
165
        $table = Database::get_main_table(TABLE_TICKET_CATEGORY);
166
        Database::insert($table, $params);
167
    }
168
169
    /**
170
     * @param int $id
171
     *
172
     * @return bool
173
     */
174
    public static function deleteCategory($id)
175
    {
176
        $id = (int) $id;
177
        if (empty($id)) {
178
            return false;
179
        }
180
181
        $table = Database::get_main_table(TABLE_TICKET_TICKET);
182
        $sql = "UPDATE $table SET category_id = NULL WHERE category_id = $id";
183
        Database::query($sql);
184
185
        $table = Database::get_main_table(TABLE_TICKET_CATEGORY);
186
        $sql = "DELETE FROM $table WHERE id = $id";
187
        Database::query($sql);
188
189
        return true;
190
    }
191
192
    /**
193
     * @param int   $categoryId
194
     * @param array $users
195
     *
196
     * @return bool
197
     */
198
    public static function addUsersToCategory($categoryId, $users)
199
    {
200
        if (empty($users) || empty($categoryId)) {
201
            return false;
202
        }
203
204
        $table = Database::get_main_table(TABLE_TICKET_CATEGORY_REL_USER);
205
        foreach ($users as $userId) {
206
            if (false === self::userIsAssignedToCategory($userId, $categoryId)) {
207
                $params = [
208
                    'category_id' => $categoryId,
209
                    'user_id' => $userId,
210
                ];
211
                Database::insert($table, $params);
212
            }
213
        }
214
215
        return true;
216
    }
217
218
    /**
219
     * @param int $userId
220
     * @param int $categoryId
221
     *
222
     * @return bool
223
     */
224
    public static function userIsAssignedToCategory($userId, $categoryId)
225
    {
226
        $table = Database::get_main_table(TABLE_TICKET_CATEGORY_REL_USER);
227
        $userId = (int) $userId;
228
        $categoryId = (int) $categoryId;
229
        $sql = "SELECT * FROM $table
230
                WHERE category_id = $categoryId AND user_id = $userId";
231
        $result = Database::query($sql);
232
233
        return Database::num_rows($result) > 0;
234
    }
235
236
    /**
237
     * @param int $categoryId
238
     *
239
     * @return array
240
     */
241
    public static function getUsersInCategory($categoryId)
242
    {
243
        $table = Database::get_main_table(TABLE_TICKET_CATEGORY_REL_USER);
244
        $categoryId = (int) $categoryId;
245
        $sql = "SELECT * FROM $table WHERE category_id = $categoryId";
246
        $result = Database::query($sql);
247
248
        return Database::store_result($result);
249
    }
250
251
    /**
252
     * @param int $categoryId
253
     */
254
    public static function deleteAllUserInCategory($categoryId)
255
    {
256
        $table = Database::get_main_table(TABLE_TICKET_CATEGORY_REL_USER);
257
        $categoryId = (int) $categoryId;
258
        $sql = "DELETE FROM $table WHERE category_id = $categoryId";
259
        Database::query($sql);
260
    }
261
262
    /**
263
     * Get all possible tickets statuses.
264
     *
265
     * @return array
266
     */
267
    public static function get_all_tickets_status()
268
    {
269
        $table = Database::get_main_table(TABLE_TICKET_STATUS);
270
        $sql = "SELECT * FROM $table";
271
        $result = Database::query($sql);
272
        $types = [];
273
        while ($row = Database::fetch_assoc($result)) {
274
            $types[] = $row;
275
        }
276
277
        return $types;
278
    }
279
280
    /**
281
     * Inserts a new ticket in the corresponding tables.
282
     *
283
     * @param int      $category_id
284
     * @param int      $course_id
285
     * @param int      $sessionId
286
     * @param int      $project_id
287
     * @param string   $other_area
288
     * @param string   $subject
289
     * @param string   $content
290
     * @param string   $personalEmail
291
     * @param array    $fileAttachments
292
     * @param string   $source
293
     * @param string   $priority
294
     * @param string   $status
295
     * @param int|null $assignedUserId
296
     * @param int      $exerciseId
297
     * @param int      $lpId
298
     *
299
     * @return bool
300
     */
301
    public static function add(
302
        $category_id,
303
        $course_id,
304
        $sessionId,
305
        $project_id,
306
        $other_area,
307
        $subject,
308
        $content,
309
        $personalEmail = '',
310
        $fileAttachments = [],
311
        $source = '',
312
        $priority = '',
313
        $status = '',
314
        $assignedUserId = null,
315
        $exerciseId = null,
316
        $lpId = null
317
    ) {
318
        $table_support_tickets = Database::get_main_table(TABLE_TICKET_TICKET);
319
        $table_support_category = Database::get_main_table(TABLE_TICKET_CATEGORY);
320
321
        if (empty($category_id)) {
322
            return false;
323
        }
324
325
        $currentUserId = api_get_user_id();
326
        $currentUserInfo = api_get_user_info();
327
        $now = api_get_utc_datetime();
328
        $course_id = (int) $course_id;
329
        $category_id = (int) $category_id;
330
        $project_id = (int) $project_id;
331
        $priority = empty($priority) ? self::PRIORITY_NORMAL : (int) $priority;
332
333
        if ('' === $status) {
334
            $status = self::STATUS_NEW;
335
            if ($other_area > 0) {
336
                $status = self::STATUS_FORWARDED;
337
            }
338
        }
339
340
        if (empty($assignedUserId)) {
341
            $usersInCategory = self::getUsersInCategory($category_id);
342
            if (!empty($usersInCategory) && count($usersInCategory) > 0) {
343
                $userCategoryInfo = $usersInCategory[0];
344
                if (isset($userCategoryInfo['user_id'])) {
345
                    $assignedUserId = $userCategoryInfo['user_id'];
346
                }
347
            }
348
        }
349
350
        $assignedUserInfo = [];
351
        if (!empty($assignedUserId)) {
352
            $assignedUserInfo = api_get_user_info($assignedUserId);
353
            if (empty($assignedUserInfo)) {
354
                return false;
355
            }
356
        }
357
358
        // insert_ticket
359
        $params = [
360
            'project_id' => $project_id,
361
            'category_id' => $category_id,
362
            'priority_id' => $priority,
363
            'personal_email' => $personalEmail,
364
            'status_id' => $status,
365
            'start_date' => $now,
366
            'sys_insert_user_id' => $currentUserId,
367
            'sys_insert_datetime' => $now,
368
            'sys_lastedit_user_id' => $currentUserId,
369
            'sys_lastedit_datetime' => $now,
370
            'source' => $source,
371
            'assigned_last_user' => $assignedUserId,
372
            'subject' => $subject,
373
            'message' => $content,
374
            'code' => '',
375
            'total_messages' => 0,
376
        ];
377
378
        if (!empty($exerciseId)) {
379
            $params['exercise_id'] = $exerciseId;
380
        }
381
382
        if (!empty($lpId)) {
383
            $params['lp_id'] = $lpId;
384
        }
385
        if (!empty($course_id)) {
386
            $params['course_id'] = $course_id;
387
        }
388
389
        if (!empty($sessionId)) {
390
            $params['session_id'] = $sessionId;
391
        }
392
        $ticketId = Database::insert($table_support_tickets, $params);
393
394
        if ($ticketId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $ticketId of type false|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
395
            $ticket_code = 'A'.str_pad($ticketId, 11, '0', STR_PAD_LEFT);
396
            $titleCreated = sprintf(
397
                get_lang('Ticket %s created'),
398
                $ticket_code
399
            );
400
401
            Display::addFlash(Display::return_message(
402
                $titleCreated,
403
                'normal',
404
                false
405
            ));
406
407
            if (0 != $assignedUserId) {
408
                self::assignTicketToUser(
409
                    $ticketId,
410
                    $assignedUserId
411
                );
412
413
                Display::addFlash(Display::return_message(
414
                    sprintf(
415
                        get_lang('Ticket <b>#%s</b> assigned to user <b>%s</b>'),
416
                        $ticket_code,
417
                        $assignedUserInfo['complete_name']
418
                    ),
419
                    'normal',
420
                    false
421
                ));
422
            }
423
424
            if (!empty($fileAttachments)) {
425
                $attachmentCount = 0;
426
                foreach ($fileAttachments as $attach) {
427
                    if (!empty($attach['tmp_name'])) {
428
                        $attachmentCount++;
429
                    }
430
                }
431
                if ($attachmentCount > 0) {
432
                    self::insertMessage(
433
                        $ticketId,
434
                        '',
435
                        '',
436
                        $fileAttachments,
437
                        $currentUserId
438
                    );
439
                }
440
            }
441
442
            // Update code
443
            $sql = "UPDATE $table_support_tickets
444
                    SET code = '$ticket_code'
445
                    WHERE id = '$ticketId'";
446
            Database::query($sql);
447
448
            // Update total
449
            $sql = "UPDATE $table_support_category
450
                    SET total_tickets = total_tickets + 1
451
                    WHERE id = $category_id";
452
            Database::query($sql);
453
454
            $helpDeskMessage =
455
                '<table>
456
                        <tr>
457
                            <td width="100px"><b>'.get_lang('User').'</b></td>
458
                            <td width="400px">'.$currentUserInfo['complete_name'].'</td>
459
                        </tr>
460
                        <tr>
461
                            <td width="100px"><b>'.get_lang('Username').'</b></td>
462
                            <td width="400px">'.$currentUserInfo['username'].'</td>
463
                        </tr>
464
                        <tr>
465
                            <td width="100px"><b>'.get_lang('Email').'</b></td>
466
                            <td width="400px">'.$currentUserInfo['email'].'</td>
467
                        </tr>
468
                        <tr>
469
                            <td width="100px"><b>'.get_lang('Phone').'</b></td>
470
                            <td width="400px">'.$currentUserInfo['phone'].'</td>
471
                        </tr>
472
                        <tr>
473
                            <td width="100px"><b>'.get_lang('Date').'</b></td>
474
                            <td width="400px">'.api_convert_and_format_date($now, DATE_TIME_FORMAT_LONG).'</td>
475
                        </tr>
476
                        <tr>
477
                            <td width="100px"><b>'.get_lang('Title').'</b></td>
478
                            <td width="400px">'.Security::remove_XSS($subject).'</td>
0 ignored issues
show
Bug introduced by
Are you sure Security::remove_XSS($subject) of type array|string can be used in concatenation? ( Ignorable by Annotation )

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

478
                            <td width="400px">'./** @scrutinizer ignore-type */ Security::remove_XSS($subject).'</td>
Loading history...
479
                        </tr>
480
                        <tr>
481
                            <td width="100px"><b>'.get_lang('Description').'</b></td>
482
                            <td width="400px">'.Security::remove_XSS($content).'</td>
0 ignored issues
show
Bug introduced by
Are you sure Security::remove_XSS($content) of type array|string can be used in concatenation? ( Ignorable by Annotation )

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

482
                            <td width="400px">'./** @scrutinizer ignore-type */ Security::remove_XSS($content).'</td>
Loading history...
483
                        </tr>
484
                    </table>';
485
486
            if (0 != $assignedUserId) {
487
                $href = api_get_path(WEB_CODE_PATH).'ticket/ticket_details.php?ticket_id='.$ticketId;
488
                $helpDeskMessage .= sprintf(
489
                    get_lang("Ticket assigned to %s. Follow-up at <a href='%s'>#%s</a>."),
490
                    $assignedUserInfo['complete_name'],
491
                    $href,
492
                    $ticketId
493
                );
494
            }
495
496
            if (empty($category_id)) {
497
                if ('true' === api_get_setting('ticket_send_warning_to_all_admins')) {
498
                    $warningSubject = sprintf(
499
                        get_lang('Ticket %s was created without a category'),
500
                        $ticket_code
501
                    );
502
                    Display::addFlash(Display::return_message($warningSubject));
503
504
                    $admins = UserManager::get_all_administrators();
505
                    foreach ($admins as $userId => $data) {
506
                        if ($data['active']) {
507
                            MessageManager::send_message_simple(
508
                                $userId,
509
                                $warningSubject,
510
                                $helpDeskMessage
511
                            );
512
                        }
513
                    }
514
                }
515
            } else {
516
                $categoryInfo = self::getCategory($category_id);
517
                $usersInCategory = self::getUsersInCategory($category_id);
518
                $message = '<h2>'.get_lang('Ticket info').'</h2><br />'.$helpDeskMessage;
519
520
                if ('true' === api_get_setting('ticket_warn_admin_no_user_in_category')) {
521
                    $usersInCategory = self::getUsersInCategory($category_id);
522
                    if (empty($usersInCategory)) {
523
                        $subject = sprintf(
524
                            get_lang('Warning: No one has been assigned to category %s'),
525
                            $categoryInfo['title']
526
                        );
527
528
                        if ('true' === api_get_setting('ticket_send_warning_to_all_admins')) {
529
                            Display::addFlash(Display::return_message(
530
                                sprintf(
531
                                    get_lang(
532
                                        'A notification was sent to the administrators to report this category has no user assigned'
533
                                    ),
534
                                    $categoryInfo['title']
535
                                ),
536
                                null,
537
                                false
538
                            ));
539
540
                            $admins = UserManager::get_all_administrators();
541
                            foreach ($admins as $userId => $data) {
542
                                if ($data['active']) {
543
                                    self::sendNotification(
544
                                        $ticketId,
545
                                        $subject,
546
                                        $message,
547
                                        $userId
548
                                    );
549
                                }
550
                            }
551
                        } else {
552
                            Display::addFlash(Display::return_message($subject));
553
                        }
554
                    }
555
                }
556
557
                // Send notification to all users
558
                if (!empty($usersInCategory)) {
559
                    foreach ($usersInCategory as $data) {
560
                        if ($data['user_id']) {
561
                            self::sendNotification(
562
                                $ticketId,
563
                                $subject,
564
                                $message,
565
                                $data['user_id']
566
                            );
567
                        }
568
                    }
569
                }
570
            }
571
572
            if (!empty($personalEmail)) {
573
                api_mail_html(
574
                    get_lang('Virtual support'),
575
                    $personalEmail,
576
                    get_lang('The incident has been sent to the virtual support team again'),
577
                    $helpDeskMessage
578
                );
579
            }
580
581
            self::sendNotification(
582
                $ticketId,
583
                $titleCreated,
584
                $helpDeskMessage
585
            );
586
587
            return true;
588
        }
589
590
        return false;
591
    }
592
593
    /**
594
     * Assign ticket to admin.
595
     *
596
     * @param int $ticketId
597
     * @param int $userId
598
     *
599
     * @return bool
600
     */
601
    public static function assignTicketToUser(
602
        $ticketId,
603
        $userId
604
    ) {
605
        $ticketId = (int) $ticketId;
606
        $userId = (int) $userId;
607
608
        if (empty($ticketId)) {
609
            return false;
610
        }
611
612
        $ticket = self::get_ticket_detail_by_id($ticketId);
613
614
        if ($ticket) {
615
            $table = Database::get_main_table(TABLE_TICKET_TICKET);
616
            $sql = "UPDATE $table
617
                    SET assigned_last_user = $userId
618
                    WHERE id = $ticketId";
619
            Database::query($sql);
620
621
            $table = Database::get_main_table(TABLE_TICKET_ASSIGNED_LOG);
622
            $params = [
623
                'ticket_id' => $ticketId,
624
                'user_id' => $userId,
625
                'sys_insert_user_id' => api_get_user_id(),
626
                'assigned_date' => api_get_utc_datetime(),
627
            ];
628
            Database::insert($table, $params);
629
630
            return true;
631
        } else {
632
            return false;
633
        }
634
    }
635
636
    /**
637
     * Insert message between Users and Admins.
638
     *
639
     * @param int    $ticketId
640
     * @param string $subject
641
     * @param string $content
642
     * @param array  $fileAttachments
643
     * @param int    $userId
644
     * @param string $status
645
     * @param bool   $sendConfirmation
646
     *
647
     * @return bool
648
     */
649
    public static function insertMessage(
650
        $ticketId,
651
        $subject,
652
        $content,
653
        $fileAttachments,
654
        $userId,
655
        $status = 'NOL',
656
        $sendConfirmation = false
657
    ) {
658
        $ticketId = (int) $ticketId;
659
        $userId = (int) $userId;
660
        $table_support_messages = Database::get_main_table(TABLE_TICKET_MESSAGE);
661
        $table_support_tickets = Database::get_main_table(TABLE_TICKET_TICKET);
662
        if ($sendConfirmation) {
663
            $form =
664
                '<form action="ticket_details.php?ticket_id='.$ticketId.'" id="confirmticket" method="POST" >
665
                     <p>'.get_lang('Was this answer satisfactory?').'</p>
666
                     <button class="btn btn--primary responseyes" name="response" id="responseyes" value="1">'.
667
                get_lang('Yes').'</button>
668
                     <button class="btn btn--danger responseno" name="response" id="responseno" value="0">'.
669
                get_lang('No').'</button>
670
                 </form>';
671
            $content .= $form;
672
        }
673
674
        $now = api_get_utc_datetime();
675
676
        $params = [
677
            'ticket_id' => $ticketId,
678
            'subject' => $subject,
679
            'message' => $content,
680
            'ip_address' => api_get_real_ip(),
681
            'sys_insert_user_id' => $userId,
682
            'sys_insert_datetime' => $now,
683
            'sys_lastedit_user_id' => $userId,
684
            'sys_lastedit_datetime' => $now,
685
            'status' => $status,
686
        ];
687
        $messageId = Database::insert($table_support_messages, $params);
688
        if ($messageId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $messageId of type false|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
689
            // update_total_message
690
            $sql = "UPDATE $table_support_tickets
691
                    SET
692
                        sys_lastedit_user_id = $userId,
693
                        sys_lastedit_datetime = '$now',
694
                        total_messages = (
695
                            SELECT COUNT(*) as total_messages
696
                            FROM $table_support_messages
697
                            WHERE ticket_id = $ticketId
698
                        )
699
                    WHERE id = $ticketId ";
700
            Database::query($sql);
701
702
            if (is_array($fileAttachments)) {
703
                foreach ($fileAttachments as $file_attach) {
704
                    if (0 == $file_attach['error']) {
705
                        self::saveMessageAttachmentFile(
706
                            $file_attach,
707
                            $ticketId,
708
                            $messageId
709
                        );
710
                    } else {
711
                        if (UPLOAD_ERR_NO_FILE != $file_attach['error']) {
712
                            return false;
713
                        }
714
                    }
715
                }
716
            }
717
718
            if (!self::isUserSubscribedToTicket($ticketId, $userId)) {
719
                self::subscribeUserToTicket($ticketId, $userId);
720
            }
721
        }
722
723
        return true;
724
    }
725
726
    /**
727
     * Attachment files when a message is sent.
728
     *
729
     * @throws \Doctrine\ORM\ORMException
730
     * @throws \Doctrine\ORM\OptimisticLockException
731
     * @throws \Doctrine\ORM\TransactionRequiredException
732
     */
733
    public static function saveMessageAttachmentFile(
734
        $fileAttach,
735
        $ticketId,
736
        $messageId
737
    ): bool {
738
        if (!is_array($fileAttach) || UPLOAD_ERR_OK != $fileAttach['error']) {
739
            return false;
740
        }
741
742
        $em = Database::getManager();
743
744
        $ticket = $em->find(Ticket::class, $ticketId);
745
        $message = $em->find(TicketMessage::class, $messageId);
746
747
        $newFileName = add_ext_on_mime(
748
            stripslashes($fileAttach['name']),
749
            $fileAttach['type']
750
        );
751
752
        $fileName = $fileAttach['name'];
753
754
        if (!filter_extension($newFileName)) {
755
            Display::addFlash(
756
                Display::return_message(
757
                    get_lang('File upload failed: this file extension or file type is prohibited'),
758
                    'error'
759
                )
760
            );
761
762
            return false;
763
        }
764
765
        $currentUser = api_get_user_entity();
766
767
        $repo = Container::getTicketMessageAttachmentRepository();
768
        $attachment = (new TicketMessageAttachment())
769
            ->setFilename($fileName)
770
            ->setPath(uniqid('ticket_message', true))
771
            ->setMessage($message)
772
            ->setSize((int) $fileAttach['size'])
773
            ->setTicket($ticket)
774
            ->setInsertUserId($currentUser->getId())
775
            ->setInsertDateTime(api_get_utc_datetime(null, false, true))
776
            ->setParent($currentUser)
777
        ;
778
779
        if (null !== $ticket->getAssignedLastUser()) {
780
            $attachment->addUserLink($ticket->getAssignedLastUser());
781
        }
782
783
        $em->persist($attachment);
784
        $em->flush();
785
786
        $file = new UploadedFile($fileAttach['tmp_name'], $fileAttach['name'], $fileAttach['type'], $fileAttach['error']);
787
788
        $repo->addFile($attachment, $file);
789
790
        return true;
791
    }
792
793
    /**
794
     * Get tickets by userId.
795
     *
796
     * @param int $from
797
     * @param int $number_of_items
798
     * @param $column
799
     * @param $direction
800
     *
801
     * @return array
802
     */
803
    public static function getTicketsByCurrentUser($from, $number_of_items, $column, $direction)
804
    {
805
        $table_support_category = Database::get_main_table(TABLE_TICKET_CATEGORY);
806
        $table_support_tickets = Database::get_main_table(TABLE_TICKET_TICKET);
807
        $table_support_priority = Database::get_main_table(TABLE_TICKET_PRIORITY);
808
        $table_support_status = Database::get_main_table(TABLE_TICKET_STATUS);
809
        $direction = !empty($direction) ? $direction : 'DESC';
810
        $userId = api_get_user_id();
811
        $userInfo = api_get_user_info($userId);
812
813
        if (empty($userInfo)) {
814
            return [];
815
        }
816
        $isAdmin = UserManager::is_admin($userId);
817
818
        if (!isset($_GET['project_id'])) {
819
            return [];
820
        }
821
822
        switch ($column) {
823
            case 0:
824
                $column = 'ticket_id';
825
                break;
826
            case 1:
827
                $column = 'status_title';
828
                break;
829
            case 2:
830
                $column = 'start_date';
831
                break;
832
            case 3:
833
                $column = 'sys_lastedit_datetime';
834
                break;
835
            case 4:
836
                $column = 'category_title';
837
                break;
838
            case 5:
839
                $column = 'sys_insert_user_id';
840
                break;
841
            case 6:
842
                $column = 'assigned_last_user';
843
                break;
844
            case 7:
845
                $column = 'total_messages';
846
                break;
847
            case 8:
848
                $column = 'subject';
849
                break;
850
            default:
851
                $column = 'ticket_id';
852
        }
853
854
        $sql = "SELECT DISTINCT
855
                ticket.*,
856
                ticket.id ticket_id,
857
                status.title AS status_title,
858
                ticket.start_date,
859
                ticket.sys_lastedit_datetime,
860
                cat.title AS category_title,
861
                priority.title AS priority_title,
862
                ticket.total_messages AS total_messages,
863
                ticket.message AS message,
864
                ticket.subject AS subject,
865
                ticket.assigned_last_user
866
            FROM $table_support_tickets ticket
867
            INNER JOIN $table_support_category cat
868
            ON (cat.id = ticket.category_id)
869
            INNER JOIN $table_support_priority priority
870
            ON (ticket.priority_id = priority.id)
871
            INNER JOIN $table_support_status status
872
            ON (ticket.status_id = status.id)
873
            WHERE 1=1
874
        ";
875
876
        $projectId = (int) $_GET['project_id'];
877
        $userIsAllowInProject = self::userIsAllowInProject($projectId);
0 ignored issues
show
Deprecated Code introduced by
The function TicketManager::userIsAllowInProject() has been deprecated: Use TicketProjectHelper::userIsAllowInProject instead ( Ignorable by Annotation )

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

877
        $userIsAllowInProject = /** @scrutinizer ignore-deprecated */ self::userIsAllowInProject($projectId);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
878
879
        // Check if a role was set to the project
880
        if (false == $userIsAllowInProject) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
881
            $sql .= " AND (ticket.assigned_last_user = $userId OR ticket.sys_insert_user_id = $userId )";
882
        }
883
884
        // Search simple
885
        if (isset($_GET['submit_simple']) && '' != $_GET['keyword']) {
886
            $keyword = Database::escape_string(trim($_GET['keyword']));
887
            $sql .= " AND (
888
                      ticket.id LIKE '%$keyword%' OR
889
                      ticket.code LIKE '%$keyword%' OR
890
                      ticket.subject LIKE '%$keyword%' OR
891
                      ticket.message LIKE '%$keyword%' OR
892
                      ticket.keyword LIKE '%$keyword%' OR
893
                      ticket.source LIKE '%$keyword%' OR
894
                      cat.title LIKE '%$keyword%' OR
895
                      status.title LIKE '%$keyword%' OR
896
                      priority.title LIKE '%$keyword%' OR
897
                      ticket.personal_email LIKE '%$keyword%'
898
            )";
899
        }
900
901
        $keywords = [
902
            'project_id' => 'ticket.project_id',
903
            'keyword_category' => 'ticket.category_id',
904
            'keyword_assigned_to' => 'ticket.assigned_last_user',
905
            'keyword_source' => 'ticket.source ',
906
            'keyword_status' => 'ticket.status_id',
907
            'keyword_priority' => 'ticket.priority_id',
908
        ];
909
910
        foreach ($keywords as $keyword => $label) {
911
            if (isset($_GET[$keyword])) {
912
                $data = Database::escape_string(trim($_GET[$keyword]));
913
                if (!empty($data)) {
914
                    $sql .= " AND $label = '$data' ";
915
                }
916
            }
917
        }
918
919
        // Search advanced
920
        $keyword_start_date_start = isset($_GET['keyword_start_date_start']) ? Database::escape_string(trim($_GET['keyword_start_date_start'])) : '';
921
        $keyword_start_date_end = isset($_GET['keyword_start_date_end']) ? Database::escape_string(trim($_GET['keyword_start_date_end'])) : '';
922
        $keyword_course = isset($_GET['keyword_course']) ? Database::escape_string(trim($_GET['keyword_course'])) : '';
923
        $keyword_range = !empty($keyword_start_date_start) && !empty($keyword_start_date_end);
924
925
        if (false == $keyword_range && '' != $keyword_start_date_start) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
926
            $sql .= " AND DATE_FORMAT(ticket.start_date,'%d/%m/%Y') >= '$keyword_start_date_start' ";
927
        }
928
        if ($keyword_range && '' != $keyword_start_date_start && '' != $keyword_start_date_end) {
929
            $sql .= " AND DATE_FORMAT(ticket.start_date,'%d/%m/%Y') >= '$keyword_start_date_start'
930
                      AND DATE_FORMAT(ticket.start_date,'%d/%m/%Y') <= '$keyword_start_date_end'";
931
        }
932
933
        if ('' != $keyword_course) {
934
            $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
935
            $sql .= " AND ticket.course_id IN (
936
                     SELECT id FROM $course_table
937
                     WHERE (
938
                        title LIKE '%$keyword_course%' OR
939
                        code LIKE '%$keyword_course%' OR
940
                        visual_code LIKE '%$keyword_course%'
941
                     )
942
            )";
943
        }
944
        $sql .= " ORDER BY `$column` $direction";
945
        $sql .= " LIMIT $from, $number_of_items";
946
947
        $result = Database::query($sql);
948
        $tickets = [];
949
        $webPath = api_get_path(WEB_PATH);
950
        while ($row = Database::fetch_assoc($result)) {
951
            $userInfo = api_get_user_info($row['sys_insert_user_id']);
952
            $hrefUser = $webPath.'main/admin/user_information.php?user_id='.$userInfo['user_id'];
953
            $name = "<a href='$hrefUser'> {$userInfo['complete_name_with_username']} </a>";
954
            if (0 != $row['assigned_last_user']) {
955
                $assignedUserInfo = api_get_user_info($row['assigned_last_user']);
956
                if (!empty($assignedUserInfo)) {
957
                    $hrefResp = $webPath.'main/admin/user_information.php?user_id='.$assignedUserInfo['user_id'];
958
                    $row['assigned_last_user'] = "<a href='$hrefResp'> {$assignedUserInfo['complete_name_with_username']} </a>";
959
                } else {
960
                    $row['assigned_last_user'] = get_lang('Unknown user');
961
                }
962
            } else {
963
                if (self::STATUS_FORWARDED !== $row['status_id']) {
964
                    $row['assigned_last_user'] = '<span style="color:#ff0000;">'.get_lang('To be assigned').'</span>';
965
                } else {
966
                    $row['assigned_last_user'] = '<span style="color:#00ff00;">'.get_lang('Message resent').'</span>';
967
                }
968
            }
969
970
            switch ($row['source']) {
971
                case self::SOURCE_PRESENTIAL:
972
                    $img_source = ObjectIcon::USER;
973
                    break;
974
                case self::SOURCE_EMAIL:
975
                    $img_source = ObjectIcon::EMAIL;
976
                    break;
977
                case self::SOURCE_PHONE:
978
                    $img_source = ObjectIcon::PHONE;
979
                    break;
980
                default:
981
                    $img_source = ObjectIcon::TICKET;
982
                    break;
983
            }
984
985
            $row['start_date'] = Display::dateToStringAgoAndLongDate($row['start_date']);
986
            $row['sys_lastedit_datetime'] = Display::dateToStringAgoAndLongDate($row['sys_lastedit_datetime']);
987
988
            $icon = Display::getMdiIcon(
989
                $img_source,
990
                'ch-tool-icon',
991
                'margin-right: 10px; float: left;',
992
                ICON_SIZE_SMALL,
993
                get_lang('Information'),
994
            );
995
996
            $icon .= '<a href="ticket_details.php?ticket_id='.$row['id'].'">'.$row['code'].'</a>';
997
998
            if ($isAdmin) {
999
                $ticket = [
1000
                    $icon.' '.Security::remove_XSS($row['subject']),
0 ignored issues
show
Bug introduced by
Are you sure Security::remove_XSS($row['subject']) of type array|string can be used in concatenation? ( Ignorable by Annotation )

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

1000
                    $icon.' './** @scrutinizer ignore-type */ Security::remove_XSS($row['subject']),
Loading history...
1001
                    $row['status_title'],
1002
                    $row['start_date'],
1003
                    $row['sys_lastedit_datetime'],
1004
                    $row['category_title'],
1005
                    $name,
1006
                    $row['assigned_last_user'],
1007
                    $row['total_messages'],
1008
                ];
1009
            } else {
1010
                $ticket = [
1011
                    $icon.' '.Security::remove_XSS($row['subject']),
1012
                    $row['status_title'],
1013
                    $row['start_date'],
1014
                    $row['sys_lastedit_datetime'],
1015
                    $row['category_title'],
1016
                ];
1017
            }
1018
            if ($isAdmin) {
1019
                $ticket['0'] .= '&nbsp;&nbsp;<a
1020
                href="javascript:void(0)"
1021
                onclick="load_history_ticket(\'div_'.$row['ticket_id'].'\','.$row['ticket_id'].')">
1022
                    <a
1023
                        onclick="load_course_list(\'div_'.$row['ticket_id'].'\','.$row['ticket_id'].')"
1024
					    onmouseover="clear_course_list (\'div_'.$row['ticket_id'].'\')"
1025
					    title="'.get_lang('History').'"
1026
					    alt="'.get_lang('History').'"
1027
                    >
1028
                    '.Display::getMdiIcon('history').'
1029
                    </a>
1030
1031
					<div class="blackboard_hide" id="div_'.$row['ticket_id'].'">&nbsp;&nbsp;</div>
1032
					</a>&nbsp;&nbsp;';
1033
            }
1034
            $tickets[] = $ticket;
1035
        }
1036
1037
        return $tickets;
1038
    }
1039
1040
    /**
1041
     * @return int
1042
     */
1043
    public static function getTotalTicketsCurrentUser()
1044
    {
1045
        $table_support_category = Database::get_main_table(TABLE_TICKET_CATEGORY);
1046
        $table_support_tickets = Database::get_main_table(TABLE_TICKET_TICKET);
1047
        $table_support_priority = Database::get_main_table(TABLE_TICKET_PRIORITY);
1048
        $table_support_status = Database::get_main_table(TABLE_TICKET_STATUS);
1049
1050
        $userInfo = api_get_user_info();
1051
        if (empty($userInfo)) {
1052
            return 0;
1053
        }
1054
        $userId = $userInfo['id'];
1055
1056
        if (!isset($_GET['project_id'])) {
1057
            return 0;
1058
        }
1059
1060
        $sql = "SELECT COUNT(ticket.id) AS total
1061
                FROM $table_support_tickets ticket
1062
                INNER JOIN $table_support_category cat
1063
                ON (cat.id = ticket.category_id)
1064
                INNER JOIN $table_support_priority priority
1065
                ON (ticket.priority_id = priority.id)
1066
                INNER JOIN $table_support_status status
1067
                ON (ticket.status_id = status.id)
1068
	            WHERE 1 = 1";
1069
1070
        $projectId = (int) $_GET['project_id'];
1071
        $allowRoleList = self::getAllowedRolesFromProject($projectId);
0 ignored issues
show
Deprecated Code introduced by
The function TicketManager::getAllowedRolesFromProject() has been deprecated: Use TicketProjectHelper::getAllowedRolesFromProject instead ( Ignorable by Annotation )

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

1071
        $allowRoleList = /** @scrutinizer ignore-deprecated */ self::getAllowedRolesFromProject($projectId);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
1072
1073
        // Check if a role was set to the project
1074
        if (!empty($allowRoleList) && is_array($allowRoleList)) {
1075
            $allowed = self::userIsAllowInProject($projectId);
0 ignored issues
show
Deprecated Code introduced by
The function TicketManager::userIsAllowInProject() has been deprecated: Use TicketProjectHelper::userIsAllowInProject instead ( Ignorable by Annotation )

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

1075
            $allowed = /** @scrutinizer ignore-deprecated */ self::userIsAllowInProject($projectId);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
1076
            if (!$allowed) {
1077
                $sql .= " AND (ticket.assigned_last_user = $userId OR ticket.sys_insert_user_id = $userId )";
1078
            }
1079
        } else {
1080
            if (!api_is_platform_admin()) {
1081
                $sql .= " AND (ticket.assigned_last_user = $userId OR ticket.sys_insert_user_id = $userId )";
1082
            }
1083
        }
1084
1085
        // Search simple
1086
        if (isset($_GET['submit_simple'])) {
1087
            if ('' != $_GET['keyword']) {
1088
                $keyword = Database::escape_string(trim($_GET['keyword']));
1089
                $sql .= " AND (
1090
                          ticket.code LIKE '%$keyword%' OR
1091
                          ticket.subject LIKE '%$keyword%' OR
1092
                          ticket.message LIKE '%$keyword%' OR
1093
                          ticket.keyword LIKE '%$keyword%' OR
1094
                          ticket.personal_email LIKE '%$keyword%' OR
1095
                          ticket.source LIKE '%$keyword%'
1096
                )";
1097
            }
1098
        }
1099
1100
        $keywords = [
1101
            'project_id' => 'ticket.project_id',
1102
            'keyword_category' => 'ticket.category_id',
1103
            'keyword_assigned_to' => 'ticket.assigned_last_user',
1104
            'keyword_source' => 'ticket.source',
1105
            'keyword_status' => 'ticket.status_id',
1106
            'keyword_priority' => 'ticket.priority_id',
1107
        ];
1108
1109
        foreach ($keywords as $keyword => $sqlLabel) {
1110
            if (isset($_GET[$keyword])) {
1111
                $data = Database::escape_string(trim($_GET[$keyword]));
1112
                $sql .= " AND $sqlLabel = '$data' ";
1113
            }
1114
        }
1115
1116
        // Search advanced
1117
        $keyword_start_date_start = isset($_GET['keyword_start_date_start']) ? Database::escape_string(trim($_GET['keyword_start_date_start'])) : '';
1118
        $keyword_start_date_end = isset($_GET['keyword_start_date_end']) ? Database::escape_string(trim($_GET['keyword_start_date_end'])) : '';
1119
        $keyword_range = isset($_GET['keyword_dates']) ? Database::escape_string(trim($_GET['keyword_dates'])) : '';
1120
        $keyword_course = isset($_GET['keyword_course']) ? Database::escape_string(trim($_GET['keyword_course'])) : '';
1121
1122
        if (false == $keyword_range && '' != $keyword_start_date_start) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $keyword_range of type string to the boolean false. If you are specifically checking for an empty string, consider using the more explicit === '' instead.
Loading history...
1123
            $sql .= " AND DATE_FORMAT( ticket.start_date,'%d/%m/%Y') = '$keyword_start_date_start' ";
1124
        }
1125
        if ($keyword_range && '' != $keyword_start_date_start && '' != $keyword_start_date_end) {
1126
            $sql .= " AND DATE_FORMAT( ticket.start_date,'%d/%m/%Y') >= '$keyword_start_date_start'
1127
                      AND DATE_FORMAT( ticket.start_date,'%d/%m/%Y') <= '$keyword_start_date_end'";
1128
        }
1129
        if ('' != $keyword_course) {
1130
            $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1131
            $sql .= " AND ticket.course_id IN (
1132
                        SELECT id
1133
                        FROM $course_table
1134
                        WHERE (
1135
                            title LIKE '%$keyword_course%' OR
1136
                            code LIKE '%$keyword_course%' OR
1137
                            visual_code LIKE '%$keyword_course%'
1138
                        )
1139
                   ) ";
1140
        }
1141
1142
        $res = Database::query($sql);
1143
        $obj = Database::fetch_object($res);
1144
1145
        return (int) $obj->total;
1146
    }
1147
1148
    /**
1149
     * @param int $id
1150
     *
1151
     * @return false|TicketMessageAttachment
1152
     */
1153
    public static function getTicketMessageAttachment($id)
1154
    {
1155
        $id = (int) $id;
1156
        $em = Database::getManager();
1157
        $item = $em->getRepository(TicketMessageAttachment::class)->find($id);
1158
        if ($item) {
1159
            return $item;
1160
        }
1161
1162
        return false;
1163
    }
1164
1165
    /**
1166
     * @param int $id
1167
     *
1168
     * @return array
1169
     */
1170
    public static function getTicketMessageAttachmentsByTicketId($id)
1171
    {
1172
        $id = (int) $id;
1173
        $em = Database::getManager();
1174
        $items = $em->getRepository(TicketMessageAttachment::class)->findBy(['ticket' => $id]);
1175
        if ($items) {
1176
            return $items;
1177
        }
1178
1179
        return false;
1180
    }
1181
1182
    /**
1183
     * @param int $ticketId
1184
     *
1185
     * @return array
1186
     */
1187
    public static function get_ticket_detail_by_id($ticketId)
1188
    {
1189
        $attachmentRepo = Container::getTicketMessageAttachmentRepository();
1190
1191
        $ticketId = (int) $ticketId;
1192
        $table_support_category = Database::get_main_table(TABLE_TICKET_CATEGORY);
1193
        $table_support_tickets = Database::get_main_table(TABLE_TICKET_TICKET);
1194
        $table_support_priority = Database::get_main_table(TABLE_TICKET_PRIORITY);
1195
        $table_support_status = Database::get_main_table(TABLE_TICKET_STATUS);
1196
        $table_support_messages = Database::get_main_table(TABLE_TICKET_MESSAGE);
1197
        $table_main_user = Database::get_main_table(TABLE_MAIN_USER);
1198
1199
        $sql = "SELECT
1200
                    ticket.*,
1201
                    cat.title,
1202
                    status.title as status,
1203
                    priority.title priority
1204
                FROM $table_support_tickets ticket
1205
                INNER JOIN $table_support_category cat
1206
                ON (cat.id = ticket.category_id)
1207
                INNER JOIN $table_support_priority priority
1208
                ON (priority.id = ticket.priority_id)
1209
                INNER JOIN $table_support_status status
1210
                ON (status.id = ticket.status_id)
1211
		        WHERE
1212
                    ticket.id = $ticketId ";
1213
        $result = Database::query($sql);
1214
        $ticket = [];
1215
1216
        $repo = Container::getLpRepository();
1217
        if (Database::num_rows($result) > 0) {
1218
            while ($row = Database::fetch_assoc($result)) {
1219
                $row['course'] = null;
1220
                $row['start_date_from_db'] = $row['start_date'];
1221
                $row['start_date'] = api_convert_and_format_date(
1222
                    api_get_local_time($row['start_date']),
1223
                    DATE_TIME_FORMAT_LONG,
1224
                    api_get_timezone()
1225
                );
1226
                $row['end_date_from_db'] = $row['end_date'];
1227
                $row['end_date'] = api_convert_and_format_date(
1228
                    api_get_local_time($row['end_date']),
1229
                    DATE_TIME_FORMAT_LONG,
1230
                    api_get_timezone()
1231
                );
1232
                $row['sys_lastedit_datetime_from_db'] = $row['sys_lastedit_datetime'];
1233
                $row['sys_lastedit_datetime'] = api_convert_and_format_date(
1234
                    api_get_local_time($row['sys_lastedit_datetime']),
1235
                    DATE_TIME_FORMAT_LONG,
1236
                    api_get_timezone()
1237
                );
1238
                $row['course_url'] = null;
1239
                if (0 != $row['course_id']) {
1240
                    $course = api_get_course_info_by_id($row['course_id']);
1241
                    $sessionId = 0;
1242
                    if ($row['session_id']) {
1243
                        $sessionId = $row['session_id'];
1244
                    }
1245
                    if ($course) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $course of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1246
                        $row['course_url'] = '<a href="'.$course['course_public_url'].'?id_session='.$sessionId.'">'.$course['name'].'</a>';
1247
                    }
1248
                    $row['exercise_url'] = null;
1249
1250
                    if (!empty($row['exercise_id'])) {
1251
                        $exerciseTitle = ExerciseLib::getExerciseTitleById($row['exercise_id']);
1252
                        $dataExercise = [
1253
                            'cidReq' => $course['code'],
1254
                            'id_session' => $sessionId,
1255
                            'exerciseId' => $row['exercise_id'],
1256
                        ];
1257
                        $urlParamsExercise = http_build_query($dataExercise);
1258
1259
                        $row['exercise_url'] = '<a href="'.api_get_path(WEB_CODE_PATH).'exercise/overview.php?'.$urlParamsExercise.'">'.$exerciseTitle.'</a>';
1260
                    }
1261
1262
                    $row['lp_url'] = null;
1263
1264
                    if (!empty($row['lp_id'])) {
1265
                        /** @var CLp $lp */
1266
                        $lp = $repo->find($row['lp_id']);
1267
                        $dataLp = [
1268
                            'cidReq' => $course['code'],
1269
                            'id_session' => $sessionId,
1270
                            'lp_id' => $row['lp_id'],
1271
                            'action' => 'view',
1272
                        ];
1273
                        $urlParamsLp = http_build_query($dataLp);
1274
1275
                        $row['lp_url'] = '<a
1276
                            href="'.api_get_path(WEB_CODE_PATH).'lp/lp_controller.php?'.$urlParamsLp.'">'.
1277
                            $lp->getTitle().
1278
                        '</a>';
1279
                    }
1280
                }
1281
1282
                $userInfo = api_get_user_info($row['sys_insert_user_id']);
1283
                $row['user_url'] = '<a href="'.api_get_path(WEB_PATH).'main/admin/user_information.php?user_id='.$userInfo['user_id'].'">
1284
                '.$userInfo['complete_name'].'</a>';
1285
                $ticket['user'] = $userInfo;
1286
                $ticket['ticket'] = $row;
1287
            }
1288
1289
            $sql = "SELECT *, message.id as message_id, user.id AS user_id
1290
                    FROM $table_support_messages message
1291
                    INNER JOIN $table_main_user user
1292
                    ON (message.sys_insert_user_id = user.id)
1293
                    WHERE user.active <> ".USER_SOFT_DELETED." AND
1294
                        message.ticket_id = '$ticketId' ";
1295
            $result = Database::query($sql);
1296
            $ticket['messages'] = [];
1297
            $attach_icon = Display::getMdiIcon(ObjectIcon::ATTACHMENT, 'ch-tool-icon', null, ICON_SIZE_SMALL);
1298
1299
            while ($row = Database::fetch_assoc($result)) {
1300
                $message = $row;
1301
                $message['admin'] = UserManager::is_admin($message['user_id']);
1302
                $message['user_info'] = api_get_user_info($message['user_id']);
1303
1304
                $messageAttachments = $attachmentRepo->findBy(['ticket' => $ticketId, 'message' => $row['message_id']]);
1305
1306
                /** @var TicketMessageAttachment $messageAttachment */
1307
                foreach ($messageAttachments as $messageAttachment) {
1308
                    $archiveURL = $attachmentRepo->getResourceFileDownloadUrl($messageAttachment);
1309
                    $link = Display::url(
1310
                        sprintf("%s (%d)", $messageAttachment->getFilename(), $messageAttachment->getSize()),
1311
                        $archiveURL
1312
                    );
1313
1314
                    $message['attachments'][] = $attach_icon.PHP_EOL.$link;
1315
                }
1316
                $ticket['messages'][] = $message;
1317
            }
1318
        }
1319
1320
        return $ticket;
1321
    }
1322
1323
    /**
1324
     * @param int $ticketId
1325
     * @param int $userId
1326
     *
1327
     * @return bool
1328
     */
1329
    public static function update_message_status($ticketId, $userId)
1330
    {
1331
        $ticketId = (int) $ticketId;
1332
        $userId = (int) $userId;
1333
        $table_support_messages = Database::get_main_table(TABLE_TICKET_MESSAGE);
1334
        $table_support_tickets = Database::get_main_table(TABLE_TICKET_TICKET);
1335
        $now = api_get_utc_datetime();
1336
        $sql = "UPDATE $table_support_messages
1337
                SET
1338
                    status = 'LEI',
1339
                    sys_lastedit_user_id ='".api_get_user_id()."',
1340
                    sys_lastedit_datetime ='".$now."'
1341
                WHERE ticket_id ='$ticketId' ";
1342
1343
        if (api_is_platform_admin()) {
1344
            $sql .= " AND sys_insert_user_id = '$userId'";
1345
        } else {
1346
            $sql .= " AND sys_insert_user_id != '$userId'";
1347
        }
1348
        $result = Database::query($sql);
1349
        if (Database::affected_rows($result) > 0) {
1350
            Database::query(
1351
                "UPDATE $table_support_tickets SET
1352
                    status_id = '".self::STATUS_PENDING."'
1353
                 WHERE id ='$ticketId' AND status_id = '".self::STATUS_NEW."'"
1354
            );
1355
1356
            return true;
1357
        }
1358
1359
        return false;
1360
    }
1361
1362
    /**
1363
     * Send notification to a user through the internal messaging system.
1364
     */
1365
    public static function sendNotification($ticketId, $title, $message, $onlyToUserId = 0, $debug = false)
1366
    {
1367
        $ticketInfo = self::get_ticket_detail_by_id($ticketId);
1368
1369
        if (empty($ticketInfo)) {
1370
            return false;
1371
        }
1372
1373
        $assignedUserInfo = api_get_user_info($ticketInfo['ticket']['assigned_last_user']);
1374
        $requestUserInfo = $ticketInfo['user'];
1375
        $ticketCode = $ticketInfo['ticket']['code'];
1376
        $status = $ticketInfo['ticket']['status'];
1377
        $priority = $ticketInfo['ticket']['priority'];
1378
1379
        // Subject
1380
        $titleEmail = "[$ticketCode] $title";
1381
1382
        // Content
1383
        $href = api_get_path(WEB_CODE_PATH) . 'ticket/ticket_details.php?ticket_id=' . $ticketId;
1384
        $ticketUrl = Display::url($ticketCode, $href);
1385
        $messageEmailBase = get_lang('Ticket number') . ": $ticketUrl <br />";
1386
        $messageEmailBase .= get_lang('Status') . ": $status <br />";
1387
        $messageEmailBase .= get_lang('Priority') . ": $priority <br />";
1388
        $messageEmailBase .= '<hr /><br />';
1389
        $messageEmailBase .= $message;
1390
1391
        $currentUserId = api_get_user_id();
1392
        $recipients = [];
1393
1394
        if (!empty($onlyToUserId) && $currentUserId != $onlyToUserId) {
1395
            $recipients[$onlyToUserId] = $onlyToUserId;
1396
        } else {
1397
            if ($requestUserInfo && $currentUserId != $requestUserInfo['id']) {
1398
                $recipients[$requestUserInfo['id']] = $requestUserInfo['complete_name_with_username'];
1399
            }
1400
1401
            if ($assignedUserInfo && $currentUserId != $assignedUserInfo['id']) {
1402
                $recipients[$assignedUserInfo['id']] = $assignedUserInfo['complete_name_with_username'];
1403
            }
1404
1405
            $followers = self::getFollowers($ticketId);
1406
            /* @var User $follower */
1407
            foreach ($followers as $follower) {
1408
                if ($currentUserId != $follower->getId()) {
1409
                    $recipients[$follower->getId()] = $follower->getFullname();
1410
                }
1411
            }
1412
        }
1413
1414
        if ($debug) {
1415
            echo "<pre>";
1416
            echo "Title: $titleEmail\n";
1417
            echo "Message Preview:\n\n";
1418
1419
            foreach ($recipients as $recipientId => $recipientName) {
1420
                $unsubscribeLink = self::generateUnsubscribeLink($ticketId, $recipientId);
1421
                $finalMessageEmail = $messageEmailBase;
1422
                $finalMessageEmail .= '<br /><hr /><br />';
1423
                $finalMessageEmail .= '<small>' . get_lang('To unsubscribe from notifications, click here') . ': ';
1424
                $finalMessageEmail .= '<a href="' . $unsubscribeLink . '">' . $unsubscribeLink . '</a></small>';
1425
1426
                echo "------------------------------------\n";
1427
                echo "Recipient: $recipientName (User ID: $recipientId)\n";
1428
                echo "Message:\n$finalMessageEmail\n";
1429
                echo "------------------------------------\n\n";
1430
            }
1431
1432
            echo "</pre>";
1433
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
1434
        }
1435
1436
        foreach ($recipients as $recipientId => $recipientName) {
1437
            $unsubscribeLink = self::generateUnsubscribeLink($ticketId, $recipientId);
1438
1439
            $finalMessageEmail = $messageEmailBase;
1440
            $finalMessageEmail .= '<br /><hr /><br />';
1441
            $finalMessageEmail .= '<small>' . get_lang('To unsubscribe from notifications, click here') . ': ';
1442
            $finalMessageEmail .= '<a href="' . $unsubscribeLink . '">' . $unsubscribeLink . '</a></small>';
1443
1444
            MessageManager::send_message_simple(
1445
                $recipientId,
1446
                $titleEmail,
1447
                $finalMessageEmail,
1448
                0,
1449
                false,
1450
                false,
1451
                false
1452
            );
1453
        }
1454
1455
        return true;
1456
    }
1457
1458
    /**
1459
     * @param array $params
1460
     * @param int   $ticketId
1461
     * @param int   $userId
1462
     *
1463
     * @return bool
1464
     */
1465
    public static function updateTicket(
1466
        $params,
1467
        $ticketId,
1468
        $userId
1469
    ) {
1470
        $now = api_get_utc_datetime();
1471
        $table = Database::get_main_table(TABLE_TICKET_TICKET);
1472
        $newParams = [
1473
            'priority_id' => isset($params['priority_id']) ? (int) $params['priority_id'] : '',
1474
            'status_id' => isset($params['status_id']) ? (int) $params['status_id'] : '',
1475
            'sys_lastedit_user_id' => (int) $userId,
1476
            'sys_lastedit_datetime' => $now,
1477
        ];
1478
        Database::update($table, $newParams, ['id = ? ' => $ticketId]);
1479
1480
        return true;
1481
    }
1482
1483
    /**
1484
     * @param int $status_id
1485
     * @param int $ticketId
1486
     * @param int $userId
1487
     *
1488
     * @return bool
1489
     */
1490
    public static function update_ticket_status(
1491
        $status_id,
1492
        $ticketId,
1493
        $userId
1494
    ) {
1495
        $table_support_tickets = Database::get_main_table(TABLE_TICKET_TICKET);
1496
1497
        $ticketId = (int) $ticketId;
1498
        $status_id = (int) $status_id;
1499
        $userId = (int) $userId;
1500
        $now = api_get_utc_datetime();
1501
1502
        $sql = "UPDATE $table_support_tickets
1503
                SET
1504
                    status_id = '$status_id',
1505
                    sys_lastedit_user_id ='$userId',
1506
                    sys_lastedit_datetime ='".$now."'
1507
                WHERE id ='$ticketId'";
1508
        $result = Database::query($sql);
1509
1510
        if (Database::affected_rows($result) > 0) {
1511
            self::sendNotification(
1512
                $ticketId,
1513
                get_lang('Ticket updated'),
1514
                get_lang('Ticket updated')
1515
            );
1516
1517
            return true;
1518
        }
1519
1520
        return false;
1521
    }
1522
1523
    /**
1524
     * @return mixed
1525
     */
1526
    public static function getNumberOfMessages()
1527
    {
1528
        $table_support_tickets = Database::get_main_table(TABLE_TICKET_TICKET);
1529
        $table_support_messages = Database::get_main_table(TABLE_TICKET_MESSAGE);
1530
        $table_main_user = Database::get_main_table(TABLE_MAIN_USER);
1531
        $table_main_admin = Database::get_main_table(TABLE_MAIN_ADMIN);
1532
        $user_info = api_get_user_info();
1533
        $userId = $user_info['user_id'];
1534
        $sql = "SELECT COUNT(DISTINCT ticket.id) AS unread
1535
                FROM $table_support_tickets ticket,
1536
                $table_support_messages message ,
1537
                $table_main_user user
1538
                WHERE
1539
                    ticket.id = message.ticket_id AND
1540
                    message.status = 'NOL' AND
1541
                    user.user_id = message.sys_insert_user_id ";
1542
        if (!api_is_platform_admin()) {
1543
            $sql .= " AND ticket.request_user = '$userId'
1544
                      AND user_id IN (SELECT user_id FROM $table_main_admin)  ";
1545
        } else {
1546
            $sql .= " AND user_id NOT IN (SELECT user_id FROM $table_main_admin)
1547
                      AND ticket.status_id != '".self::STATUS_FORWARDED."'";
1548
        }
1549
        $sql .= "  AND ticket.project_id != '' ";
1550
        $res = Database::query($sql);
1551
        $obj = Database::fetch_object($res);
1552
1553
        return $obj->unread;
1554
    }
1555
1556
    /**
1557
     * @param int $ticketId
1558
     * @param int $userId
1559
     */
1560
    public static function send_alert($ticketId, $userId)
1561
    {
1562
        $table_support_tickets = Database::get_main_table(TABLE_TICKET_TICKET);
1563
        $now = api_get_utc_datetime();
1564
1565
        $ticketId = (int) $ticketId;
1566
        $userId = (int) $userId;
1567
1568
        $sql = "UPDATE $table_support_tickets SET
1569
                  priority_id = '".self::PRIORITY_HIGH."',
1570
                  sys_lastedit_user_id = $userId,
1571
                  sys_lastedit_datetime = '$now'
1572
                WHERE id = $ticketId";
1573
        Database::query($sql);
1574
    }
1575
1576
    /**
1577
     * @param int $ticketId
1578
     * @param int $userId
1579
     */
1580
    public static function close_ticket($ticketId, $userId)
1581
    {
1582
        $ticketId = (int) $ticketId;
1583
        $userId = (int) $userId;
1584
1585
        $table_support_tickets = Database::get_main_table(TABLE_TICKET_TICKET);
1586
        $now = api_get_utc_datetime();
1587
        $sql = "UPDATE $table_support_tickets SET
1588
                    status_id = '".self::STATUS_CLOSE."',
1589
                    sys_lastedit_user_id ='$userId',
1590
                    sys_lastedit_datetime ='".$now."',
1591
                    end_date ='$now'
1592
                WHERE id ='$ticketId'";
1593
        Database::query($sql);
1594
1595
        self::sendNotification(
1596
            $ticketId,
1597
            get_lang('Ticket closed'),
1598
            get_lang('Ticket closed')
1599
        );
1600
    }
1601
1602
    /**
1603
     * Close old tickets.
1604
     */
1605
    public static function close_old_tickets()
1606
    {
1607
        $table = Database::get_main_table(TABLE_TICKET_TICKET);
1608
        $now = api_get_utc_datetime();
1609
        $userId = api_get_user_id();
1610
        $sql = "UPDATE $table
1611
                SET
1612
                    status_id = '".self::STATUS_CLOSE."',
1613
                    sys_lastedit_user_id ='$userId',
1614
                    sys_lastedit_datetime ='$now',
1615
                    end_date = '$now'
1616
                WHERE
1617
                    DATEDIFF('$now', sys_lastedit_datetime) > 7 AND
1618
                    status_id != '".self::STATUS_CLOSE."' AND
1619
                    status_id != '".self::STATUS_NEW."' AND
1620
                    status_id != '".self::STATUS_FORWARDED."'";
1621
        Database::query($sql);
1622
    }
1623
1624
    /**
1625
     * @param int $ticketId
1626
     *
1627
     * @return array
1628
     */
1629
    public static function get_assign_log($ticketId)
1630
    {
1631
        $table = Database::get_main_table(TABLE_TICKET_ASSIGNED_LOG);
1632
        $ticketId = (int) $ticketId;
1633
1634
        $sql = "SELECT * FROM $table
1635
                WHERE ticket_id = $ticketId
1636
                ORDER BY assigned_date DESC";
1637
        $result = Database::query($sql);
1638
        $history = [];
1639
        $webpath = api_get_path(WEB_PATH);
1640
        while ($row = Database::fetch_assoc($result)) {
1641
            if (0 != $row['user_id']) {
1642
                $assignuser = api_get_user_info($row['user_id']);
1643
                $row['assignuser'] = '<a href="'.$webpath.'main/admin/user_information.php?user_id='.$row['user_id'].'"  target="_blank">'.
1644
                $assignuser['username'].'</a>';
1645
            } else {
1646
                $row['assignuser'] = get_lang('Unassign');
1647
            }
1648
            $row['assigned_date'] = Display::dateToStringAgoAndLongDate($row['assigned_date']);
1649
            $insertuser = api_get_user_info($row['sys_insert_user_id']);
1650
            $row['insertuser'] = '<a href="'.$webpath.'main/admin/user_information.php?user_id='.$row['sys_insert_user_id'].'"  target="_blank">'.
1651
                $insertuser['username'].'</a>';
1652
            $history[] = $row;
1653
        }
1654
1655
        return $history;
1656
    }
1657
1658
    /**
1659
     * @param $from
1660
     * @param $number_of_items
1661
     * @param $column
1662
     * @param $direction
1663
     * @param null $userId
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $userId is correct as it would always require null to be passed?
Loading history...
1664
     *
1665
     * @return array
1666
     */
1667
    public static function export_tickets_by_user_id(
1668
        $from,
1669
        $number_of_items,
1670
        $column,
1671
        $direction,
1672
        $userId = null
1673
    ) {
1674
        $from = (int) $from;
1675
        $number_of_items = (int) $number_of_items;
1676
        $table_support_category = Database::get_main_table(
1677
            TABLE_TICKET_CATEGORY
1678
        );
1679
        $table_support_tickets = Database::get_main_table(TABLE_TICKET_TICKET);
1680
        $table_support_priority = Database::get_main_table(TABLE_TICKET_PRIORITY);
1681
        $table_support_status = Database::get_main_table(TABLE_TICKET_STATUS);
1682
        $table_support_messages = Database::get_main_table(TABLE_TICKET_MESSAGE);
1683
        $table_main_user = Database::get_main_table(TABLE_MAIN_USER);
1684
1685
        if (is_null($direction)) {
1686
            $direction = 'DESC';
1687
        }
1688
        if (is_null($userId) || 0 == $userId) {
1689
            $userId = api_get_user_id();
1690
        }
1691
1692
        $sql = "SELECT
1693
                    ticket.code,
1694
                    ticket.sys_insert_datetime,
1695
                    ticket.sys_lastedit_datetime,
1696
                    cat.title as category,
1697
                    CONCAT(user.lastname,' ', user.firstname) AS fullname,
1698
                    status.title as status,
1699
                    ticket.total_messages as messages,
1700
                    ticket.assigned_last_user as responsable
1701
                FROM $table_support_tickets ticket,
1702
                $table_support_category cat ,
1703
                $table_support_priority priority,
1704
                $table_support_status status ,
1705
                $table_main_user user
1706
                WHERE
1707
                    cat.id = ticket.category_id
1708
                    AND ticket.priority_id = priority.id
1709
                    AND ticket.status_id = status.id
1710
                    AND user.user_id = ticket.request_user ";
1711
        // Search simple
1712
        if (isset($_GET['submit_simple'])) {
1713
            if ('' !== $_GET['keyword']) {
1714
                $keyword = Database::escape_string(trim($_GET['keyword']));
1715
                $sql .= " AND (ticket.code = '$keyword'
1716
                          OR user.firstname LIKE '%$keyword%'
1717
                          OR user.lastname LIKE '%$keyword%'
1718
                          OR concat(user.firstname,' ',user.lastname) LIKE '%$keyword%'
1719
                          OR concat(user.lastname,' ',user.firstname) LIKE '%$keyword%'
1720
                          OR user.username LIKE '%$keyword%')  ";
1721
            }
1722
        }
1723
        // Search advanced
1724
        if (isset($_GET['submit_advanced'])) {
1725
            $keyword_category = Database::escape_string(
1726
                trim($_GET['keyword_category'])
1727
            );
1728
            $keyword_request_user = Database::escape_string(
1729
                trim($_GET['keyword_request_user'])
1730
            );
1731
            $keywordAssignedTo = (int) $_GET['keyword_assigned_to'];
1732
            $keyword_start_date_start = Database::escape_string(
1733
                trim($_GET['keyword_start_date_start'])
1734
            );
1735
            $keyword_start_date_end = Database::escape_string(
1736
                trim($_GET['keyword_start_date_end'])
1737
            );
1738
            $keyword_status = Database::escape_string(
1739
                trim($_GET['keyword_status'])
1740
            );
1741
            $keyword_source = Database::escape_string(
1742
                trim($_GET['keyword_source'])
1743
            );
1744
            $keyword_priority = Database::escape_string(
1745
                trim($_GET['keyword_priority'])
1746
            );
1747
            $keyword_range = Database::escape_string(
1748
                trim($_GET['keyword_dates'])
1749
            );
1750
            $keyword_unread = Database::escape_string(
1751
                trim($_GET['keyword_unread'])
1752
            );
1753
            $keyword_course = Database::escape_string(
1754
                trim($_GET['keyword_course'])
1755
            );
1756
1757
            if ('' != $keyword_category) {
1758
                $sql .= " AND ticket.category_id = '$keyword_category'  ";
1759
            }
1760
            if ('' != $keyword_request_user) {
1761
                $sql .= " AND (ticket.request_user = '$keyword_request_user'
1762
                          OR user.firstname LIKE '%$keyword_request_user%'
1763
                          OR user.official_code LIKE '%$keyword_request_user%'
1764
                          OR user.lastname LIKE '%$keyword_request_user%'
1765
                          OR concat(user.firstname,' ',user.lastname) LIKE '%$keyword_request_user%'
1766
                          OR concat(user.lastname,' ',user.firstname) LIKE '%$keyword_request_user%'
1767
                          OR user.username LIKE '%$keyword_request_user%') ";
1768
            }
1769
            if (!empty($keywordAssignedTo)) {
1770
                $sql .= " AND ticket.assigned_last_user = $keywordAssignedTo ";
1771
            }
1772
            if ('' != $keyword_status) {
1773
                $sql .= " AND ticket.status_id = '$keyword_status'  ";
1774
            }
1775
            if ('' == $keyword_range && '' != $keyword_start_date_start) {
1776
                $sql .= " AND DATE_FORMAT( ticket.start_date,'%d/%m/%Y') = '$keyword_start_date_start' ";
1777
            }
1778
            if ('1' == $keyword_range && '' != $keyword_start_date_start && '' != $keyword_start_date_end) {
1779
                $sql .= " AND DATE_FORMAT( ticket.start_date,'%d/%m/%Y') >= '$keyword_start_date_start'
1780
                          AND DATE_FORMAT( ticket.start_date,'%d/%m/%Y') <= '$keyword_start_date_end'";
1781
            }
1782
            if ('' != $keyword_priority) {
1783
                $sql .= " AND ticket.priority_id = '$keyword_priority'  ";
1784
            }
1785
            if ('' != $keyword_source) {
1786
                $sql .= " AND ticket.source = '$keyword_source' ";
1787
            }
1788
            if ('' != $keyword_priority) {
1789
                $sql .= " AND ticket.priority_id = '$keyword_priority' ";
1790
            }
1791
            if ('' != $keyword_course) {
1792
                $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1793
                $sql .= " AND ticket.course_id IN ( ";
1794
                $sql .= "SELECT id
1795
                         FROM $course_table
1796
                         WHERE (title LIKE '%$keyword_course%'
1797
                         OR code LIKE '%$keyword_course%'
1798
                         OR visual_code LIKE '%$keyword_course%' )) ";
1799
            }
1800
            if ('yes' == $keyword_unread) {
1801
                $sql .= " AND ticket.id IN (
1802
                          SELECT ticket.id
1803
                          FROM $table_support_tickets ticket,
1804
                          $table_support_messages message,
1805
                          $table_main_user user
1806
                          WHERE ticket.id = message.ticket_id
1807
                          AND message.status = 'NOL'
1808
                          AND message.sys_insert_user_id = user.user_id
1809
                          AND user.status != 1   AND ticket.status_id != '".self::STATUS_FORWARDED."'
1810
                          GROUP BY ticket.id)";
1811
            } else {
1812
                if ('no' == $keyword_unread) {
1813
                    $sql .= " AND ticket.id NOT IN (
1814
                              SELECT ticket.id
1815
                              FROM  $table_support_tickets ticket,
1816
                              $table_support_messages message,
1817
                              $table_main_user user
1818
                              WHERE ticket.id = message.ticket_id
1819
                              AND message.status = 'NOL'
1820
                              AND message.sys_insert_user_id = user.user_id
1821
                              AND user.status != 1
1822
                              AND ticket.status_id != '".self::STATUS_FORWARDED."'
1823
                             GROUP BY ticket.id)";
1824
                }
1825
            }
1826
        }
1827
1828
        $sql .= !str_contains($sql, 'WHERE') ? ' WHERE user.active <> '.USER_SOFT_DELETED : ' AND user.active <> '.USER_SOFT_DELETED;
1829
        $sql .= " LIMIT $from,$number_of_items";
1830
1831
        $result = Database::query($sql);
1832
        $tickets[0] = [
0 ignored issues
show
Comprehensibility Best Practice introduced by
$tickets was never initialized. Although not strictly required by PHP, it is generally a good practice to add $tickets = array(); before regardless.
Loading history...
1833
            utf8_decode('Ticket#'),
1834
            utf8_decode('Fecha'),
1835
            utf8_decode('Fecha Edicion'),
1836
            utf8_decode('Categoria'),
1837
            utf8_decode('Usuario'),
1838
            utf8_decode('Estado'),
1839
            utf8_decode('Mensajes'),
1840
            utf8_decode('Responsable'),
1841
            utf8_decode('Programa'),
1842
        ];
1843
1844
        while ($row = Database::fetch_assoc($result)) {
1845
            if (0 != $row['responsable']) {
1846
                $row['responsable'] = api_get_user_info($row['responsable']);
1847
                $row['responsable'] = $row['responsable']['firstname'].' '.$row['responsable']['lastname'];
1848
            }
1849
            $row['sys_insert_datetime'] = api_format_date(
1850
                $row['sys_insert_datetime'],
1851
                '%d/%m/%y - %I:%M:%S %p'
1852
            );
1853
            $row['sys_lastedit_datetime'] = api_format_date(
1854
                $row['sys_lastedit_datetime'],
1855
                '%d/%m/%y - %I:%M:%S %p'
1856
            );
1857
            $row['category'] = utf8_decode($row['category']);
1858
            $row['programa'] = utf8_decode($row['fullname']);
1859
            $row['fullname'] = utf8_decode($row['fullname']);
1860
            $row['responsable'] = utf8_decode($row['responsable']);
1861
            $tickets[] = $row;
1862
        }
1863
1864
        return $tickets;
1865
    }
1866
1867
    /**
1868
     * @param string $url
1869
     * @param int    $projectId
1870
     *
1871
     * @return FormValidator
1872
     */
1873
    public static function getCategoryForm($url, $projectId)
1874
    {
1875
        $form = new FormValidator('category', 'post', $url);
1876
        $form->addText('name', get_lang('Name'));
1877
        $form->addHtmlEditor('description', get_lang('Description'));
1878
        $form->addHidden('project_id', $projectId);
1879
        $form->addButtonUpdate(get_lang('Save'));
1880
1881
        return $form;
1882
    }
1883
1884
    /**
1885
     * @return array
1886
     */
1887
    public static function getStatusList()
1888
    {
1889
        $items = Database::getManager()->getRepository(TicketStatus::class)->findAll();
1890
1891
        $list = [];
1892
        /** @var TicketStatus $row */
1893
        foreach ($items as $row) {
1894
            $list[$row->getId()] = $row->getTitle();
1895
        }
1896
1897
        return $list;
1898
    }
1899
1900
    /**
1901
     * @param array $criteria
1902
     *
1903
     * @return array
1904
     */
1905
    public static function getTicketsFromCriteria($criteria)
1906
    {
1907
        $items = Database::getManager()->getRepository(Ticket::class)->findBy($criteria);
1908
        $list = [];
1909
        /** @var Ticket $row */
1910
        foreach ($items as $row) {
1911
            $list[$row->getId()] = $row->getCode();
1912
        }
1913
1914
        return $list;
1915
    }
1916
1917
    /**
1918
     * @param string $code
1919
     *
1920
     * @return int
1921
     */
1922
    public static function getStatusIdFromCode($code)
1923
    {
1924
        $item = Database::getManager()
1925
            ->getRepository(TicketStatus::class)
1926
            ->findOneBy(['code' => $code])
1927
        ;
1928
1929
        if ($item) {
1930
            return $item->getId();
1931
        }
1932
1933
        return 0;
1934
    }
1935
1936
    /**
1937
     * @return array
1938
     */
1939
    public static function getPriorityList()
1940
    {
1941
        $projects = Database::getManager()->getRepository(TicketPriority::class)->findAll();
1942
        $list = [];
1943
        /** @var TicketPriority $row */
1944
        foreach ($projects as $row) {
1945
            $list[$row->getId()] = $row->getTitle();
1946
        }
1947
1948
        return $list;
1949
    }
1950
1951
    /**
1952
     * @return array
1953
     */
1954
    public static function getProjects()
1955
    {
1956
        $projects = Database::getManager()->getRepository(TicketProject::class)->findAll();
1957
1958
        $list = [];
1959
        /** @var TicketProject $row */
1960
        foreach ($projects as $row) {
1961
            $list[] = [
1962
                'id' => $row->getId(),
1963
                '0' => $row->getId(),
1964
                '1' => $row->getTitle(),
1965
                '2' => $row->getDescription(),
1966
                '3' => $row->getId(),
1967
            ];
1968
        }
1969
1970
        return $list;
1971
    }
1972
1973
    /**
1974
     * @return array
1975
     */
1976
    public static function getProjectsSimple()
1977
    {
1978
        $projects = Database::getManager()->getRepository(TicketProject::class)->findAll();
1979
        $list = [];
1980
        /** @var TicketProject $row */
1981
        foreach ($projects as $row) {
1982
            $list[] = [
1983
                'id' => $row->getId(),
1984
                '0' => $row->getId(),
1985
                '1' => Display::url(
1986
                    $row->getTitle(),
1987
                    api_get_path(WEB_CODE_PATH).'ticket/tickets.php?project_id='.$row->getId()
1988
                ),
1989
                '2' => $row->getDescription(),
1990
            ];
1991
        }
1992
1993
        return $list;
1994
    }
1995
1996
    /**
1997
     * @return int
1998
     */
1999
    public static function getProjectsCount()
2000
    {
2001
        return Database::getManager()->getRepository(TicketProject::class)->createQueryBuilder('p')
2002
            ->select('COUNT(p.id)')
2003
            ->getQuery()
2004
            ->getSingleScalarResult();
2005
    }
2006
2007
    /**
2008
     * @param array $params
2009
     */
2010
    public static function addProject($params)
2011
    {
2012
        $project = new TicketProject();
2013
        $project->setTitle($params['title']);
2014
        $project->setDescription($params['description']);
2015
        $project->setInsertUserId(api_get_user_id());
2016
2017
        Database::getManager()->persist($project);
2018
        Database::getManager()->flush();
2019
    }
2020
2021
    /**
2022
     * @param int $id
2023
     *
2024
     * @return TicketProject
2025
     */
2026
    public static function getProject($id)
2027
    {
2028
        return Database::getManager()->getRepository(TicketProject::class)->find($id);
2029
    }
2030
2031
    /**
2032
     * @param int   $id
2033
     * @param array $params
2034
     */
2035
    public static function updateProject($id, $params)
2036
    {
2037
        $project = self::getProject($id);
2038
        $project->setTitle($params['title']);
2039
        $project->setDescription($params['description']);
2040
        $project->setLastEditDateTime(new DateTime($params['sys_lastedit_datetime']));
2041
        $project->setLastEditUserId($params['sys_lastedit_user_id']);
2042
2043
        Database::getManager()->persist($project);
2044
        Database::getManager()->flush();
2045
    }
2046
2047
    /**
2048
     * @param int $id
2049
     */
2050
    public static function deleteProject($id)
2051
    {
2052
        $project = self::getProject($id);
2053
        if ($project) {
0 ignored issues
show
introduced by
$project is of type Chamilo\CoreBundle\Entity\TicketProject, thus it always evaluated to true.
Loading history...
2054
            Database::getManager()->remove($project);
2055
            Database::getManager()->flush();
2056
        }
2057
    }
2058
2059
    /**
2060
     * @param string $url
2061
     *
2062
     * @return FormValidator
2063
     */
2064
    public static function getProjectForm($url)
2065
    {
2066
        $form = new FormValidator('project', 'post', $url);
2067
        $form->addText('name', get_lang('Name'));
2068
        $form->addHtmlEditor('description', get_lang('Description'));
2069
        $form->addButtonUpdate(get_lang('Save'));
2070
2071
        return $form;
2072
    }
2073
2074
    /**
2075
     * @return array
2076
     */
2077
    public static function getStatusAdminList()
2078
    {
2079
        $items = Database::getManager()->getRepository(TicketStatus::class)->findAll();
2080
        $list = [];
2081
        /** @var TicketStatus $row */
2082
        foreach ($items as $row) {
2083
            $list[] = [
2084
                'id' => $row->getId(),
2085
                'code' => $row->getCode(),
2086
                '0' => $row->getId(),
2087
                '1' => $row->getTitle(),
2088
                '2' => $row->getDescription(),
2089
                '3' => $row->getId(),
2090
            ];
2091
        }
2092
2093
        return $list;
2094
    }
2095
2096
    /**
2097
     * @return array
2098
     */
2099
    /*public static function getStatusSimple()
2100
    {
2101
        $projects = Database::getManager()->getRepository(TicketStatus::class)->findAll();
2102
        $list = [];
2103
        // @var TicketProject $row
2104
        foreach ($projects as $row) {
2105
            $list[] = [
2106
                'id' => $row->getId(),
2107
                '0' => $row->getId(),
2108
                '1' => Display::url($row->getName()),
2109
                '2' => $row->getDescription(),
2110
            ];
2111
        }
2112
2113
        return $list;
2114
    }*/
2115
2116
    /**
2117
     * @return int
2118
     */
2119
    public static function getStatusCount()
2120
    {
2121
        return Database::getManager()->getRepository(TicketStatus::class)->createQueryBuilder('p')
2122
            ->select('COUNT(p.id)')
2123
            ->getQuery()
2124
            ->getSingleScalarResult();
2125
    }
2126
2127
    /**
2128
     * @param array $params
2129
     */
2130
    public static function addStatus($params)
2131
    {
2132
        $item = new TicketStatus();
2133
        $item->setCode(URLify::filter($params['title']));
2134
        $item->setTitle($params['title']);
2135
        $item->setDescription($params['description']);
2136
2137
        Database::getManager()->persist($item);
2138
        Database::getManager()->flush();
2139
    }
2140
2141
    /**
2142
     * @param $id
2143
     *
2144
     * @return TicketProject
2145
     */
2146
    public static function getStatus($id)
2147
    {
2148
        return Database::getManager()->getRepository(TicketStatus::class)->find($id);
2149
    }
2150
2151
    /**
2152
     * @param int   $id
2153
     * @param array $params
2154
     */
2155
    public static function updateStatus($id, $params)
2156
    {
2157
        $item = self::getStatus($id);
2158
        $item->setTitle($params['title']);
2159
        $item->setDescription($params['description']);
2160
2161
        Database::getManager()->persist($item);
2162
        Database::getManager()->flush();
2163
    }
2164
2165
    /**
2166
     * @param int $id
2167
     */
2168
    public static function deleteStatus($id)
2169
    {
2170
        $item = self::getStatus($id);
2171
        if ($item) {
0 ignored issues
show
introduced by
$item is of type Chamilo\CoreBundle\Entity\TicketProject, thus it always evaluated to true.
Loading history...
2172
            Database::getManager()->remove($item);
2173
            Database::getManager()->flush();
2174
        }
2175
    }
2176
2177
    /**
2178
     * @param string $url
2179
     *
2180
     * @return FormValidator
2181
     */
2182
    public static function getStatusForm($url)
2183
    {
2184
        $form = new FormValidator('status', 'post', $url);
2185
        $form->addText('name', get_lang('Name'));
2186
        $form->addHtmlEditor('description', get_lang('Description'));
2187
        $form->addButtonUpdate(get_lang('Save'));
2188
2189
        return $form;
2190
    }
2191
2192
    /**
2193
     * @return array
2194
     */
2195
    public static function getPriorityAdminList()
2196
    {
2197
        $items = Database::getManager()->getRepository(TicketPriority::class)->findAll();
2198
2199
        $list = [];
2200
        /** @var TicketStatus $row */
2201
        foreach ($items as $row) {
2202
            $list[] = [
2203
                'id' => $row->getId(),
2204
                'code' => $row->getCode(),
2205
                '0' => $row->getId(),
2206
                '1' => $row->getTitle(),
2207
                '2' => $row->getDescription(),
2208
                '3' => $row->getId(),
2209
            ];
2210
        }
2211
2212
        return $list;
2213
    }
2214
2215
    /**
2216
     * @return int
2217
     */
2218
    public static function getPriorityCount()
2219
    {
2220
        return Database::getManager()->getRepository(TicketPriority::class)->createQueryBuilder('p')
2221
            ->select('COUNT(p.id)')
2222
            ->getQuery()
2223
            ->getSingleScalarResult();
2224
    }
2225
2226
    /**
2227
     * @param array $params
2228
     */
2229
    public static function addPriority($params)
2230
    {
2231
        $item = new TicketPriority();
2232
        $item
2233
            ->setCode(URLify::filter($params['title']))
2234
            ->setTitle($params['title'])
2235
            ->setDescription($params['description'])
2236
            ->setColor('')
2237
            ->setInsertUserId(api_get_user_id())
2238
            ->setUrgency('')
2239
        ;
2240
2241
        Database::getManager()->persist($item);
2242
        Database::getManager()->flush();
2243
    }
2244
2245
    /**
2246
     * @param $id
2247
     *
2248
     * @return TicketPriority
2249
     */
2250
    public static function getPriority($id)
2251
    {
2252
        return Database::getManager()->getRepository(TicketPriority::class)->find($id);
2253
    }
2254
2255
    /**
2256
     * @param int   $id
2257
     * @param array $params
2258
     */
2259
    public static function updatePriority($id, $params)
2260
    {
2261
        $item = self::getPriority($id);
2262
        $item->setTitle($params['title']);
2263
        $item->setDescription($params['description']);
2264
2265
        Database::getManager()->persist($item);
2266
        Database::getManager()->flush();
2267
    }
2268
2269
    /**
2270
     * @param int $id
2271
     */
2272
    public static function deletePriority($id)
2273
    {
2274
        $item = self::getPriority($id);
2275
        if ($item) {
0 ignored issues
show
introduced by
$item is of type Chamilo\CoreBundle\Entity\TicketPriority, thus it always evaluated to true.
Loading history...
2276
            Database::getManager()->remove($item);
2277
            Database::getManager()->flush();
2278
        }
2279
    }
2280
2281
    /**
2282
     * @param string $url
2283
     *
2284
     * @return FormValidator
2285
     */
2286
    public static function getPriorityForm($url)
2287
    {
2288
        $form = new FormValidator('priority', 'post', $url);
2289
        $form->addText('name', get_lang('Name'));
2290
        $form->addHtmlEditor('description', get_lang('Description'));
2291
        $form->addButtonUpdate(get_lang('Save'));
2292
2293
        return $form;
2294
    }
2295
2296
    /**
2297
     * Returns a list of menu elements for the tickets system's configuration.
2298
     *
2299
     * @param string $exclude The element to exclude from the list
2300
     *
2301
     * @return array
2302
     */
2303
    public static function getSettingsMenuItems($exclude = null)
2304
    {
2305
        $project = [
2306
            'icon' => ObjectIcon::PROJECT,
2307
            'url' => 'projects.php',
2308
            'content' => get_lang('Projects'),
2309
        ];
2310
        $status = [
2311
            'icon' => StateIcon::COMPLETE,
2312
            'url' => 'status.php',
2313
            'content' => get_lang('Status'),
2314
        ];
2315
        $priority = [
2316
            'icon' => StateIcon::EXPIRED,
2317
            'url' => 'priorities.php',
2318
            'content' => get_lang('Priority'),
2319
        ];
2320
        switch ($exclude) {
2321
            case 'project':
2322
                $items = [$status, $priority];
2323
                break;
2324
            case 'status':
2325
                $items = [$project, $priority];
2326
                break;
2327
            case 'priority':
2328
                $items = [$project, $status];
2329
                break;
2330
            default:
2331
                $items = [$project, $status, $priority];
2332
                break;
2333
        }
2334
2335
        return $items;
2336
    }
2337
2338
    /**
2339
     * Returns a list of strings representing the default statuses.
2340
     *
2341
     * @return array
2342
     */
2343
    public static function getDefaultStatusList()
2344
    {
2345
        return [
2346
            self::STATUS_NEW,
2347
            self::STATUS_PENDING,
2348
            self::STATUS_UNCONFIRMED,
2349
            self::STATUS_CLOSE,
2350
            self::STATUS_FORWARDED,
2351
        ];
2352
    }
2353
2354
    /**
2355
     * @return array
2356
     */
2357
    public static function getDefaultPriorityList()
2358
    {
2359
        return [
2360
            self::PRIORITY_NORMAL,
2361
            self::PRIORITY_HIGH,
2362
            self::PRIORITY_LOW,
2363
            self::STATUS_CLOSE,
2364
            self::STATUS_FORWARDED,
2365
        ];
2366
    }
2367
2368
    /**
2369
     * Deletes the user from all the ticket system.
2370
     *
2371
     * @param int $userId
2372
     */
2373
    public static function deleteUserFromTicketSystem($userId)
2374
    {
2375
        $userId = (int) $userId;
2376
        $schema = Database::getManager()->getConnection()->createSchemaManager();
2377
2378
        if ($schema->tablesExist('ticket_assigned_log')) {
2379
            $sql = "UPDATE ticket_assigned_log SET user_id = NULL WHERE user_id = $userId";
2380
            Database::query($sql);
2381
2382
            $sql = "UPDATE ticket_assigned_log SET sys_insert_user_id = NULL WHERE sys_insert_user_id = $userId";
2383
            Database::query($sql);
2384
        }
2385
2386
        if ($schema->tablesExist('ticket_ticket')) {
2387
            $sql = "UPDATE ticket_ticket SET assigned_last_user = NULL WHERE assigned_last_user = $userId";
2388
            Database::query($sql);
2389
2390
            $sql = "UPDATE ticket_ticket SET sys_insert_user_id = NULL WHERE sys_insert_user_id = $userId";
2391
            Database::query($sql);
2392
2393
            $sql = "UPDATE ticket_ticket SET sys_lastedit_user_id = NULL WHERE sys_lastedit_user_id = $userId";
2394
            Database::query($sql);
2395
        }
2396
2397
        if ($schema->tablesExist('ticket_category')) {
2398
            $sql = "UPDATE ticket_category SET sys_insert_user_id = NULL WHERE sys_insert_user_id = $userId";
2399
            Database::query($sql);
2400
2401
            $sql = "UPDATE ticket_category SET sys_lastedit_user_id = NULL WHERE sys_lastedit_user_id = $userId";
2402
            Database::query($sql);
2403
        }
2404
2405
        if ($schema->tablesExist('ticket_category_rel_user')) {
2406
            $sql = "DELETE FROM ticket_category_rel_user WHERE user_id = $userId";
2407
            Database::query($sql);
2408
        }
2409
2410
        if ($schema->tablesExist('ticket_message')) {
2411
            $sql = "UPDATE ticket_message SET sys_insert_user_id = NULL WHERE sys_insert_user_id = $userId";
2412
            Database::query($sql);
2413
2414
            $sql = "UPDATE ticket_message SET sys_lastedit_user_id = NULL WHERE sys_lastedit_user_id = $userId";
2415
            Database::query($sql);
2416
        }
2417
2418
        if ($schema->tablesExist('ticket_message_attachments')) {
2419
            $sql = "UPDATE ticket_message_attachments SET sys_insert_user_id = NULL WHERE sys_insert_user_id = $userId";
2420
            Database::query($sql);
2421
2422
            $sql = "UPDATE ticket_message_attachments SET sys_lastedit_user_id = NULL WHERE sys_lastedit_user_id = $userId";
2423
            Database::query($sql);
2424
        }
2425
2426
        if ($schema->tablesExist('ticket_priority')) {
2427
            $sql = "UPDATE ticket_priority SET sys_insert_user_id = NULL WHERE sys_insert_user_id = $userId";
2428
            Database::query($sql);
2429
2430
            $sql = "UPDATE ticket_priority SET sys_lastedit_user_id = NULL WHERE sys_lastedit_user_id = $userId";
2431
            Database::query($sql);
2432
        }
2433
2434
        if ($schema->tablesExist('ticket_project')) {
2435
            $sql = "UPDATE ticket_project SET sys_insert_user_id = NULL WHERE sys_insert_user_id = $userId";
2436
            Database::query($sql);
2437
2438
            $sql = "UPDATE ticket_project SET sys_lastedit_user_id = NULL WHERE sys_lastedit_user_id = $userId";
2439
            Database::query($sql);
2440
        }
2441
    }
2442
2443
    /**
2444
     * @deprecated Use TicketProjectHelper::userIsAllowInProject instead
2445
     */
2446
    public static function userIsAllowInProject(int $projectId): bool
2447
    {
2448
        $authorizationChecked = Container::getAuthorizationChecker();
2449
2450
        if ($authorizationChecked->isGranted('ROLE_ADMIN')) {
2451
            return true;
2452
        }
2453
2454
        $allowRoleList = self::getAllowedRolesFromProject($projectId);
0 ignored issues
show
Deprecated Code introduced by
The function TicketManager::getAllowedRolesFromProject() has been deprecated: Use TicketProjectHelper::getAllowedRolesFromProject instead ( Ignorable by Annotation )

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

2454
        $allowRoleList = /** @scrutinizer ignore-deprecated */ self::getAllowedRolesFromProject($projectId);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
2455
2456
        // Check if a role was set to the project.
2457
        // Project 1 is considered the default and is accessible to all users
2458
        if (!empty($allowRoleList)) {
2459
            $result = false;
2460
            foreach ($allowRoleList as $role) {
2461
                if ($authorizationChecked->isGranted($role)) {
2462
                    $result = true;
2463
                    break;
2464
                }
2465
            }
2466
2467
            return $result;
2468
        }
2469
2470
        return false;
2471
    }
2472
2473
    /**
2474
     * @deprecated Use TicketProjectHelper::getAllowedRolesFromProject instead
2475
     */
2476
    public static function getAllowedRolesFromProject(int $projectId): array
2477
    {
2478
        // Define a mapping from role IDs to role names
2479
        $roleMap = [
2480
            1 => 'ROLE_TEACHER',
2481
            17 => 'ROLE_STUDENT_BOSS',
2482
            4 => 'ROLE_HR',
2483
            3 => 'ROLE_SESSION_MANAGER',
2484
            // ... other mappings can be added as needed
2485
        ];
2486
2487
        $jsonString = Container::getSettingsManager()->getSetting('ticket.ticket_project_user_roles');
2488
2489
        if (empty($jsonString)) {
2490
            return [];
2491
        }
2492
2493
        $data = json_decode($jsonString, true);
2494
2495
        if (JSON_ERROR_NONE !== json_last_error()) {
2496
            // Invalid JSON
2497
            return [];
2498
        }
2499
2500
        if (!isset($data['permissions'][$projectId])) {
2501
            // No permissions for the given projectId
2502
            return [];
2503
        }
2504
2505
        $roleIds = $data['permissions'][$projectId];
2506
2507
        // Transform role IDs into role names using the defined mapping
2508
        return array_map(function ($roleId) use ($roleMap) {
2509
            return $roleMap[$roleId] ?? "$roleId";
2510
        }, $roleIds);
2511
    }
2512
2513
    /**
2514
     * Subscribes a user to a ticket.
2515
     */
2516
    public static function subscribeUserToTicket(int $ticketId, int $userId): void
2517
    {
2518
        $em = Database::getManager();
2519
        $ticket = $em->getRepository(Ticket::class)->find($ticketId);
2520
        $user = $em->getRepository(User::class)->find($userId);
2521
2522
        if ($ticket && $user) {
2523
            $repository = $em->getRepository(TicketRelUser::class);
2524
            $repository->subscribeUserToTicket($user, $ticket);
2525
2526
            Event::addEvent(
0 ignored issues
show
Bug introduced by
The method addEvent() does not exist on Event. ( Ignorable by Annotation )

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

2526
            Event::/** @scrutinizer ignore-call */ 
2527
                   addEvent(

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...
2527
                'ticket_subscribe',
2528
                'ticket_event',
2529
                ['user_id' => $userId, 'ticket_id' => $ticketId, 'action' => 'subscribe']
2530
            );
2531
        }
2532
    }
2533
2534
    /**
2535
     * Unsubscribes a user from a ticket.
2536
     */
2537
    public static function unsubscribeUserFromTicket(int $ticketId, int $userId): void
2538
    {
2539
        $em = Database::getManager();
2540
        $ticket = $em->getRepository(Ticket::class)->find($ticketId);
2541
        $user = $em->getRepository(User::class)->find($userId);
2542
2543
        if ($ticket && $user) {
2544
            $repository = $em->getRepository(TicketRelUser::class);
2545
            $repository->unsubscribeUserFromTicket($user, $ticket);
2546
2547
            Event::addEvent(
2548
                'ticket_unsubscribe',
2549
                'ticket_event',
2550
                ['user_id' => $userId, 'ticket_id' => $ticketId, 'action' => 'unsubscribe']
2551
            );
2552
        }
2553
    }
2554
2555
    /**
2556
     * Checks if a user is subscribed to a ticket.
2557
     */
2558
    public static function isUserSubscribedToTicket(int $ticketId, int $userId): bool
2559
    {
2560
        $em = Database::getManager();
2561
        $ticket = $em->getRepository(Ticket::class)->find($ticketId);
2562
        $user = $em->getRepository(User::class)->find($userId);
2563
2564
        if ($ticket && $user) {
2565
            $repository = $em->getRepository(TicketRelUser::class);
2566
            return $repository->isUserSubscribedToTicket($user, $ticket);
2567
        }
2568
2569
        return false;
2570
    }
2571
2572
    /**
2573
     * Retrieves the followers of a ticket.
2574
     */
2575
    public static function getFollowers($ticketId): array
2576
    {
2577
        $em = Database::getManager();
2578
        $repository = $em->getRepository(TicketRelUser::class);
2579
        $ticket = $em->getRepository(Ticket::class)->find($ticketId);
2580
2581
        $followers = $repository->findBy(['ticket' => $ticket]);
2582
2583
        $users = [];
2584
        foreach ($followers as $follower) {
2585
            $users[] = $follower->getUser();
2586
        }
2587
2588
        return $users;
2589
    }
2590
2591
    /**
2592
     * Generates an unsubscribe link for a ticket.
2593
     */
2594
    public static function generateUnsubscribeLink($ticketId, $userId): string
2595
    {
2596
        $token = new ValidationToken(ValidationTokenHelper::TYPE_TICKET, $ticketId);
2597
        Database::getManager()->persist($token);
2598
        Database::getManager()->flush();
2599
2600
        return api_get_path(WEB_PATH).'validate/ticket/'.$token->getHash().'?user_id='.$userId;
2601
    }
2602
}
2603