Passed
Push — master ( 5a2f2e...a7c512 )
by Julito
07:01
created

TicketManager::update_ticket_status()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 31
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 18
nc 2
nop 3
dl 0
loc 31
rs 9.6666
c 0
b 0
f 0
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\Ticket;
6
use Chamilo\CoreBundle\Entity\TicketMessageAttachment;
7
use Chamilo\CoreBundle\Entity\TicketPriority;
8
use Chamilo\CoreBundle\Entity\TicketProject;
9
use Chamilo\CoreBundle\Entity\TicketStatus;
10
use Chamilo\CoreBundle\Framework\Container;
11
use Chamilo\CourseBundle\Entity\CLp;
12
13
/**
14
 * Class TicketManager.
15
 */
16
class TicketManager
17
{
18
    public const PRIORITY_NORMAL = 'NRM';
19
    public const PRIORITY_HIGH = 'HGH';
20
    public const PRIORITY_LOW = 'LOW';
21
22
    public const SOURCE_EMAIL = 'MAI';
23
    public const SOURCE_PHONE = 'TEL';
24
    public const SOURCE_PLATFORM = 'PLA';
25
    public const SOURCE_PRESENTIAL = 'PRE';
26
27
    public const STATUS_NEW = 'NAT';
28
    public const STATUS_PENDING = 'PND';
29
    public const STATUS_UNCONFIRMED = 'XCF';
30
    public const STATUS_CLOSE = 'CLS';
31
    public const STATUS_FORWARDED = 'REE';
32
33
    public function __construct()
34
    {
35
    }
36
37
    /**
38
     * Get categories of tickets.
39
     *
40
     * @param int    $projectId
41
     * @param string $order
42
     *
43
     * @return array
44
     */
45
    public static function get_all_tickets_categories($projectId, $order = '')
46
    {
47
        $table_support_category = Database::get_main_table(TABLE_TICKET_CATEGORY);
48
        $table_support_project = Database::get_main_table(TABLE_TICKET_PROJECT);
49
50
        $order = empty($order) ? 'category.total_tickets DESC' : $order;
51
        $order = Database::escape_string($order);
52
        $projectId = (int) $projectId;
53
54
        $sql = "SELECT
55
                    category.*,
56
                    category.id category_id,
57
                    project.other_area,
58
                    project.email
59
                FROM
60
                $table_support_category category
61
                INNER JOIN $table_support_project project
62
                ON project.id = category.project_id
63
                WHERE project.id  = $projectId
64
                ORDER BY $order";
65
        $result = Database::query($sql);
66
        $types = [];
67
        while ($row = Database::fetch_assoc($result)) {
68
            $types[] = $row;
69
        }
70
71
        return $types;
72
    }
73
74
    /**
75
     * @param $from
76
     * @param $numberItems
77
     * @param $column
78
     * @param $direction
79
     *
80
     * @return array
81
     */
82
    public static function getCategories($from, $numberItems, $column, $direction)
83
    {
84
        $table = Database::get_main_table(TABLE_TICKET_CATEGORY);
85
        $sql = "SELECT id, name, description, total_tickets
86
                FROM $table";
87
88
        if (!in_array($direction, ['ASC', 'DESC'])) {
89
            $direction = 'ASC';
90
        }
91
        $column = (int) $column;
92
        $from = (int) $from;
93
        $numberItems = (int) $numberItems;
94
95
        //$sql .= " ORDER BY col$column $direction ";
96
        $sql .= " LIMIT $from,$numberItems";
97
98
        $result = Database::query($sql);
99
        $types = [];
100
        while ($row = Database::fetch_array($result)) {
101
            $types[] = $row;
102
        }
103
104
        return $types;
105
    }
106
107
    /**
108
     * @param int $id
109
     *
110
     * @return array|mixed
111
     */
112
    public static function getCategory($id)
113
    {
114
        $table = Database::get_main_table(TABLE_TICKET_CATEGORY);
115
        $id = (int) $id;
116
        $sql = "SELECT id, name, description, total_tickets
117
                FROM $table WHERE id = $id";
118
119
        $result = Database::query($sql);
120
        $category = Database::fetch_array($result);
121
122
        return $category;
123
    }
124
125
    /**
126
     * @return int
127
     */
128
    public static function getCategoriesCount()
129
    {
130
        $table = Database::get_main_table(TABLE_TICKET_CATEGORY);
131
132
        $sql = "SELECT count(id) count
133
                FROM $table ";
134
135
        $result = Database::query($sql);
136
        $category = Database::fetch_array($result);
137
138
        return $category['count'];
139
    }
140
141
    /**
142
     * @param int   $id
143
     * @param array $params
144
     */
145
    public static function updateCategory($id, $params)
146
    {
147
        $table = Database::get_main_table(TABLE_TICKET_CATEGORY);
148
        $id = (int) $id;
149
        Database::update($table, $params, ['id = ?' => $id]);
150
    }
151
152
    /**
153
     * @param array $params
154
     */
155
    public static function addCategory($params)
156
    {
157
        $table = Database::get_main_table(TABLE_TICKET_CATEGORY);
158
        Database::insert($table, $params);
159
    }
160
161
    /**
162
     * @param int $id
163
     *
164
     * @return bool
165
     */
166
    public static function deleteCategory($id)
167
    {
168
        $id = (int) $id;
169
        if (empty($id)) {
170
            return false;
171
        }
172
173
        $table = Database::get_main_table(TABLE_TICKET_TICKET);
174
        $sql = "UPDATE $table SET category_id = NULL WHERE category_id = $id";
175
        Database::query($sql);
176
177
        $table = Database::get_main_table(TABLE_TICKET_CATEGORY);
178
        $sql = "DELETE FROM $table WHERE id = $id";
179
        Database::query($sql);
180
181
        return true;
182
    }
183
184
    /**
185
     * @param int   $categoryId
186
     * @param array $users
187
     *
188
     * @return bool
189
     */
190
    public static function addUsersToCategory($categoryId, $users)
191
    {
192
        if (empty($users) || empty($categoryId)) {
193
            return false;
194
        }
195
196
        $table = Database::get_main_table(TABLE_TICKET_CATEGORY_REL_USER);
197
        foreach ($users as $userId) {
198
            if (false === self::userIsAssignedToCategory($userId, $categoryId)) {
199
                $params = [
200
                    'category_id' => $categoryId,
201
                    'user_id' => $userId,
202
                ];
203
                Database::insert($table, $params);
204
            }
205
        }
206
207
        return true;
208
    }
209
210
    /**
211
     * @param int $userId
212
     * @param int $categoryId
213
     *
214
     * @return bool
215
     */
216
    public static function userIsAssignedToCategory($userId, $categoryId)
217
    {
218
        $table = Database::get_main_table(TABLE_TICKET_CATEGORY_REL_USER);
219
        $userId = (int) $userId;
220
        $categoryId = (int) $categoryId;
221
        $sql = "SELECT * FROM $table
222
                WHERE category_id = $categoryId AND user_id = $userId";
223
        $result = Database::query($sql);
224
225
        return Database::num_rows($result) > 0;
226
    }
227
228
    /**
229
     * @param int $categoryId
230
     *
231
     * @return array
232
     */
233
    public static function getUsersInCategory($categoryId)
234
    {
235
        $table = Database::get_main_table(TABLE_TICKET_CATEGORY_REL_USER);
236
        $categoryId = (int) $categoryId;
237
        $sql = "SELECT * FROM $table WHERE category_id = $categoryId";
238
        $result = Database::query($sql);
239
240
        return Database::store_result($result);
241
    }
242
243
    /**
244
     * @param int $categoryId
245
     */
246
    public static function deleteAllUserInCategory($categoryId)
247
    {
248
        $table = Database::get_main_table(TABLE_TICKET_CATEGORY_REL_USER);
249
        $categoryId = (int) $categoryId;
250
        $sql = "DELETE FROM $table WHERE category_id = $categoryId";
251
        Database::query($sql);
252
    }
253
254
    /**
255
     * Get all possible tickets statuses.
256
     *
257
     * @return array
258
     */
259
    public static function get_all_tickets_status()
260
    {
261
        $table = Database::get_main_table(TABLE_TICKET_STATUS);
262
        $sql = "SELECT * FROM $table";
263
        $result = Database::query($sql);
264
        $types = [];
265
        while ($row = Database::fetch_assoc($result)) {
266
            $types[] = $row;
267
        }
268
269
        return $types;
270
    }
271
272
    /**
273
     * Inserts a new ticket in the corresponding tables.
274
     *
275
     * @param int    $category_id
276
     * @param int    $course_id
277
     * @param int    $sessionId
278
     * @param int    $project_id
279
     * @param string $other_area
280
     * @param string $subject
281
     * @param string $content
282
     * @param string $personalEmail
283
     * @param array  $fileAttachments
284
     * @param string $source
285
     * @param string $priority
286
     * @param string $status
287
     * @param int    $assignedUserId
288
     * @param int    $exerciseId
289
     * @param int    $lpId
290
     *
291
     * @return bool
292
     */
293
    public static function add(
294
        $category_id,
295
        $course_id,
296
        $sessionId,
297
        $project_id,
298
        $other_area,
299
        $subject,
300
        $content,
301
        $personalEmail = '',
302
        $fileAttachments = [],
303
        $source = '',
304
        $priority = '',
305
        $status = '',
306
        $assignedUserId = 0,
307
        $exerciseId = null,
308
        $lpId = null
309
    ) {
310
        $table_support_tickets = Database::get_main_table(TABLE_TICKET_TICKET);
311
        $table_support_category = Database::get_main_table(TABLE_TICKET_CATEGORY);
312
313
        if (empty($category_id)) {
314
            return false;
315
        }
316
317
        $currentUserId = api_get_user_id();
318
        $currentUserInfo = api_get_user_info();
319
        $now = api_get_utc_datetime();
320
        $course_id = (int) $course_id;
321
        $category_id = (int) $category_id;
322
        $project_id = (int) $project_id;
323
        $priority = empty($priority) ? self::PRIORITY_NORMAL : (int) $priority;
324
325
        if ('' === $status) {
326
            $status = self::STATUS_NEW;
327
            if ($other_area > 0) {
328
                $status = self::STATUS_FORWARDED;
329
            }
330
        }
331
332
        if (!empty($category_id)) {
333
            if (empty($assignedUserId)) {
334
                $usersInCategory = self::getUsersInCategory($category_id);
335
                if (!empty($usersInCategory) && count($usersInCategory) > 0) {
336
                    $userCategoryInfo = $usersInCategory[0];
337
                    if (isset($userCategoryInfo['user_id'])) {
338
                        $assignedUserId = $userCategoryInfo['user_id'];
339
                    }
340
                }
341
            }
342
        }
343
344
        $assignedUserInfo = [];
345
        if (!empty($assignedUserId)) {
346
            $assignedUserInfo = api_get_user_info($assignedUserId);
347
            if (empty($assignedUserInfo)) {
348
                return false;
349
            }
350
        }
351
352
        // insert_ticket
353
        $params = [
354
            'project_id' => $project_id,
355
            'category_id' => $category_id,
356
            'priority_id' => $priority,
357
            'personal_email' => $personalEmail,
358
            'status_id' => $status,
359
            'start_date' => $now,
360
            'sys_insert_user_id' => $currentUserId,
361
            'sys_insert_datetime' => $now,
362
            'sys_lastedit_user_id' => $currentUserId,
363
            'sys_lastedit_datetime' => $now,
364
            'source' => $source,
365
            'assigned_last_user' => $assignedUserId,
366
            'subject' => $subject,
367
            'message' => $content,
368
            'code' => '',
369
            'total_messages' => 0,
370
        ];
371
372
        if (!empty($exerciseId)) {
373
            $params['exercise_id'] = $exerciseId;
374
        }
375
376
        if (!empty($lpId)) {
377
            $params['lp_id'] = $lpId;
378
        }
379
        if (!empty($course_id)) {
380
            $params['course_id'] = $course_id;
381
        }
382
383
        if (!empty($sessionId)) {
384
            $params['session_id'] = $sessionId;
385
        }
386
        $ticketId = Database::insert($table_support_tickets, $params);
387
388
        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...
389
            $ticket_code = 'A'.str_pad($ticketId, 11, '0', STR_PAD_LEFT);
390
            $titleCreated = sprintf(
391
                get_lang('Ticket %s created'),
392
                $ticket_code
393
            );
394
395
            Display::addFlash(Display::return_message(
396
                $titleCreated,
397
                'normal',
398
                false
399
            ));
400
401
            if (0 != $assignedUserId) {
402
                self::assignTicketToUser(
403
                    $ticketId,
404
                    $assignedUserId
405
                );
406
407
                Display::addFlash(Display::return_message(
408
                    sprintf(
409
                        get_lang('TicketXAssignedToUserX'),
410
                        $ticket_code,
411
                        $assignedUserInfo['complete_name']
412
                    ),
413
                    'normal',
414
                    false
415
                ));
416
            }
417
418
            if (!empty($fileAttachments)) {
419
                $attachmentCount = 0;
420
                foreach ($fileAttachments as $attach) {
421
                    if (!empty($attach['tmp_name'])) {
422
                        $attachmentCount++;
423
                    }
424
                }
425
                if ($attachmentCount > 0) {
426
                    self::insertMessage(
427
                        $ticketId,
428
                        '',
429
                        '',
430
                        $fileAttachments,
431
                        $currentUserId
432
                    );
433
                }
434
            }
435
436
            // Update code
437
            $sql = "UPDATE $table_support_tickets
438
                    SET code = '$ticket_code'
439
                    WHERE id = '$ticketId'";
440
            Database::query($sql);
441
442
            // Update total
443
            $sql = "UPDATE $table_support_category
444
                    SET total_tickets = total_tickets + 1
445
                    WHERE id = $category_id";
446
            Database::query($sql);
447
448
            $helpDeskMessage =
449
                '<table>
450
                        <tr>
451
                            <td width="100px"><b>'.get_lang('User').'</b></td>
452
                            <td width="400px">'.$currentUserInfo['complete_name'].'</td>
453
                        </tr>
454
                        <tr>
455
                            <td width="100px"><b>'.get_lang('Username').'</b></td>
456
                            <td width="400px">'.$currentUserInfo['username'].'</td>
457
                        </tr>
458
                        <tr>
459
                            <td width="100px"><b>'.get_lang('Email').'</b></td>
460
                            <td width="400px">'.$currentUserInfo['email'].'</td>
461
                        </tr>
462
                        <tr>
463
                            <td width="100px"><b>'.get_lang('Phone').'</b></td>
464
                            <td width="400px">'.$currentUserInfo['phone'].'</td>
465
                        </tr>
466
                        <tr>
467
                            <td width="100px"><b>'.get_lang('Date').'</b></td>
468
                            <td width="400px">'.api_convert_and_format_date($now, DATE_TIME_FORMAT_LONG).'</td>
469
                        </tr>
470
                        <tr>
471
                            <td width="100px"><b>'.get_lang('Title').'</b></td>
472
                            <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

472
                            <td width="400px">'./** @scrutinizer ignore-type */ Security::remove_XSS($subject).'</td>
Loading history...
473
                        </tr>
474
                        <tr>
475
                            <td width="100px"><b>'.get_lang('Description').'</b></td>
476
                            <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

476
                            <td width="400px">'./** @scrutinizer ignore-type */ Security::remove_XSS($content).'</td>
Loading history...
477
                        </tr>
478
                    </table>';
479
480
            if (0 != $assignedUserId) {
481
                $href = api_get_path(WEB_CODE_PATH).'/ticket/ticket_details.php?ticket_id='.$ticketId;
482
                $helpDeskMessage .= sprintf(
483
                    get_lang('TicketAssignedToXCheckZAtLinkY'),
484
                    $assignedUserInfo['complete_name'],
485
                    $href,
486
                    $ticketId
487
                );
488
            }
489
490
            if (empty($category_id)) {
491
                if ('true' === api_get_setting('ticket_send_warning_to_all_admins')) {
492
                    $warningSubject = sprintf(
493
                        get_lang('Ticket %s createdWithNoCategory'),
494
                        $ticket_code
495
                    );
496
                    Display::addFlash(Display::return_message($warningSubject));
497
498
                    $admins = UserManager::get_all_administrators();
499
                    foreach ($admins as $userId => $data) {
500
                        if ($data['active']) {
501
                            MessageManager::send_message_simple(
502
                                $userId,
503
                                $warningSubject,
504
                                $helpDeskMessage
505
                            );
506
                        }
507
                    }
508
                }
509
            } else {
510
                $categoryInfo = self::getCategory($category_id);
511
                $usersInCategory = self::getUsersInCategory($category_id);
512
                $message = '<h2>'.get_lang('Ticket info').'</h2><br />'.$helpDeskMessage;
513
514
                if ('true' === api_get_setting('ticket_warn_admin_no_user_in_category')) {
515
                    $usersInCategory = self::getUsersInCategory($category_id);
516
                    if (empty($usersInCategory)) {
517
                        $subject = sprintf(
518
                            get_lang('Warning: No one has been assigned to category %s'),
519
                            $categoryInfo['name']
520
                        );
521
522
                        if ('true' === api_get_setting('ticket_send_warning_to_all_admins')) {
523
                            Display::addFlash(Display::return_message(
524
                                sprintf(
525
                                    get_lang(
526
                                        'A notification was sent to the administrators to report this category has no user assigned'
527
                                    ),
528
                                    $categoryInfo['name']
529
                                ),
530
                                null,
531
                                false
532
                            ));
533
534
                            $admins = UserManager::get_all_administrators();
535
                            foreach ($admins as $userId => $data) {
536
                                if ($data['active']) {
537
                                    self::sendNotification(
538
                                        $ticketId,
539
                                        $subject,
540
                                        $message,
541
                                        $userId
542
                                    );
543
                                }
544
                            }
545
                        } else {
546
                            Display::addFlash(Display::return_message($subject));
547
                        }
548
                    }
549
                }
550
551
                // Send notification to all users
552
                if (!empty($usersInCategory)) {
553
                    foreach ($usersInCategory as $data) {
554
                        if ($data['user_id']) {
555
                            self::sendNotification(
556
                                $ticketId,
557
                                $subject,
558
                                $message,
559
                                $data['user_id']
560
                            );
561
                        }
562
                    }
563
                }
564
            }
565
566
            if (!empty($personalEmail)) {
567
                api_mail_html(
568
                    get_lang('Virtual support'),
569
                    $personalEmail,
570
                    get_lang('IncidentResentToVirtual support'),
571
                    $helpDeskMessage
572
                );
573
            }
574
575
            self::sendNotification(
576
                $ticketId,
577
                $titleCreated,
578
                $helpDeskMessage
579
            );
580
581
            return true;
582
        }
583
584
        return false;
585
    }
586
587
    /**
588
     * Assign ticket to admin.
589
     *
590
     * @param int $ticketId
591
     * @param int $userId
592
     *
593
     * @return bool
594
     */
595
    public static function assignTicketToUser(
596
        $ticketId,
597
        $userId
598
    ) {
599
        $ticketId = (int) $ticketId;
600
        $userId = (int) $userId;
601
602
        if (empty($ticketId)) {
603
            return false;
604
        }
605
606
        $ticket = self::get_ticket_detail_by_id($ticketId);
607
608
        if ($ticket) {
609
            $table = Database::get_main_table(TABLE_TICKET_TICKET);
610
            $sql = "UPDATE $table
611
                    SET assigned_last_user = $userId
612
                    WHERE id = $ticketId";
613
            Database::query($sql);
614
615
            $table = Database::get_main_table(TABLE_TICKET_ASSIGNED_LOG);
616
            $params = [
617
                'ticket_id' => $ticketId,
618
                'user_id' => $userId,
619
                'sys_insert_user_id' => api_get_user_id(),
620
                'assigned_date' => api_get_utc_datetime(),
621
            ];
622
            Database::insert($table, $params);
623
624
            return true;
625
        } else {
626
            return false;
627
        }
628
    }
629
630
    /**
631
     * Insert message between Users and Admins.
632
     *
633
     * @param int    $ticketId
634
     * @param string $subject
635
     * @param string $content
636
     * @param array  $fileAttachments
637
     * @param int    $userId
638
     * @param string $status
639
     * @param bool   $sendConfirmation
640
     *
641
     * @return bool
642
     */
643
    public static function insertMessage(
644
        $ticketId,
645
        $subject,
646
        $content,
647
        $fileAttachments,
648
        $userId,
649
        $status = 'NOL',
650
        $sendConfirmation = false
651
    ) {
652
        $ticketId = (int) $ticketId;
653
        $userId = (int) $userId;
654
        $table_support_messages = Database::get_main_table(TABLE_TICKET_MESSAGE);
655
        $table_support_tickets = Database::get_main_table(TABLE_TICKET_TICKET);
656
        if ($sendConfirmation) {
657
            $form =
658
                '<form action="ticket_details.php?ticket_id='.$ticketId.'" id="confirmticket" method="POST" >
659
                     <p>'.get_lang('Was this answer satisfactory?').'</p>
660
                     <button class="btn btn-primary responseyes" name="response" id="responseyes" value="1">'.
661
                get_lang('Yes').'</button>
662
                     <button class="btn btn-danger responseno" name="response" id="responseno" value="0">'.
663
                get_lang('No').'</button>
664
                 </form>';
665
            $content .= $form;
666
        }
667
668
        $now = api_get_utc_datetime();
669
670
        $params = [
671
            'ticket_id' => $ticketId,
672
            'subject' => $subject,
673
            'message' => $content,
674
            'ip_address' => api_get_real_ip(),
675
            'sys_insert_user_id' => $userId,
676
            'sys_insert_datetime' => $now,
677
            'sys_lastedit_user_id' => $userId,
678
            'sys_lastedit_datetime' => $now,
679
            'status' => $status,
680
        ];
681
        $messageId = Database::insert($table_support_messages, $params);
682
        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...
683
            // update_total_message
684
            $sql = "UPDATE $table_support_tickets
685
                    SET
686
                        sys_lastedit_user_id = $userId,
687
                        sys_lastedit_datetime = '$now',
688
                        total_messages = (
689
                            SELECT COUNT(*) as total_messages
690
                            FROM $table_support_messages
691
                            WHERE ticket_id = $ticketId
692
                        )
693
                    WHERE id = $ticketId ";
694
            Database::query($sql);
695
696
            if (is_array($fileAttachments)) {
697
                foreach ($fileAttachments as $file_attach) {
698
                    if (0 == $file_attach['error']) {
699
                        self::saveMessageAttachmentFile(
700
                            $file_attach,
701
                            $ticketId,
702
                            $messageId
703
                        );
704
                    } else {
705
                        if (UPLOAD_ERR_NO_FILE != $file_attach['error']) {
706
                            return false;
707
                        }
708
                    }
709
                }
710
            }
711
        }
712
713
        return true;
714
    }
715
716
    /**
717
     * Attachment files when a message is sent.
718
     *
719
     * @param $file_attach
720
     * @param $ticketId
721
     * @param $message_id
722
     *
723
     * @return bool
724
     */
725
    public static function saveMessageAttachmentFile(
726
        $file_attach,
727
        $ticketId,
728
        $message_id
729
    ) {
730
        throw new Exception('Implement saveMessageAttachmentFile');
731
        $now = api_get_utc_datetime();
0 ignored issues
show
Unused Code introduced by
$now = api_get_utc_datetime() is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
732
        $userId = api_get_user_id();
733
        $ticketId = (int) $ticketId;
734
735
        $new_file_name = add_ext_on_mime(
736
            stripslashes($file_attach['name']),
737
            $file_attach['type']
738
        );
739
        $table_support_message_attachments = Database::get_main_table(TABLE_TICKET_MESSAGE_ATTACHMENTS);
740
        if (!filter_extension($new_file_name)) {
741
            echo Display::return_message(
742
                get_lang('File upload failed: this file extension or file type is prohibited'),
743
                'error'
744
            );
745
        } else {
746
            throw new Exception('@todo file upload ticket_attachment');
747
            //$result = api_upload_file('ticket_attachment', $file_attach, $ticketId);
748
            if ($result) {
749
                $safe_file_name = Database::escape_string($new_file_name);
750
                $safe_new_file_name = Database::escape_string($result['path_to_save']);
751
                $sql = "INSERT INTO $table_support_message_attachments (
752
                        filename,
753
                        path,
754
                        ticket_id,
755
                        message_id,
756
                        size,
757
                        sys_insert_user_id,
758
                        sys_insert_datetime,
759
                        sys_lastedit_user_id,
760
                        sys_lastedit_datetime
761
                    ) VALUES (
762
                        '$safe_file_name',
763
                        '$safe_new_file_name',
764
                        '$ticketId',
765
                        '$message_id',
766
                        '".$file_attach['size']."',
767
                        '$userId',
768
                        '$now',
769
                        '$userId',
770
                        '$now'
771
                    )";
772
                Database::query($sql);
773
774
                return true;
775
            }
776
        }
777
    }
778
779
    /**
780
     * Get tickets by userId.
781
     *
782
     * @param int $from
783
     * @param int $number_of_items
784
     * @param $column
785
     * @param $direction
786
     *
787
     * @return array
788
     */
789
    public static function getTicketsByCurrentUser($from, $number_of_items, $column, $direction)
790
    {
791
        $table_support_category = Database::get_main_table(TABLE_TICKET_CATEGORY);
792
        $table_support_tickets = Database::get_main_table(TABLE_TICKET_TICKET);
793
        $table_support_priority = Database::get_main_table(TABLE_TICKET_PRIORITY);
794
        $table_support_status = Database::get_main_table(TABLE_TICKET_STATUS);
795
        $direction = !empty($direction) ? $direction : 'DESC';
796
        $userId = api_get_user_id();
797
        $userInfo = api_get_user_info($userId);
798
799
        if (empty($userInfo)) {
800
            return [];
801
        }
802
        $isAdmin = UserManager::is_admin($userId);
803
804
        if (!isset($_GET['project_id'])) {
805
            return [];
806
        }
807
808
        switch ($column) {
809
            case 0:
810
                $column = 'ticket_id';
811
                break;
812
            case 1:
813
                $column = 'status_name';
814
                break;
815
            case 2:
816
                $column = 'start_date';
817
                break;
818
            case 3:
819
                $column = 'sys_lastedit_datetime';
820
                break;
821
            case 4:
822
                $column = 'category_name';
823
                break;
824
            case 5:
825
                $column = 'sys_insert_user_id';
826
                break;
827
            case 6:
828
                $column = 'assigned_last_user';
829
                break;
830
            case 7:
831
                $column = 'total_messages';
832
                break;
833
            case 8:
834
                $column = 'subject';
835
                break;
836
            default:
837
                $column = 'ticket_id';
838
        }
839
840
        $sql = "SELECT DISTINCT
841
                ticket.*,
842
                ticket.id ticket_id,
843
                status.name AS status_name,
844
                ticket.start_date,
845
                ticket.sys_lastedit_datetime,
846
                cat.name AS category_name,
847
                priority.name AS priority_name,
848
                ticket.total_messages AS total_messages,
849
                ticket.message AS message,
850
                ticket.subject AS subject,
851
                ticket.assigned_last_user
852
            FROM $table_support_tickets ticket
853
            INNER JOIN $table_support_category cat
854
            ON (cat.id = ticket.category_id)
855
            INNER JOIN $table_support_priority priority
856
            ON (ticket.priority_id = priority.id)
857
            INNER JOIN $table_support_status status
858
            ON (ticket.status_id = status.id)
859
            WHERE 1=1
860
        ";
861
862
        $projectId = (int) $_GET['project_id'];
863
        $userIsAllowInProject = self::userIsAllowInProject($userInfo, $projectId);
864
865
        // Check if a role was set to the project
866
        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...
867
            $sql .= " AND (ticket.assigned_last_user = $userId OR ticket.sys_insert_user_id = $userId )";
868
        }
869
870
        // Search simple
871
        if (isset($_GET['submit_simple']) && '' != $_GET['keyword']) {
872
            $keyword = Database::escape_string(trim($_GET['keyword']));
873
            $sql .= " AND (
874
                      ticket.id LIKE '%$keyword%' OR
875
                      ticket.code LIKE '%$keyword%' OR
876
                      ticket.subject LIKE '%$keyword%' OR
877
                      ticket.message LIKE '%$keyword%' OR
878
                      ticket.keyword LIKE '%$keyword%' OR
879
                      ticket.source LIKE '%$keyword%' OR
880
                      cat.name LIKE '%$keyword%' OR
881
                      status.name LIKE '%$keyword%' OR
882
                      priority.name LIKE '%$keyword%' OR
883
                      ticket.personal_email LIKE '%$keyword%'
884
            )";
885
        }
886
887
        $keywords = [
888
            'project_id' => 'ticket.project_id',
889
            'keyword_category' => 'ticket.category_id',
890
            'keyword_assigned_to' => 'ticket.assigned_last_user',
891
            'keyword_source' => 'ticket.source ',
892
            'keyword_status' => 'ticket.status_id',
893
            'keyword_priority' => 'ticket.priority_id',
894
        ];
895
896
        foreach ($keywords as $keyword => $label) {
897
            if (isset($_GET[$keyword])) {
898
                $data = Database::escape_string(trim($_GET[$keyword]));
899
                if (!empty($data)) {
900
                    $sql .= " AND $label = '$data' ";
901
                }
902
            }
903
        }
904
905
        // Search advanced
906
        $keyword_start_date_start = isset($_GET['keyword_start_date_start']) ? Database::escape_string(trim($_GET['keyword_start_date_start'])) : '';
907
        $keyword_start_date_end = isset($_GET['keyword_start_date_end']) ? Database::escape_string(trim($_GET['keyword_start_date_end'])) : '';
908
        $keyword_course = isset($_GET['keyword_course']) ? Database::escape_string(trim($_GET['keyword_course'])) : '';
909
        $keyword_range = !empty($keyword_start_date_start) && !empty($keyword_start_date_end);
910
911
        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...
912
            $sql .= " AND DATE_FORMAT(ticket.start_date,'%d/%m/%Y') >= '$keyword_start_date_start' ";
913
        }
914
        if ($keyword_range && '' != $keyword_start_date_start && '' != $keyword_start_date_end) {
915
            $sql .= " AND DATE_FORMAT(ticket.start_date,'%d/%m/%Y') >= '$keyword_start_date_start'
916
                      AND DATE_FORMAT(ticket.start_date,'%d/%m/%Y') <= '$keyword_start_date_end'";
917
        }
918
919
        if ('' != $keyword_course) {
920
            $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
921
            $sql .= " AND ticket.course_id IN (
922
                     SELECT id FROM $course_table
923
                     WHERE (
924
                        title LIKE '%$keyword_course%' OR
925
                        code LIKE '%$keyword_course%' OR
926
                        visual_code LIKE '%$keyword_course%'
927
                     )
928
            )";
929
        }
930
        $sql .= " ORDER BY `$column` $direction";
931
        $sql .= " LIMIT $from, $number_of_items";
932
933
        $result = Database::query($sql);
934
        $tickets = [];
935
        $webPath = api_get_path(WEB_PATH);
936
        while ($row = Database::fetch_assoc($result)) {
937
            $userInfo = api_get_user_info($row['sys_insert_user_id']);
938
            $hrefUser = $webPath.'main/admin/user_information.php?user_id='.$userInfo['user_id'];
939
            $name = "<a href='$hrefUser'> {$userInfo['complete_name_with_username']} </a>";
940
            if (0 != $row['assigned_last_user']) {
941
                $assignedUserInfo = api_get_user_info($row['assigned_last_user']);
942
                if (!empty($assignedUserInfo)) {
943
                    $hrefResp = $webPath.'main/admin/user_information.php?user_id='.$assignedUserInfo['user_id'];
944
                    $row['assigned_last_user'] = "<a href='$hrefResp'> {$assignedUserInfo['complete_name_with_username']} </a>";
945
                } else {
946
                    $row['assigned_last_user'] = get_lang('Unknown user');
947
                }
948
            } else {
949
                if (self::STATUS_FORWARDED !== $row['status_id']) {
950
                    $row['assigned_last_user'] = '<span style="color:#ff0000;">'.get_lang('To be assigned').'</span>';
951
                } else {
952
                    $row['assigned_last_user'] = '<span style="color:#00ff00;">'.get_lang('Message resent').'</span>';
953
                }
954
            }
955
956
            switch ($row['source']) {
957
                case self::SOURCE_PRESENTIAL:
958
                    $img_source = 'icons/32/user.png';
959
                    break;
960
                case self::SOURCE_EMAIL:
961
                    $img_source = 'icons/32/mail.png';
962
                    break;
963
                case self::SOURCE_PHONE:
964
                    $img_source = 'icons/32/event.png';
965
                    break;
966
                default:
967
                    $img_source = 'icons/32/ticket.png';
968
                    break;
969
            }
970
971
            $row['start_date'] = Display::dateToStringAgoAndLongDate($row['start_date']);
972
            $row['sys_lastedit_datetime'] = Display::dateToStringAgoAndLongDate($row['sys_lastedit_datetime']);
973
974
            $icon = Display::return_icon(
975
                $img_source,
976
                get_lang('Information'),
977
                ['style' => 'margin-right: 10px; float: left;']
978
            );
979
980
            $icon .= '<a href="ticket_details.php?ticket_id='.$row['id'].'">'.$row['code'].'</a>';
981
982
            if ($isAdmin) {
983
                $ticket = [
984
                    $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

984
                    $icon.' './** @scrutinizer ignore-type */ Security::remove_XSS($row['subject']),
Loading history...
985
                    $row['status_name'],
986
                    $row['start_date'],
987
                    $row['sys_lastedit_datetime'],
988
                    $row['category_name'],
989
                    $name,
990
                    $row['assigned_last_user'],
991
                    $row['total_messages'],
992
                ];
993
            } else {
994
                $ticket = [
995
                    $icon.' '.Security::remove_XSS($row['subject']),
996
                    $row['status_name'],
997
                    $row['start_date'],
998
                    $row['sys_lastedit_datetime'],
999
                    $row['category_name'],
1000
                ];
1001
            }
1002
            if ($isAdmin) {
1003
                $ticket['0'] .= '&nbsp;&nbsp;<a 
1004
                href="javascript:void(0)" 
1005
                onclick="load_history_ticket(\'div_'.$row['ticket_id'].'\','.$row['ticket_id'].')">
1006
                    <a 
1007
                        onclick="load_course_list(\'div_'.$row['ticket_id'].'\','.$row['ticket_id'].')" 
1008
					    onmouseover="clear_course_list (\'div_'.$row['ticket_id'].'\')"					     
1009
					    title="'.get_lang('History').'" 
1010
					    alt="'.get_lang('History').'"
1011
                    >
1012
                    '.Display::returnFontAwesomeIcon('history').'
1013
                    </a>                                        
1014
					
1015
					<div class="blackboard_hide" id="div_'.$row['ticket_id'].'">&nbsp;&nbsp;</div>
1016
					</a>&nbsp;&nbsp;';
1017
            }
1018
            $tickets[] = $ticket;
1019
        }
1020
1021
        return $tickets;
1022
    }
1023
1024
    /**
1025
     * @return int
1026
     */
1027
    public static function getTotalTicketsCurrentUser()
1028
    {
1029
        $table_support_category = Database::get_main_table(TABLE_TICKET_CATEGORY);
1030
        $table_support_tickets = Database::get_main_table(TABLE_TICKET_TICKET);
1031
        $table_support_priority = Database::get_main_table(TABLE_TICKET_PRIORITY);
1032
        $table_support_status = Database::get_main_table(TABLE_TICKET_STATUS);
1033
1034
        $userInfo = api_get_user_info();
1035
        if (empty($userInfo)) {
1036
            return 0;
1037
        }
1038
        $userId = $userInfo['id'];
1039
1040
        if (!isset($_GET['project_id'])) {
1041
            return 0;
1042
        }
1043
1044
        $sql = "SELECT COUNT(ticket.id) AS total
1045
                FROM $table_support_tickets ticket
1046
                INNER JOIN $table_support_category cat
1047
                ON (cat.id = ticket.category_id)
1048
                INNER JOIN $table_support_priority priority
1049
                ON (ticket.priority_id = priority.id)
1050
                INNER JOIN $table_support_status status
1051
                ON (ticket.status_id = status.id)
1052
	            WHERE 1 = 1";
1053
1054
        $projectId = (int) $_GET['project_id'];
1055
        $allowRoleList = self::getAllowedRolesFromProject($projectId);
1056
1057
        // Check if a role was set to the project
1058
        if (!empty($allowRoleList) && is_array($allowRoleList)) {
1059
            if (!in_array($userInfo['status'], $allowRoleList)) {
1060
                $sql .= " AND (ticket.assigned_last_user = $userId OR ticket.sys_insert_user_id = $userId )";
1061
            }
1062
        } else {
1063
            if (!api_is_platform_admin()) {
1064
                $sql .= " AND (ticket.assigned_last_user = $userId OR ticket.sys_insert_user_id = $userId )";
1065
            }
1066
        }
1067
1068
        // Search simple
1069
        if (isset($_GET['submit_simple'])) {
1070
            if ('' != $_GET['keyword']) {
1071
                $keyword = Database::escape_string(trim($_GET['keyword']));
1072
                $sql .= " AND (
1073
                          ticket.code LIKE '%$keyword%' OR
1074
                          ticket.subject LIKE '%$keyword%' OR
1075
                          ticket.message LIKE '%$keyword%' OR
1076
                          ticket.keyword LIKE '%$keyword%' OR
1077
                          ticket.personal_email LIKE '%$keyword%' OR
1078
                          ticket.source LIKE '%$keyword%'
1079
                )";
1080
            }
1081
        }
1082
1083
        $keywords = [
1084
            'project_id' => 'ticket.project_id',
1085
            'keyword_category' => 'ticket.category_id',
1086
            'keyword_assigned_to' => 'ticket.assigned_last_user',
1087
            'keyword_source' => 'ticket.source',
1088
            'keyword_status' => 'ticket.status_id',
1089
            'keyword_priority' => 'ticket.priority_id',
1090
        ];
1091
1092
        foreach ($keywords as $keyword => $sqlLabel) {
1093
            if (isset($_GET[$keyword])) {
1094
                $data = Database::escape_string(trim($_GET[$keyword]));
1095
                $sql .= " AND $sqlLabel = '$data' ";
1096
            }
1097
        }
1098
1099
        // Search advanced
1100
        $keyword_start_date_start = isset($_GET['keyword_start_date_start']) ? Database::escape_string(trim($_GET['keyword_start_date_start'])) : '';
1101
        $keyword_start_date_end = isset($_GET['keyword_start_date_end']) ? Database::escape_string(trim($_GET['keyword_start_date_end'])) : '';
1102
        $keyword_range = isset($_GET['keyword_dates']) ? Database::escape_string(trim($_GET['keyword_dates'])) : '';
1103
        $keyword_course = isset($_GET['keyword_course']) ? Database::escape_string(trim($_GET['keyword_course'])) : '';
1104
1105
        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...
1106
            $sql .= " AND DATE_FORMAT( ticket.start_date,'%d/%m/%Y') = '$keyword_start_date_start' ";
1107
        }
1108
        if ($keyword_range && '' != $keyword_start_date_start && '' != $keyword_start_date_end) {
1109
            $sql .= " AND DATE_FORMAT( ticket.start_date,'%d/%m/%Y') >= '$keyword_start_date_start'
1110
                      AND DATE_FORMAT( ticket.start_date,'%d/%m/%Y') <= '$keyword_start_date_end'";
1111
        }
1112
        if ('' != $keyword_course) {
1113
            $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1114
            $sql .= " AND ticket.course_id IN (
1115
                        SELECT id
1116
                        FROM $course_table
1117
                        WHERE (
1118
                            title LIKE '%$keyword_course%' OR
1119
                            code LIKE '%$keyword_course%' OR
1120
                            visual_code LIKE '%$keyword_course%'
1121
                        )
1122
                   ) ";
1123
        }
1124
1125
        $res = Database::query($sql);
1126
        $obj = Database::fetch_object($res);
1127
1128
        return (int) $obj->total;
1129
    }
1130
1131
    /**
1132
     * @param int $id
1133
     *
1134
     * @return false|TicketMessageAttachment
1135
     */
1136
    public static function getTicketMessageAttachment($id)
1137
    {
1138
        $id = (int) $id;
1139
        $em = Database::getManager();
1140
        $item = $em->getRepository(TicketMessageAttachment::class)->find($id);
1141
        if ($item) {
1142
            return $item;
1143
        }
1144
1145
        return false;
1146
    }
1147
1148
    /**
1149
     * @param int $id
1150
     *
1151
     * @return array
1152
     */
1153
    public static function getTicketMessageAttachmentsByTicketId($id)
1154
    {
1155
        $id = (int) $id;
1156
        $em = Database::getManager();
1157
        $items = $em->getRepository(TicketMessageAttachment::class)->findBy(['ticket' => $id]);
1158
        if ($items) {
1159
            return $items;
1160
        }
1161
1162
        return false;
1163
    }
1164
1165
    /**
1166
     * @param int $ticketId
1167
     *
1168
     * @return array
1169
     */
1170
    public static function get_ticket_detail_by_id($ticketId)
1171
    {
1172
        $ticketId = (int) $ticketId;
1173
        $table_support_category = Database::get_main_table(TABLE_TICKET_CATEGORY);
1174
        $table_support_tickets = Database::get_main_table(TABLE_TICKET_TICKET);
1175
        $table_support_priority = Database::get_main_table(TABLE_TICKET_PRIORITY);
1176
        $table_support_status = Database::get_main_table(TABLE_TICKET_STATUS);
1177
        $table_support_messages = Database::get_main_table(TABLE_TICKET_MESSAGE);
1178
        $table_support_message_attachments = Database::get_main_table(TABLE_TICKET_MESSAGE_ATTACHMENTS);
1179
        $table_main_user = Database::get_main_table(TABLE_MAIN_USER);
1180
1181
        $sql = "SELECT
1182
                    ticket.*,
1183
                    cat.name,
1184
                    status.name as status,
1185
                    priority.name priority
1186
                FROM $table_support_tickets ticket
1187
                INNER JOIN $table_support_category cat
1188
                ON (cat.id = ticket.category_id)
1189
                INNER JOIN $table_support_priority priority
1190
                ON (priority.id = ticket.priority_id)
1191
                INNER JOIN $table_support_status status
1192
                ON (status.id = ticket.status_id)
1193
		        WHERE
1194
                    ticket.id = $ticketId ";
1195
        $result = Database::query($sql);
1196
        $ticket = [];
1197
1198
        $repo = Container::getLpRepository();
1199
        if (Database::num_rows($result) > 0) {
1200
            while ($row = Database::fetch_assoc($result)) {
1201
                $row['course'] = null;
1202
                $row['start_date_from_db'] = $row['start_date'];
1203
                $row['start_date'] = api_convert_and_format_date(
1204
                    api_get_local_time($row['start_date']),
1205
                    DATE_TIME_FORMAT_LONG,
1206
                    api_get_timezone()
1207
                );
1208
                $row['end_date_from_db'] = $row['end_date'];
1209
                $row['end_date'] = api_convert_and_format_date(
1210
                    api_get_local_time($row['end_date']),
1211
                    DATE_TIME_FORMAT_LONG,
1212
                    api_get_timezone()
1213
                );
1214
                $row['sys_lastedit_datetime_from_db'] = $row['sys_lastedit_datetime'];
1215
                $row['sys_lastedit_datetime'] = api_convert_and_format_date(
1216
                    api_get_local_time($row['sys_lastedit_datetime']),
1217
                    DATE_TIME_FORMAT_LONG,
1218
                    api_get_timezone()
1219
                );
1220
                $row['course_url'] = null;
1221
                if (0 != $row['course_id']) {
1222
                    $course = api_get_course_info_by_id($row['course_id']);
1223
                    $sessionId = 0;
1224
                    if ($row['session_id']) {
1225
                        $sessionId = $row['session_id'];
1226
                    }
1227
                    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...
1228
                        $row['course_url'] = '<a href="'.$course['course_public_url'].'?id_session='.$sessionId.'">'.$course['name'].'</a>';
1229
                    }
1230
                    $row['exercise_url'] = null;
1231
1232
                    if (!empty($row['exercise_id'])) {
1233
                        $exerciseTitle = ExerciseLib::getExerciseTitleById($row['exercise_id']);
1234
                        $dataExercise = [
1235
                            'cidReq' => $course['code'],
1236
                            'id_session' => $sessionId,
1237
                            'exerciseId' => $row['exercise_id'],
1238
                        ];
1239
                        $urlParamsExercise = http_build_query($dataExercise);
1240
1241
                        $row['exercise_url'] = '<a href="'.api_get_path(WEB_CODE_PATH).'exercise/overview.php?'.$urlParamsExercise.'">'.$exerciseTitle.'</a>';
1242
                    }
1243
1244
                    $row['lp_url'] = null;
1245
1246
                    if (!empty($row['lp_id'])) {
1247
                        /** @var CLp $lp */
1248
                        $lp = $repo->find($row['lp_id']);
1249
                        $dataLp = [
1250
                            'cidReq' => $course['code'],
1251
                            'id_session' => $sessionId,
1252
                            'lp_id' => $row['lp_id'],
1253
                            'action' => 'view',
1254
                        ];
1255
                        $urlParamsLp = http_build_query($dataLp);
1256
1257
                        $row['lp_url'] = '<a
1258
                            href="'.api_get_path(WEB_CODE_PATH).'lp/lp_controller.php?'.$urlParamsLp.'">'.
1259
                            $lp->getName().
1260
                        '</a>';
1261
                    }
1262
                }
1263
1264
                $userInfo = api_get_user_info($row['sys_insert_user_id']);
1265
                $row['user_url'] = '<a href="'.api_get_path(WEB_PATH).'main/admin/user_information.php?user_id='.$userInfo['user_id'].'">
1266
                '.$userInfo['complete_name'].'</a>';
1267
                $ticket['usuario'] = $userInfo;
1268
                $ticket['ticket'] = $row;
1269
            }
1270
1271
            $sql = "SELECT *, message.id as message_id
1272
                    FROM $table_support_messages message
1273
                    INNER JOIN $table_main_user user
1274
                    ON (message.sys_insert_user_id = user.id)
1275
                    WHERE
1276
                        message.ticket_id = '$ticketId' ";
1277
            $result = Database::query($sql);
1278
            $ticket['messages'] = [];
1279
            $attach_icon = Display::return_icon('attachment.gif', '');
1280
            $webPath = api_get_path(WEB_CODE_PATH);
1281
            while ($row = Database::fetch_assoc($result)) {
1282
                $message = $row;
1283
                $message['admin'] = UserManager::is_admin($message['user_id']);
1284
                $message['user_info'] = api_get_user_info($message['user_id']);
1285
                $sql = "SELECT *
1286
                        FROM $table_support_message_attachments
1287
                        WHERE
1288
                            message_id = ".$row['message_id']." AND
1289
                            ticket_id = $ticketId";
1290
1291
                $result_attach = Database::query($sql);
1292
                while ($row2 = Database::fetch_assoc($result_attach)) {
1293
                    $archiveURL = $webPath.'ticket/download.php?ticket_id='.$ticketId.'&id='.$row2['id'];
1294
                    $row2['attachment_link'] = $attach_icon.
1295
                        '&nbsp;<a href="'.$archiveURL.'">'.$row2['filename'].'</a>&nbsp;('.$row2['size'].')';
1296
                    $message['attachments'][] = $row2;
1297
                }
1298
                $ticket['messages'][] = $message;
1299
            }
1300
        }
1301
1302
        return $ticket;
1303
    }
1304
1305
    /**
1306
     * @param int $ticketId
1307
     * @param int $userId
1308
     *
1309
     * @return bool
1310
     */
1311
    public static function update_message_status($ticketId, $userId)
1312
    {
1313
        $ticketId = (int) $ticketId;
1314
        $userId = (int) $userId;
1315
        $table_support_messages = Database::get_main_table(TABLE_TICKET_MESSAGE);
1316
        $table_support_tickets = Database::get_main_table(TABLE_TICKET_TICKET);
1317
        $now = api_get_utc_datetime();
1318
        $sql = "UPDATE $table_support_messages
1319
                SET
1320
                    status = 'LEI',
1321
                    sys_lastedit_user_id ='".api_get_user_id()."',
1322
                    sys_lastedit_datetime ='".$now."'
1323
                WHERE ticket_id ='$ticketId' ";
1324
1325
        if (api_is_platform_admin()) {
1326
            $sql .= " AND sys_insert_user_id = '$userId'";
1327
        } else {
1328
            $sql .= " AND sys_insert_user_id != '$userId'";
1329
        }
1330
        $result = Database::query($sql);
1331
        if (Database::affected_rows($result) > 0) {
1332
            Database::query(
1333
                "UPDATE $table_support_tickets SET
1334
                    status_id = '".self::STATUS_PENDING."'
1335
                 WHERE id ='$ticketId' AND status_id = '".self::STATUS_NEW."'"
1336
            );
1337
1338
            return true;
1339
        }
1340
1341
        return false;
1342
    }
1343
1344
    /**
1345
     * Send notification to a user through the internal messaging system.
1346
     *
1347
     * @param int    $ticketId
1348
     * @param string $title
1349
     * @param string $message
1350
     * @param int    $onlyToUserId
1351
     *
1352
     * @return bool
1353
     */
1354
    public static function sendNotification($ticketId, $title, $message, $onlyToUserId = 0)
1355
    {
1356
        $ticketInfo = self::get_ticket_detail_by_id($ticketId);
1357
1358
        if (empty($ticketInfo)) {
1359
            return false;
1360
        }
1361
1362
        $assignedUserInfo = api_get_user_info($ticketInfo['ticket']['assigned_last_user']);
1363
        $requestUserInfo = $ticketInfo['usuario'];
1364
        $ticketCode = $ticketInfo['ticket']['code'];
1365
        $status = $ticketInfo['ticket']['status'];
1366
        $priority = $ticketInfo['ticket']['priority'];
1367
1368
        // Subject
1369
        $titleEmail = "[$ticketCode] $title";
1370
1371
        // Content
1372
        $href = api_get_path(WEB_CODE_PATH).'/ticket/ticket_details.php?ticket_id='.$ticketId;
1373
        $ticketUrl = Display::url($ticketCode, $href);
1374
        $messageEmail = get_lang('TicketNum').": $ticketUrl <br />";
1375
        $messageEmail .= get_lang('Status').": $status <br />";
1376
        $messageEmail .= get_lang('Priority').": $priority <br />";
1377
        $messageEmail .= '<hr /><br />';
1378
        $messageEmail .= $message;
1379
        $currentUserId = api_get_user_id();
1380
        $attachmentList = [];
1381
        $attachments = self::getTicketMessageAttachmentsByTicketId($ticketId);
1382
        if (!empty($attachments)) {
1383
            /** @var TicketMessageAttachment $attachment */
1384
            foreach ($attachments as $attachment) {
1385
                //$attachment->get
1386
            }
1387
        }
1388
1389
        if (!empty($onlyToUserId)) {
1390
            // Send only to specific user
1391
            if ($currentUserId != $onlyToUserId) {
1392
                MessageManager::send_message_simple(
1393
                    $onlyToUserId,
1394
                    $titleEmail,
1395
                    $messageEmail,
1396
                    0,
1397
                    false,
1398
                    false,
1399
                    [],
1400
                    false,
1401
                    $attachmentList
1402
                );
1403
            }
1404
        } else {
1405
            // Send to assigned user and to author
1406
            if ($requestUserInfo && $currentUserId != $requestUserInfo['id']) {
1407
                MessageManager::send_message_simple(
1408
                    $requestUserInfo['id'],
1409
                    $titleEmail,
1410
                    $messageEmail,
1411
                    0,
1412
                    false,
1413
                    false,
1414
                    [],
1415
                    false,
1416
                    $attachmentList
1417
                );
1418
            }
1419
1420
            if ($assignedUserInfo &&
1421
                $requestUserInfo['id'] != $assignedUserInfo['id'] &&
1422
                $currentUserId != $assignedUserInfo['id']
1423
            ) {
1424
                MessageManager::send_message_simple(
1425
                    $assignedUserInfo['id'],
1426
                    $titleEmail,
1427
                    $messageEmail,
1428
                    0,
1429
                    false,
1430
                    false,
1431
                    [],
1432
                    false,
1433
                    $attachmentList
1434
                );
1435
            }
1436
        }
1437
    }
1438
1439
    /**
1440
     * @param array $params
1441
     * @param int   $ticketId
1442
     * @param int   $userId
1443
     *
1444
     * @return bool
1445
     */
1446
    public static function updateTicket(
1447
        $params,
1448
        $ticketId,
1449
        $userId
1450
    ) {
1451
        $now = api_get_utc_datetime();
1452
        $table = Database::get_main_table(TABLE_TICKET_TICKET);
1453
        $newParams = [
1454
            'priority_id' => isset($params['priority_id']) ? (int) $params['priority_id'] : '',
1455
            'status_id' => isset($params['status_id']) ? (int) $params['status_id'] : '',
1456
            'sys_lastedit_user_id' => (int) $userId,
1457
            'sys_lastedit_datetime' => $now,
1458
        ];
1459
        Database::update($table, $newParams, ['id = ? ' => $ticketId]);
1460
1461
        return true;
1462
    }
1463
1464
    /**
1465
     * @param int $status_id
1466
     * @param int $ticketId
1467
     * @param int $userId
1468
     *
1469
     * @return bool
1470
     */
1471
    public static function update_ticket_status(
1472
        $status_id,
1473
        $ticketId,
1474
        $userId
1475
    ) {
1476
        $table_support_tickets = Database::get_main_table(TABLE_TICKET_TICKET);
1477
1478
        $ticketId = (int) $ticketId;
1479
        $status_id = (int) $status_id;
1480
        $userId = (int) $userId;
1481
        $now = api_get_utc_datetime();
1482
1483
        $sql = "UPDATE $table_support_tickets
1484
                SET
1485
                    status_id = '$status_id',
1486
                    sys_lastedit_user_id ='$userId',
1487
                    sys_lastedit_datetime ='".$now."'
1488
                WHERE id ='$ticketId'";
1489
        $result = Database::query($sql);
1490
1491
        if (Database::affected_rows($result) > 0) {
1492
            self::sendNotification(
1493
                $ticketId,
1494
                get_lang('Ticket updated'),
1495
                get_lang('Ticket updated')
1496
            );
1497
1498
            return true;
1499
        }
1500
1501
        return false;
1502
    }
1503
1504
    /**
1505
     * @return mixed
1506
     */
1507
    public static function getNumberOfMessages()
1508
    {
1509
        $table_support_tickets = Database::get_main_table(TABLE_TICKET_TICKET);
1510
        $table_support_messages = Database::get_main_table(TABLE_TICKET_MESSAGE);
1511
        $table_main_user = Database::get_main_table(TABLE_MAIN_USER);
1512
        $table_main_admin = Database::get_main_table(TABLE_MAIN_ADMIN);
1513
        $user_info = api_get_user_info();
1514
        $userId = $user_info['user_id'];
1515
        $sql = "SELECT COUNT(DISTINCT ticket.id) AS unread
1516
                FROM $table_support_tickets ticket,
1517
                $table_support_messages message ,
1518
                $table_main_user user
1519
                WHERE
1520
                    ticket.id = message.ticket_id AND
1521
                    message.status = 'NOL' AND
1522
                    user.user_id = message.sys_insert_user_id ";
1523
        if (!api_is_platform_admin()) {
1524
            $sql .= " AND ticket.request_user = '$userId'
1525
                      AND user_id IN (SELECT user_id FROM $table_main_admin)  ";
1526
        } else {
1527
            $sql .= " AND user_id NOT IN (SELECT user_id FROM $table_main_admin)
1528
                      AND ticket.status_id != '".self::STATUS_FORWARDED."'";
1529
        }
1530
        $sql .= "  AND ticket.project_id != '' ";
1531
        $res = Database::query($sql);
1532
        $obj = Database::fetch_object($res);
1533
1534
        return $obj->unread;
1535
    }
1536
1537
    /**
1538
     * @param int $ticketId
1539
     * @param int $userId
1540
     */
1541
    public static function send_alert($ticketId, $userId)
1542
    {
1543
        $table_support_tickets = Database::get_main_table(TABLE_TICKET_TICKET);
1544
        $now = api_get_utc_datetime();
1545
1546
        $ticketId = (int) $ticketId;
1547
        $userId = (int) $userId;
1548
1549
        $sql = "UPDATE $table_support_tickets SET
1550
                  priority_id = '".self::PRIORITY_HIGH."',
1551
                  sys_lastedit_user_id = $userId,
1552
                  sys_lastedit_datetime = '$now'
1553
                WHERE id = $ticketId";
1554
        Database::query($sql);
1555
    }
1556
1557
    /**
1558
     * @param int $ticketId
1559
     * @param int $userId
1560
     */
1561
    public static function close_ticket($ticketId, $userId)
1562
    {
1563
        $ticketId = (int) $ticketId;
1564
        $userId = (int) $userId;
1565
1566
        $table_support_tickets = Database::get_main_table(TABLE_TICKET_TICKET);
1567
        $now = api_get_utc_datetime();
1568
        $sql = "UPDATE $table_support_tickets SET
1569
                    status_id = '".self::STATUS_CLOSE."',
1570
                    sys_lastedit_user_id ='$userId',
1571
                    sys_lastedit_datetime ='".$now."',
1572
                    end_date ='$now'
1573
                WHERE id ='$ticketId'";
1574
        Database::query($sql);
1575
1576
        self::sendNotification(
1577
            $ticketId,
1578
            get_lang('Ticket closed'),
1579
            get_lang('Ticket closed')
1580
        );
1581
    }
1582
1583
    /**
1584
     * Close old tickets.
1585
     */
1586
    public static function close_old_tickets()
1587
    {
1588
        $table = Database::get_main_table(TABLE_TICKET_TICKET);
1589
        $now = api_get_utc_datetime();
1590
        $userId = api_get_user_id();
1591
        $sql = "UPDATE $table
1592
                SET
1593
                    status_id = '".self::STATUS_CLOSE."',
1594
                    sys_lastedit_user_id ='$userId',
1595
                    sys_lastedit_datetime ='$now',
1596
                    end_date = '$now'
1597
                WHERE
1598
                    DATEDIFF('$now', sys_lastedit_datetime) > 7 AND
1599
                    status_id != '".self::STATUS_CLOSE."' AND
1600
                    status_id != '".self::STATUS_NEW."' AND
1601
                    status_id != '".self::STATUS_FORWARDED."'";
1602
        Database::query($sql);
1603
    }
1604
1605
    /**
1606
     * @param int $ticketId
1607
     *
1608
     * @return array
1609
     */
1610
    public static function get_assign_log($ticketId)
1611
    {
1612
        $table = Database::get_main_table(TABLE_TICKET_ASSIGNED_LOG);
1613
        $ticketId = (int) $ticketId;
1614
1615
        $sql = "SELECT * FROM $table
1616
                WHERE ticket_id = $ticketId
1617
                ORDER BY assigned_date DESC";
1618
        $result = Database::query($sql);
1619
        $history = [];
1620
        $webpath = api_get_path(WEB_PATH);
1621
        while ($row = Database::fetch_assoc($result)) {
1622
            if (0 != $row['user_id']) {
1623
                $assignuser = api_get_user_info($row['user_id']);
1624
                $row['assignuser'] = '<a href="'.$webpath.'main/admin/user_information.php?user_id='.$row['user_id'].'"  target="_blank">'.
1625
                $assignuser['username'].'</a>';
1626
            } else {
1627
                $row['assignuser'] = get_lang('Unassign');
1628
            }
1629
            $row['assigned_date'] = Display::dateToStringAgoAndLongDate($row['assigned_date']);
1630
            $insertuser = api_get_user_info($row['sys_insert_user_id']);
1631
            $row['insertuser'] = '<a href="'.$webpath.'main/admin/user_information.php?user_id='.$row['sys_insert_user_id'].'"  target="_blank">'.
1632
                $insertuser['username'].'</a>';
1633
            $history[] = $row;
1634
        }
1635
1636
        return $history;
1637
    }
1638
1639
    /**
1640
     * @param $from
1641
     * @param $number_of_items
1642
     * @param $column
1643
     * @param $direction
1644
     * @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...
1645
     *
1646
     * @return array
1647
     */
1648
    public static function export_tickets_by_user_id(
1649
        $from,
1650
        $number_of_items,
1651
        $column,
1652
        $direction,
1653
        $userId = null
1654
    ) {
1655
        $from = (int) $from;
1656
        $number_of_items = (int) $number_of_items;
1657
        $table_support_category = Database::get_main_table(
1658
            TABLE_TICKET_CATEGORY
1659
        );
1660
        $table_support_tickets = Database::get_main_table(TABLE_TICKET_TICKET);
1661
        $table_support_priority = Database::get_main_table(TABLE_TICKET_PRIORITY);
1662
        $table_support_status = Database::get_main_table(TABLE_TICKET_STATUS);
1663
        $table_support_messages = Database::get_main_table(TABLE_TICKET_MESSAGE);
1664
        $table_main_user = Database::get_main_table(TABLE_MAIN_USER);
1665
1666
        if (is_null($direction)) {
1667
            $direction = 'DESC';
1668
        }
1669
        if (is_null($userId) || 0 == $userId) {
1670
            $userId = api_get_user_id();
1671
        }
1672
1673
        $sql = "SELECT
1674
                    ticket.code,
1675
                    ticket.sys_insert_datetime,
1676
                    ticket.sys_lastedit_datetime,
1677
                    cat.name as category,
1678
                    CONCAT(user.lastname,' ', user.firstname) AS fullname,
1679
                    status.name as status,
1680
                    ticket.total_messages as messages,
1681
                    ticket.assigned_last_user as responsable
1682
                FROM $table_support_tickets ticket,
1683
                $table_support_category cat ,
1684
                $table_support_priority priority,
1685
                $table_support_status status ,
1686
                $table_main_user user
1687
                WHERE
1688
                    cat.id = ticket.category_id
1689
                    AND ticket.priority_id = priority.id
1690
                    AND ticket.status_id = status.id
1691
                    AND user.user_id = ticket.request_user ";
1692
        // Search simple
1693
        if (isset($_GET['submit_simple'])) {
1694
            if ('' !== $_GET['keyword']) {
1695
                $keyword = Database::escape_string(trim($_GET['keyword']));
1696
                $sql .= " AND (ticket.code = '$keyword'
1697
                          OR user.firstname LIKE '%$keyword%'
1698
                          OR user.lastname LIKE '%$keyword%'
1699
                          OR concat(user.firstname,' ',user.lastname) LIKE '%$keyword%'
1700
                          OR concat(user.lastname,' ',user.firstname) LIKE '%$keyword%'
1701
                          OR user.username LIKE '%$keyword%')  ";
1702
            }
1703
        }
1704
        // Search advanced
1705
        if (isset($_GET['submit_advanced'])) {
1706
            $keyword_category = Database::escape_string(
1707
                trim($_GET['keyword_category'])
1708
            );
1709
            $keyword_request_user = Database::escape_string(
1710
                trim($_GET['keyword_request_user'])
1711
            );
1712
            $keywordAssignedTo = (int) $_GET['keyword_assigned_to'];
1713
            $keyword_start_date_start = Database::escape_string(
1714
                trim($_GET['keyword_start_date_start'])
1715
            );
1716
            $keyword_start_date_end = Database::escape_string(
1717
                trim($_GET['keyword_start_date_end'])
1718
            );
1719
            $keyword_status = Database::escape_string(
1720
                trim($_GET['keyword_status'])
1721
            );
1722
            $keyword_source = Database::escape_string(
1723
                trim($_GET['keyword_source'])
1724
            );
1725
            $keyword_priority = Database::escape_string(
1726
                trim($_GET['keyword_priority'])
1727
            );
1728
            $keyword_range = Database::escape_string(
1729
                trim($_GET['keyword_dates'])
1730
            );
1731
            $keyword_unread = Database::escape_string(
1732
                trim($_GET['keyword_unread'])
1733
            );
1734
            $keyword_course = Database::escape_string(
1735
                trim($_GET['keyword_course'])
1736
            );
1737
1738
            if ('' != $keyword_category) {
1739
                $sql .= " AND ticket.category_id = '$keyword_category'  ";
1740
            }
1741
            if ('' != $keyword_request_user) {
1742
                $sql .= " AND (ticket.request_user = '$keyword_request_user'
1743
                          OR user.firstname LIKE '%$keyword_request_user%'
1744
                          OR user.official_code LIKE '%$keyword_request_user%'
1745
                          OR user.lastname LIKE '%$keyword_request_user%'
1746
                          OR concat(user.firstname,' ',user.lastname) LIKE '%$keyword_request_user%'
1747
                          OR concat(user.lastname,' ',user.firstname) LIKE '%$keyword_request_user%'
1748
                          OR user.username LIKE '%$keyword_request_user%') ";
1749
            }
1750
            if (!empty($keywordAssignedTo)) {
1751
                $sql .= " AND ticket.assigned_last_user = $keywordAssignedTo ";
1752
            }
1753
            if ('' != $keyword_status) {
1754
                $sql .= " AND ticket.status_id = '$keyword_status'  ";
1755
            }
1756
            if ('' == $keyword_range && '' != $keyword_start_date_start) {
1757
                $sql .= " AND DATE_FORMAT( ticket.start_date,'%d/%m/%Y') = '$keyword_start_date_start' ";
1758
            }
1759
            if ('1' == $keyword_range && '' != $keyword_start_date_start && '' != $keyword_start_date_end) {
1760
                $sql .= " AND DATE_FORMAT( ticket.start_date,'%d/%m/%Y') >= '$keyword_start_date_start'
1761
                          AND DATE_FORMAT( ticket.start_date,'%d/%m/%Y') <= '$keyword_start_date_end'";
1762
            }
1763
            if ('' != $keyword_priority) {
1764
                $sql .= " AND ticket.priority_id = '$keyword_priority'  ";
1765
            }
1766
            if ('' != $keyword_source) {
1767
                $sql .= " AND ticket.source = '$keyword_source' ";
1768
            }
1769
            if ('' != $keyword_priority) {
1770
                $sql .= " AND ticket.priority_id = '$keyword_priority' ";
1771
            }
1772
            if ('' != $keyword_course) {
1773
                $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1774
                $sql .= " AND ticket.course_id IN ( ";
1775
                $sql .= "SELECT id
1776
                         FROM $course_table
1777
                         WHERE (title LIKE '%$keyword_course%'
1778
                         OR code LIKE '%$keyword_course%'
1779
                         OR visual_code LIKE '%$keyword_course%' )) ";
1780
            }
1781
            if ('yes' == $keyword_unread) {
1782
                $sql .= " AND ticket.id IN (
1783
                          SELECT ticket.id
1784
                          FROM $table_support_tickets ticket,
1785
                          $table_support_messages message,
1786
                          $table_main_user user
1787
                          WHERE ticket.id = message.ticket_id
1788
                          AND message.status = 'NOL'
1789
                          AND message.sys_insert_user_id = user.user_id
1790
                          AND user.status != 1   AND ticket.status_id != '".self::STATUS_FORWARDED."'
1791
                          GROUP BY ticket.id)";
1792
            } else {
1793
                if ('no' == $keyword_unread) {
1794
                    $sql .= " AND ticket.id NOT IN (
1795
                              SELECT ticket.id
1796
                              FROM  $table_support_tickets ticket,
1797
                              $table_support_messages message,
1798
                              $table_main_user user
1799
                              WHERE ticket.id = message.ticket_id
1800
                              AND message.status = 'NOL'
1801
                              AND message.sys_insert_user_id = user.user_id
1802
                              AND user.status != 1
1803
                              AND ticket.status_id != '".self::STATUS_FORWARDED."'
1804
                             GROUP BY ticket.id)";
1805
                }
1806
            }
1807
        }
1808
1809
        $sql .= " LIMIT $from,$number_of_items";
1810
1811
        $result = Database::query($sql);
1812
        $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...
1813
            utf8_decode('Ticket#'),
1814
            utf8_decode('Fecha'),
1815
            utf8_decode('Fecha Edicion'),
1816
            utf8_decode('Categoria'),
1817
            utf8_decode('Usuario'),
1818
            utf8_decode('Estado'),
1819
            utf8_decode('Mensajes'),
1820
            utf8_decode('Responsable'),
1821
            utf8_decode('Programa'),
1822
        ];
1823
1824
        while ($row = Database::fetch_assoc($result)) {
1825
            if (0 != $row['responsable']) {
1826
                $row['responsable'] = api_get_user_info($row['responsable']);
1827
                $row['responsable'] = $row['responsable']['firstname'].' '.$row['responsable']['lastname'];
1828
            }
1829
            $row['sys_insert_datetime'] = api_format_date(
1830
                $row['sys_insert_datetime'],
1831
                '%d/%m/%y - %I:%M:%S %p'
1832
            );
1833
            $row['sys_lastedit_datetime'] = api_format_date(
1834
                $row['sys_lastedit_datetime'],
1835
                '%d/%m/%y - %I:%M:%S %p'
1836
            );
1837
            $row['category'] = utf8_decode($row['category']);
1838
            $row['programa'] = utf8_decode($row['fullname']);
1839
            $row['fullname'] = utf8_decode($row['fullname']);
1840
            $row['responsable'] = utf8_decode($row['responsable']);
1841
            $tickets[] = $row;
1842
        }
1843
1844
        return $tickets;
1845
    }
1846
1847
    /**
1848
     * @param string $url
1849
     * @param int    $projectId
1850
     *
1851
     * @return FormValidator
1852
     */
1853
    public static function getCategoryForm($url, $projectId)
1854
    {
1855
        $form = new FormValidator('category', 'post', $url);
1856
        $form->addText('name', get_lang('Name'));
1857
        $form->addHtmlEditor('description', get_lang('Description'));
1858
        $form->addHidden('project_id', $projectId);
1859
        $form->addButtonUpdate(get_lang('Save'));
1860
1861
        return $form;
1862
    }
1863
1864
    /**
1865
     * @return array
1866
     */
1867
    public static function getStatusList()
1868
    {
1869
        $items = Database::getManager()->getRepository(TicketStatus::class)->findAll();
1870
1871
        $list = [];
1872
        /** @var TicketStatus $row */
1873
        foreach ($items as $row) {
1874
            $list[$row->getId()] = $row->getName();
1875
        }
1876
1877
        return $list;
1878
    }
1879
1880
    /**
1881
     * @param array $criteria
1882
     *
1883
     * @return array
1884
     */
1885
    public static function getTicketsFromCriteria($criteria)
1886
    {
1887
        $items = Database::getManager()->getRepository(Ticket::class)->findBy($criteria);
1888
        $list = [];
1889
        /** @var Ticket $row */
1890
        foreach ($items as $row) {
1891
            $list[$row->getId()] = $row->getCode();
1892
        }
1893
1894
        return $list;
1895
    }
1896
1897
    /**
1898
     * @param string $code
1899
     *
1900
     * @return int
1901
     */
1902
    public static function getStatusIdFromCode($code)
1903
    {
1904
        $item = Database::getManager()
1905
            ->getRepository(TicketStatus::class)
1906
            ->findOneBy(['code' => $code])
1907
        ;
1908
1909
        if ($item) {
1910
            return $item->getId();
1911
        }
1912
1913
        return 0;
1914
    }
1915
1916
    /**
1917
     * @return array
1918
     */
1919
    public static function getPriorityList()
1920
    {
1921
        $projects = Database::getManager()->getRepository(TicketPriority::class)->findAll();
1922
        $list = [];
1923
        /** @var TicketPriority $row */
1924
        foreach ($projects as $row) {
1925
            $list[$row->getId()] = $row->getName();
1926
        }
1927
1928
        return $list;
1929
    }
1930
1931
    /**
1932
     * @return array
1933
     */
1934
    public static function getProjects()
1935
    {
1936
        $projects = Database::getManager()->getRepository(TicketProject::class)->findAll();
1937
1938
        $list = [];
1939
        /** @var TicketProject $row */
1940
        foreach ($projects as $row) {
1941
            $list[] = [
1942
                'id' => $row->getId(),
1943
                '0' => $row->getId(),
1944
                '1' => $row->getName(),
1945
                '2' => $row->getDescription(),
1946
                '3' => $row->getId(),
1947
            ];
1948
        }
1949
1950
        return $list;
1951
    }
1952
1953
    /**
1954
     * @return array
1955
     */
1956
    public static function getProjectsSimple()
1957
    {
1958
        $projects = Database::getManager()->getRepository(TicketProject::class)->findAll();
1959
        $list = [];
1960
        /** @var TicketProject $row */
1961
        foreach ($projects as $row) {
1962
            $list[] = [
1963
                'id' => $row->getId(),
1964
                '0' => $row->getId(),
1965
                '1' => Display::url(
1966
                    $row->getName(),
1967
                    api_get_path(WEB_CODE_PATH).'ticket/tickets.php?project_id='.$row->getId()
1968
                ),
1969
                '2' => $row->getDescription(),
1970
            ];
1971
        }
1972
1973
        return $list;
1974
    }
1975
1976
    /**
1977
     * @return int
1978
     */
1979
    public static function getProjectsCount()
1980
    {
1981
        return Database::getManager()->getRepository(TicketProject::class)->createQueryBuilder('p')
1982
            ->select('COUNT(p.id)')
1983
            ->getQuery()
1984
            ->getSingleScalarResult();
1985
    }
1986
1987
    /**
1988
     * @param array $params
1989
     */
1990
    public static function addProject($params)
1991
    {
1992
        $project = new TicketProject();
1993
        $project->setName($params['name']);
1994
        $project->setDescription($params['description']);
1995
        $project->setInsertUserId(api_get_user_id());
1996
1997
        Database::getManager()->persist($project);
1998
        Database::getManager()->flush();
1999
    }
2000
2001
    /**
2002
     * @param int $id
2003
     *
2004
     * @return TicketProject
2005
     */
2006
    public static function getProject($id)
2007
    {
2008
        return Database::getManager()->getRepository(TicketProject::class)->find($id);
2009
    }
2010
2011
    /**
2012
     * @param int   $id
2013
     * @param array $params
2014
     */
2015
    public static function updateProject($id, $params)
2016
    {
2017
        $project = self::getProject($id);
2018
        $project->setName($params['name']);
2019
        $project->setDescription($params['description']);
2020
        $project->setLastEditDateTime(new DateTime($params['sys_lastedit_datetime']));
2021
        $project->setLastEditUserId($params['sys_lastedit_user_id']);
2022
2023
        Database::getManager()->persist($project);
2024
        Database::getManager()->flush();
2025
    }
2026
2027
    /**
2028
     * @param int $id
2029
     */
2030
    public static function deleteProject($id)
2031
    {
2032
        $project = self::getProject($id);
2033
        if ($project) {
0 ignored issues
show
introduced by
$project is of type Chamilo\CoreBundle\Entity\TicketProject, thus it always evaluated to true.
Loading history...
2034
            Database::getManager()->remove($project);
2035
            Database::getManager()->flush();
2036
        }
2037
    }
2038
2039
    /**
2040
     * @param string $url
2041
     *
2042
     * @return FormValidator
2043
     */
2044
    public static function getProjectForm($url)
2045
    {
2046
        $form = new FormValidator('project', 'post', $url);
2047
        $form->addText('name', get_lang('Name'));
2048
        $form->addHtmlEditor('description', get_lang('Description'));
2049
        $form->addButtonUpdate(get_lang('Save'));
2050
2051
        return $form;
2052
    }
2053
2054
    /**
2055
     * @return array
2056
     */
2057
    public static function getStatusAdminList()
2058
    {
2059
        $items = Database::getManager()->getRepository(TicketStatus::class)->findAll();
2060
        $list = [];
2061
        /** @var TicketStatus $row */
2062
        foreach ($items as $row) {
2063
            $list[] = [
2064
                'id' => $row->getId(),
2065
                'code' => $row->getCode(),
2066
                '0' => $row->getId(),
2067
                '1' => $row->getName(),
2068
                '2' => $row->getDescription(),
2069
                '3' => $row->getId(),
2070
            ];
2071
        }
2072
2073
        return $list;
2074
    }
2075
2076
    /**
2077
     * @return array
2078
     */
2079
    /*public static function getStatusSimple()
2080
    {
2081
        $projects = Database::getManager()->getRepository(TicketStatus::class)->findAll();
2082
        $list = [];
2083
        // @var TicketProject $row
2084
        foreach ($projects as $row) {
2085
            $list[] = [
2086
                'id' => $row->getId(),
2087
                '0' => $row->getId(),
2088
                '1' => Display::url($row->getName()),
2089
                '2' => $row->getDescription(),
2090
            ];
2091
        }
2092
2093
        return $list;
2094
    }*/
2095
2096
    /**
2097
     * @return int
2098
     */
2099
    public static function getStatusCount()
2100
    {
2101
        return Database::getManager()->getRepository(TicketStatus::class)->createQueryBuilder('p')
2102
            ->select('COUNT(p.id)')
2103
            ->getQuery()
2104
            ->getSingleScalarResult();
2105
    }
2106
2107
    /**
2108
     * @param array $params
2109
     */
2110
    public static function addStatus($params)
2111
    {
2112
        $item = new TicketStatus();
2113
        $item->setCode(URLify::filter($params['name']));
2114
        $item->setName($params['name']);
2115
        $item->setDescription($params['description']);
2116
2117
        Database::getManager()->persist($item);
2118
        Database::getManager()->flush();
2119
    }
2120
2121
    /**
2122
     * @param $id
2123
     *
2124
     * @return TicketProject
2125
     */
2126
    public static function getStatus($id)
2127
    {
2128
        return Database::getManager()->getRepository(TicketStatus::class)->find($id);
2129
    }
2130
2131
    /**
2132
     * @param int   $id
2133
     * @param array $params
2134
     */
2135
    public static function updateStatus($id, $params)
2136
    {
2137
        $item = self::getStatus($id);
2138
        $item->setName($params['name']);
2139
        $item->setDescription($params['description']);
2140
2141
        Database::getManager()->persist($item);
2142
        Database::getManager()->flush();
2143
    }
2144
2145
    /**
2146
     * @param int $id
2147
     */
2148
    public static function deleteStatus($id)
2149
    {
2150
        $item = self::getStatus($id);
2151
        if ($item) {
0 ignored issues
show
introduced by
$item is of type Chamilo\CoreBundle\Entity\TicketProject, thus it always evaluated to true.
Loading history...
2152
            Database::getManager()->remove($item);
2153
            Database::getManager()->flush();
2154
        }
2155
    }
2156
2157
    /**
2158
     * @param string $url
2159
     *
2160
     * @return FormValidator
2161
     */
2162
    public static function getStatusForm($url)
2163
    {
2164
        $form = new FormValidator('status', 'post', $url);
2165
        $form->addText('name', get_lang('Name'));
2166
        $form->addHtmlEditor('description', get_lang('Description'));
2167
        $form->addButtonUpdate(get_lang('Save'));
2168
2169
        return $form;
2170
    }
2171
2172
    /**
2173
     * @return array
2174
     */
2175
    public static function getPriorityAdminList()
2176
    {
2177
        $items = Database::getManager()->getRepository(TicketPriority::class)->findAll();
2178
2179
        $list = [];
2180
        /** @var TicketStatus $row */
2181
        foreach ($items as $row) {
2182
            $list[] = [
2183
                'id' => $row->getId(),
2184
                'code' => $row->getCode(),
2185
                '0' => $row->getId(),
2186
                '1' => $row->getName(),
2187
                '2' => $row->getDescription(),
2188
                '3' => $row->getId(),
2189
            ];
2190
        }
2191
2192
        return $list;
2193
    }
2194
2195
    /**
2196
     * @return array
2197
     */
2198
    public static function getPrioritySimple()
2199
    {
2200
        $projects = Database::getManager()->getRepository(TicketPriority::class)->findAll();
2201
2202
        $list = [];
2203
        /** @var TicketPriority $row */
2204
        foreach ($projects as $row) {
2205
            $list[] = [
2206
                'id' => $row->getId(),
2207
                '0' => $row->getId(),
2208
                '1' => Display::url($row->getName()),
0 ignored issues
show
Bug introduced by
The call to Display::url() has too few arguments starting with url. ( Ignorable by Annotation )

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

2208
                '1' => Display::/** @scrutinizer ignore-call */ url($row->getName()),

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
2209
                '2' => $row->getDescription(),
2210
            ];
2211
        }
2212
2213
        return $list;
2214
    }
2215
2216
    /**
2217
     * @return int
2218
     */
2219
    public static function getPriorityCount()
2220
    {
2221
        return Database::getManager()->getRepository(TicketPriority::class)->createQueryBuilder('p')
2222
            ->select('COUNT(p.id)')
2223
            ->getQuery()
2224
            ->getSingleScalarResult();
2225
    }
2226
2227
    /**
2228
     * @param array $params
2229
     */
2230
    public static function addPriority($params)
2231
    {
2232
        $item = new TicketPriority();
2233
        $item
2234
            ->setCode(URLify::filter($params['name']))
2235
            ->setName($params['name'])
2236
            ->setDescription($params['description'])
2237
            ->setColor('')
2238
            ->setInsertUserId(api_get_user_id())
2239
            ->setUrgency('')
2240
        ;
2241
2242
        Database::getManager()->persist($item);
2243
        Database::getManager()->flush();
2244
    }
2245
2246
    /**
2247
     * @param $id
2248
     *
2249
     * @return TicketPriority
2250
     */
2251
    public static function getPriority($id)
2252
    {
2253
        return Database::getManager()->getRepository(TicketPriority::class)->find($id);
2254
    }
2255
2256
    /**
2257
     * @param int   $id
2258
     * @param array $params
2259
     */
2260
    public static function updatePriority($id, $params)
2261
    {
2262
        $item = self::getPriority($id);
2263
        $item->setName($params['name']);
2264
        $item->setDescription($params['description']);
2265
2266
        Database::getManager()->persist($item);
2267
        Database::getManager()->flush();
2268
    }
2269
2270
    /**
2271
     * @param int $id
2272
     */
2273
    public static function deletePriority($id)
2274
    {
2275
        $item = self::getPriority($id);
2276
        if ($item) {
0 ignored issues
show
introduced by
$item is of type Chamilo\CoreBundle\Entity\TicketPriority, thus it always evaluated to true.
Loading history...
2277
            Database::getManager()->remove($item);
2278
            Database::getManager()->flush();
2279
        }
2280
    }
2281
2282
    /**
2283
     * @param string $url
2284
     *
2285
     * @return FormValidator
2286
     */
2287
    public static function getPriorityForm($url)
2288
    {
2289
        $form = new FormValidator('priority', 'post', $url);
2290
        $form->addText('name', get_lang('Name'));
2291
        $form->addHtmlEditor('description', get_lang('Description'));
2292
        $form->addButtonUpdate(get_lang('Save'));
2293
2294
        return $form;
2295
    }
2296
2297
    /**
2298
     * Returns a list of menu elements for the tickets system's configuration.
2299
     *
2300
     * @param string $exclude The element to exclude from the list
2301
     *
2302
     * @return array
2303
     */
2304
    public static function getSettingsMenuItems($exclude = null)
2305
    {
2306
        $project = [
2307
            'icon' => 'project.png',
2308
            'url' => 'projects.php',
2309
            'content' => get_lang('Projects'),
2310
        ];
2311
        $status = [
2312
            'icon' => 'check-circle.png',
2313
            'url' => 'status.php',
2314
            'content' => get_lang('Status'),
2315
        ];
2316
        $priority = [
2317
            'icon' => 'tickets_urgent.png',
2318
            'url' => 'priorities.php',
2319
            'content' => get_lang('Priority'),
2320
        ];
2321
        switch ($exclude) {
2322
            case 'project':
2323
                $items = [$status, $priority];
2324
                break;
2325
            case 'status':
2326
                $items = [$project, $priority];
2327
                break;
2328
            case 'priority':
2329
                $items = [$project, $status];
2330
                break;
2331
            default:
2332
                $items = [$project, $status, $priority];
2333
                break;
2334
        }
2335
2336
        return $items;
2337
    }
2338
2339
    /**
2340
     * Returns a list of strings representing the default statuses.
2341
     *
2342
     * @return array
2343
     */
2344
    public static function getDefaultStatusList()
2345
    {
2346
        return [
2347
            self::STATUS_NEW,
2348
            self::STATUS_PENDING,
2349
            self::STATUS_UNCONFIRMED,
2350
            self::STATUS_CLOSE,
2351
            self::STATUS_FORWARDED,
2352
        ];
2353
    }
2354
2355
    /**
2356
     * @return array
2357
     */
2358
    public static function getDefaultPriorityList()
2359
    {
2360
        return [
2361
            self::PRIORITY_NORMAL,
2362
            self::PRIORITY_HIGH,
2363
            self::PRIORITY_LOW,
2364
            self::STATUS_CLOSE,
2365
            self::STATUS_FORWARDED,
2366
        ];
2367
    }
2368
2369
    /**
2370
     * Deletes the user from all the ticket system.
2371
     *
2372
     * @param int $userId
2373
     */
2374
    public static function deleteUserFromTicketSystem($userId)
2375
    {
2376
        $userId = (int) $userId;
2377
        $schema = Database::getManager()->getConnection()->getSchemaManager();
2378
2379
        if ($schema->tablesExist('ticket_assigned_log')) {
2380
            $sql = "UPDATE ticket_assigned_log SET user_id = NULL WHERE user_id = $userId";
2381
            Database::query($sql);
2382
2383
            $sql = "UPDATE ticket_assigned_log SET sys_insert_user_id = NULL WHERE sys_insert_user_id = $userId";
2384
            Database::query($sql);
2385
        }
2386
2387
        if ($schema->tablesExist('ticket_ticket')) {
2388
            $sql = "UPDATE ticket_ticket SET assigned_last_user = NULL WHERE assigned_last_user = $userId";
2389
            Database::query($sql);
2390
2391
            $sql = "UPDATE ticket_ticket SET sys_insert_user_id = NULL WHERE sys_insert_user_id = $userId";
2392
            Database::query($sql);
2393
2394
            $sql = "UPDATE ticket_ticket SET sys_lastedit_user_id = NULL WHERE sys_lastedit_user_id = $userId";
2395
            Database::query($sql);
2396
        }
2397
2398
        if ($schema->tablesExist('ticket_category')) {
2399
            $sql = "UPDATE ticket_category SET sys_insert_user_id = NULL WHERE sys_insert_user_id = $userId";
2400
            Database::query($sql);
2401
2402
            $sql = "UPDATE ticket_category SET sys_lastedit_user_id = NULL WHERE sys_lastedit_user_id = $userId";
2403
            Database::query($sql);
2404
        }
2405
2406
        if ($schema->tablesExist('ticket_category_rel_user')) {
2407
            $sql = "DELETE FROM ticket_category_rel_user WHERE user_id = $userId";
2408
            Database::query($sql);
2409
        }
2410
2411
        if ($schema->tablesExist('ticket_message')) {
2412
            $sql = "UPDATE ticket_message SET sys_insert_user_id = NULL WHERE sys_insert_user_id = $userId";
2413
            Database::query($sql);
2414
2415
            $sql = "UPDATE ticket_message SET sys_lastedit_user_id = NULL WHERE sys_lastedit_user_id = $userId";
2416
            Database::query($sql);
2417
        }
2418
2419
        if ($schema->tablesExist('ticket_message_attachments')) {
2420
            $sql = "UPDATE ticket_message_attachments SET sys_insert_user_id = NULL WHERE sys_insert_user_id = $userId";
2421
            Database::query($sql);
2422
2423
            $sql = "UPDATE ticket_message_attachments SET sys_lastedit_user_id = NULL WHERE sys_lastedit_user_id = $userId";
2424
            Database::query($sql);
2425
        }
2426
2427
        if ($schema->tablesExist('ticket_priority')) {
2428
            $sql = "UPDATE ticket_priority SET sys_insert_user_id = NULL WHERE sys_insert_user_id = $userId";
2429
            Database::query($sql);
2430
2431
            $sql = "UPDATE ticket_priority SET sys_lastedit_user_id = NULL WHERE sys_lastedit_user_id = $userId";
2432
            Database::query($sql);
2433
        }
2434
2435
        if ($schema->tablesExist('ticket_project')) {
2436
            $sql = "UPDATE ticket_project SET sys_insert_user_id = NULL WHERE sys_insert_user_id = $userId";
2437
            Database::query($sql);
2438
2439
            $sql = "UPDATE ticket_project SET sys_lastedit_user_id = NULL WHERE sys_lastedit_user_id = $userId";
2440
            Database::query($sql);
2441
        }
2442
    }
2443
2444
    /**
2445
     * @param array $userInfo
2446
     * @param int   $projectId
2447
     *
2448
     * @return bool
2449
     */
2450
    public static function userIsAllowInProject($userInfo, $projectId)
2451
    {
2452
        if (api_is_platform_admin()) {
2453
            return true;
2454
        }
2455
2456
        $allowRoleList = self::getAllowedRolesFromProject($projectId);
2457
2458
        // Check if a role was set to the project
2459
        // Project 1 is considered the default and is accessible to all users
2460
        if (!empty($allowRoleList) && is_array($allowRoleList)) {
2461
            if (in_array($userInfo['status'], $allowRoleList)) {
2462
                return true;
2463
            }
2464
        }
2465
2466
        return false;
2467
    }
2468
2469
    /**
2470
     * @param int $projectId
2471
     *
2472
     * @todo load from database instead of configuration.php setting
2473
     *
2474
     * @return array
2475
     */
2476
    public static function getAllowedRolesFromProject($projectId)
2477
    {
2478
        $options = api_get_configuration_value('ticket_project_user_roles');
2479
        if ($options) {
2480
            if (isset($options['permissions'][$projectId])) {
2481
                return $options['permissions'][$projectId];
2482
            }
2483
        }
2484
2485
        return [];
2486
    }
2487
}
2488