Passed
Push — 1.11.x ( 304865...7405ba )
by Julito
10:51
created

getAllWork()   F

Complexity

Conditions 68
Paths > 20000

Size

Total Lines 500
Code Lines 277

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 68
eloc 277
c 1
b 0
f 0
nc 1557178465
nop 8
dl 0
loc 500
rs 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CourseBundle\Entity\CStudentPublication;
6
use ChamiloSession as Session;
7
8
/**
9
 *  @author Thomas, Hugues, Christophe - original version
10
 *  @author Patrick Cool <[email protected]>, Ghent University -
11
 * ability for course admins to specify wether uploaded documents are visible or invisible by default.
12
 *  @author Roan Embrechts, code refactoring and virtual course support
13
 *  @author Frederic Vauthier, directories management
14
 *  @author Julio Montoya <[email protected]> BeezNest 2011 LOTS of bug fixes
15
 *
16
 *  @todo   this lib should be convert in a static class and moved to main/inc/lib
17
 */
18
19
/**
20
 * Displays action links (for admins, authorized groups members and authorized students).
21
 *
22
 * @param   int Whether to show tool options
23
 * @param   int Whether to show upload form option
24
 * @param bool $isTutor
25
 */
26
function displayWorkActionLinks($id, $action, $isTutor)
27
{
28
    $id = $my_back_id = (int) $id;
29
    if ('list' == $action) {
30
        $my_back_id = 0;
31
    }
32
33
    $output = '';
34
    $origin = api_get_origin();
35
36
    if (!empty($id)) {
37
        $output .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&id='.$my_back_id.'">'.
38
            Display::return_icon('back.png', get_lang('BackToWorksList'), '', ICON_SIZE_MEDIUM).
39
            '</a>';
40
    }
41
42
    if (($isTutor || api_is_allowed_to_edit(null, true)) &&
43
        'learnpath' != $origin
44
    ) {
45
        // Create dir
46
        if (empty($id)) {
47
            $output .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=create_dir">';
48
            $output .= Display::return_icon(
49
                'new_work.png',
50
                get_lang('CreateAssignment'),
51
                '',
52
                ICON_SIZE_MEDIUM
53
            );
54
            $output .= '</a>';
55
        }
56
    }
57
58
    if (api_is_allowed_to_edit(null, true) && $origin != 'learnpath' && $action == 'list') {
59
        $output .= '<a id="open-view-list" href="#">'.
60
            Display::return_icon(
61
                'listwork.png',
62
                get_lang('ViewStudents'),
63
                '',
64
                ICON_SIZE_MEDIUM
65
            ).
66
            '</a>';
67
    }
68
69
    if ('' != $output) {
70
        echo '<div class="actions">';
71
        echo $output;
72
        echo '</div>';
73
    }
74
}
75
76
/**
77
 * @param string $path
78
 * @param int    $courseId
79
 *
80
 * @return array
81
 */
82
function get_work_data_by_path($path, $courseId = 0)
83
{
84
    $path = Database::escape_string($path);
85
    $courseId = (int) $courseId;
86
    if (empty($courseId)) {
87
        $courseId = api_get_course_int_id();
88
    }
89
90
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
91
    $sql = "SELECT *  FROM $table
92
            WHERE url = '$path' AND c_id = $courseId ";
93
    $result = Database::query($sql);
94
    $return = [];
95
    if (Database::num_rows($result)) {
96
        $return = Database::fetch_array($result, 'ASSOC');
97
    }
98
99
    return $return;
100
}
101
102
/**
103
 * @param int $id
104
 * @param int $courseId
105
 * @param int $sessionId
106
 *
107
 * @return array
108
 */
109
function get_work_data_by_id($id, $courseId = 0, $sessionId = 0)
110
{
111
    $id = (int) $id;
112
    $courseId = ((int) $courseId) ?: api_get_course_int_id();
113
    $course = api_get_course_entity($courseId);
114
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
115
116
    $sessionCondition = '';
117
    if (!empty($sessionId)) {
118
        $sessionCondition = api_get_session_condition($sessionId, true);
119
    }
120
121
    $webCodePath = api_get_path(WEB_CODE_PATH);
122
123
    $sql = "SELECT * FROM $table
124
            WHERE
125
                id = $id AND c_id = $courseId
126
                $sessionCondition";
127
    $result = Database::query($sql);
128
    $work = [];
129
    if (Database::num_rows($result)) {
130
        $work = Database::fetch_array($result, 'ASSOC');
131
        if (empty($work['title'])) {
132
            $work['title'] = basename($work['url']);
133
        }
134
        $work['download_url'] = $webCodePath.'work/download.php?id='.$work['id'].'&'.api_get_cidreq();
135
        $work['view_url'] = $webCodePath.'work/view.php?id='.$work['id'].'&'.api_get_cidreq();
136
        $work['show_url'] = $webCodePath.'work/show_file.php?id='.$work['id'].'&'.api_get_cidreq();
137
        $work['show_content'] = '';
138
        if ($work['contains_file']) {
139
            $fileType = '';
140
            $file = api_get_path(SYS_COURSE_PATH).$course->getDirectory().'/'.$work['url'];
141
            if (file_exists($file)) {
142
                $fileType = mime_content_type($file);
143
            }
144
145
            if (in_array($fileType, ['image/jpeg', 'image/jpg', 'image/png', 'image/gif'])) {
146
                $work['show_content'] = Display::img($work['show_url'], $work['title'], null, false);
147
            } elseif (false !== strpos($fileType, 'video/')) {
148
                $work['show_content'] = Display::tag(
149
                    'video',
150
                    get_lang('FileFormatNotSupported'),
151
                    ['src' => $work['show_url']]
152
                );
153
            }
154
        }
155
156
        $fieldValue = new ExtraFieldValue('work');
157
        $work['extra'] = $fieldValue->getAllValuesForAnItem($id, true);
158
    }
159
160
    return $work;
161
}
162
163
/**
164
 * @param int $user_id
165
 * @param int $work_id
166
 *
167
 * @return int
168
 */
169
function get_work_count_by_student($user_id, $work_id)
170
{
171
    $user_id = (int) $user_id;
172
    $work_id = (int) $work_id;
173
    $course_id = api_get_course_int_id();
174
    $session_id = api_get_session_id();
175
    $sessionCondition = api_get_session_condition($session_id);
176
177
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
178
    $sql = "SELECT COUNT(*) as count
179
            FROM  $table
180
            WHERE
181
                c_id = $course_id AND
182
                parent_id = $work_id AND
183
                user_id = $user_id AND
184
                active IN (0, 1)
185
                $sessionCondition";
186
    $result = Database::query($sql);
187
    $return = 0;
188
    if (Database::num_rows($result)) {
189
        $return = Database::fetch_row($result, 'ASSOC');
190
        $return = (int) ($return[0]);
191
    }
192
193
    return $return;
194
}
195
196
/**
197
 * @param int $id
198
 * @param int $courseId
199
 *
200
 * @return array
201
 */
202
function get_work_assignment_by_id($id, $courseId = 0)
203
{
204
    $courseId = (int) $courseId;
205
    if (empty($courseId)) {
206
        $courseId = api_get_course_int_id();
207
    }
208
    $id = (int) $id;
209
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
210
    $sql = "SELECT * FROM $table
211
            WHERE c_id = $courseId AND publication_id = $id";
212
    $result = Database::query($sql);
213
    $return = [];
214
    if (Database::num_rows($result)) {
215
        $return = Database::fetch_array($result, 'ASSOC');
216
    }
217
218
    return $return;
219
}
220
221
/**
222
 * @param int    $id
223
 * @param array  $my_folder_data
224
 * @param string $add_in_where_query
225
 * @param int    $course_id
226
 * @param int    $session_id
227
 *
228
 * @return array
229
 */
230
function getWorkList($id, $my_folder_data, $add_in_where_query = null, $course_id = 0, $session_id = 0)
231
{
232
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
233
234
    $course_id = $course_id ? $course_id : api_get_course_int_id();
235
    $session_id = $session_id ? $session_id : api_get_session_id();
236
    $condition_session = api_get_session_condition($session_id);
237
    $group_id = api_get_group_id();
238
239
    $groupIid = 0;
240
    if ($group_id) {
241
        $groupInfo = GroupManager::get_group_properties($group_id);
242
        if ($groupInfo) {
243
            $groupIid = $groupInfo['iid'];
244
        }
245
    }
246
247
    $is_allowed_to_edit = api_is_allowed_to_edit(null, true);
248
    $linkInfo = GradebookUtils::isResourceInCourseGradebook(
249
        api_get_course_id(),
250
        3,
251
        $id,
252
        api_get_session_id()
253
    );
254
255
    if ($linkInfo) {
256
        $workInGradeBookLinkId = $linkInfo['id'];
257
        if ($workInGradeBookLinkId) {
258
            if ($is_allowed_to_edit) {
259
                if (intval($my_folder_data['qualification']) == 0) {
260
                    echo Display::return_message(
261
                        get_lang('MaxWeightNeedToBeProvided'),
262
                        'warning'
263
                    );
264
                }
265
            }
266
        }
267
    }
268
269
    $contains_file_query = '';
270
    // Get list from database
271
    if ($is_allowed_to_edit) {
272
        $active_condition = ' active IN (0, 1)';
273
        $sql = "SELECT * FROM $work_table
274
                WHERE
275
                    c_id = $course_id
276
                    $add_in_where_query
277
                    $condition_session AND
278
                    $active_condition AND
279
                    (parent_id = 0)
280
                    $contains_file_query AND
281
                    post_group_id = $groupIid
282
                ORDER BY sent_date DESC";
283
    } else {
284
        if (!empty($group_id)) {
285
            // set to select only messages posted by the user's group
286
            $group_query = " WHERE c_id = $course_id AND post_group_id = $groupIid";
287
            $subdirs_query = ' AND parent_id = 0';
288
        } else {
289
            $group_query = " WHERE c_id = $course_id AND (post_group_id = '0' OR post_group_id is NULL) ";
290
            $subdirs_query = ' AND parent_id = 0';
291
        }
292
        //@todo how we can active or not an assignment?
293
        $active_condition = ' AND active IN (1, 0)';
294
        $sql = "SELECT * FROM  $work_table
295
                $group_query
296
                $subdirs_query
297
                $add_in_where_query
298
                $active_condition
299
                $condition_session
300
                ORDER BY title";
301
    }
302
303
    $work_parents = [];
304
305
    $sql_result = Database::query($sql);
306
    if (Database::num_rows($sql_result)) {
307
        while ($work = Database::fetch_object($sql_result)) {
308
            if (0 == $work->parent_id) {
309
                $work_parents[] = $work;
310
            }
311
        }
312
    }
313
314
    return $work_parents;
315
}
316
317
/**
318
 * @param int $userId
319
 * @param int $courseId
320
 * @param int $sessionId
321
 *
322
 * @return array
323
 */
324
function getWorkPerUser($userId, $courseId = 0, $sessionId = 0)
325
{
326
    $works = getWorkList(null, null, null, $courseId, $sessionId);
327
    $result = [];
328
    if (!empty($works)) {
329
        foreach ($works as $workData) {
330
            $workId = $workData->id;
331
            $result[$workId]['work'] = $workData;
332
            $result[$workId]['work']->user_results = get_work_user_list(
333
                0,
334
                100,
335
                null,
336
                null,
337
                $workId,
338
                null,
339
                $userId,
340
                false,
341
                $courseId,
342
                $sessionId
343
            );
344
        }
345
    }
346
347
    return $result;
348
}
349
350
/**
351
 * @param int $workId
352
 * @param int $groupId
353
 * @param int $course_id
354
 * @param int $sessionId
355
 */
356
function getUniqueStudentAttemptsTotal($workId, $groupId, $course_id, $sessionId)
357
{
358
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
359
    $user_table = Database::get_main_table(TABLE_MAIN_USER);
360
    $course_id = (int) $course_id;
361
    $workId = (int) $workId;
362
    $sessionId = (int) $sessionId;
363
    $groupId = (int) $groupId;
364
    $sessionCondition = api_get_session_condition(
365
        $sessionId,
366
        true,
367
        false,
368
        'w.session_id'
369
    );
370
371
    $groupIid = 0;
372
    if ($groupId) {
373
        $groupInfo = GroupManager::get_group_properties($groupId);
374
        $groupIid = $groupInfo['iid'];
375
    }
376
377
    $sql = "SELECT count(DISTINCT u.user_id)
378
            FROM $work_table w
379
            INNER JOIN $user_table u
380
            ON w.user_id = u.user_id
381
            WHERE
382
                w.c_id = $course_id
383
                $sessionCondition AND
384
                w.parent_id = $workId AND
385
                w.post_group_id = $groupIid AND
386
                w.active IN (0, 1)
387
            ";
388
389
    $res_document = Database::query($sql);
390
    $rowCount = Database::fetch_row($res_document);
391
392
    return $rowCount[0];
393
}
394
395
/**
396
 * @param mixed $workId
397
 * @param int   $groupId
398
 * @param int   $course_id
399
 * @param int   $sessionId
400
 * @param int   $userId       user id to filter
401
 * @param array $onlyUserList only parse this user list
402
 *
403
 * @return mixed
404
 */
405
function getUniqueStudentAttempts(
406
    $workId,
407
    $groupId,
408
    $course_id,
409
    $sessionId,
410
    $userId = null,
411
    $onlyUserList = []
412
) {
413
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
414
    $user_table = Database::get_main_table(TABLE_MAIN_USER);
415
416
    $course_id = (int) $course_id;
417
    $workCondition = null;
418
    if (is_array($workId)) {
419
        $workId = array_map('intval', $workId);
420
        $workId = implode("','", $workId);
421
        $workCondition = " w.parent_id IN ('".$workId."') AND";
422
    } else {
423
        $workId = (int) $workId;
424
        $workCondition = ' w.parent_id = '.$workId.' AND';
425
    }
426
427
    $sessionId = (int) $sessionId;
428
    $groupId = (int) $groupId;
429
    $studentCondition = null;
430
431
    if (!empty($onlyUserList)) {
432
        $onlyUserList = array_map('intval', $onlyUserList);
433
        $studentCondition = "AND u.user_id IN ('".implode("', '", $onlyUserList)."') ";
434
    } else {
435
        if (empty($userId)) {
436
            return 0;
437
        }
438
    }
439
440
    $groupIid = 0;
441
    if ($groupId) {
442
        $groupInfo = GroupManager::get_group_properties($groupId);
443
        $groupIid = $groupInfo['iid'];
444
    }
445
446
    $sessionCondition = api_get_session_condition(
447
        $sessionId,
448
        true,
449
        false,
450
        'w.session_id'
451
    );
452
453
    $sql = "SELECT count(*) FROM (
454
                SELECT count(*), w.parent_id
455
                FROM $work_table w
456
                INNER JOIN $user_table u
457
                ON w.user_id = u.user_id
458
                WHERE
459
                    w.filetype = 'file' AND
460
                    w.c_id = $course_id
461
                    $sessionCondition AND
462
                    $workCondition
463
                    w.post_group_id = $groupIid AND
464
                    w.active IN (0, 1) $studentCondition
465
                ";
466
    if (!empty($userId)) {
467
        $userId = (int) $userId;
468
        $sql .= ' AND u.user_id = '.$userId;
469
    }
470
    $sql .= ' GROUP BY u.user_id, w.parent_id) as t';
471
    $result = Database::query($sql);
472
    $row = Database::fetch_row($result);
473
474
    return $row[0];
475
}
476
477
/**
478
 * Shows the work list (student view).
479
 *
480
 * @return string
481
 */
482
function showStudentWorkGrid()
483
{
484
    $courseInfo = api_get_course_info();
485
    $url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_work_student&'.api_get_cidreq();
486
487
    $columns = [
488
        get_lang('Type'),
489
        get_lang('Title'),
490
        get_lang('HandOutDateLimit'),
491
        get_lang('Feedback'),
492
        get_lang('LastUpload'),
493
    ];
494
495
    $columnModel = [
496
        ['name' => 'type', 'index' => 'type', 'width' => '30', 'align' => 'center', 'sortable' => 'false'],
497
        ['name' => 'title', 'index' => 'title', 'width' => '250', 'align' => 'left'],
498
        ['name' => 'expires_on', 'index' => 'expires_on', 'width' => '80', 'align' => 'center', 'sortable' => 'false'],
499
        ['name' => 'feedback', 'index' => 'feedback', 'width' => '80', 'align' => 'center', 'sortable' => 'false'],
500
        ['name' => 'last_upload', 'index' => 'feedback', 'width' => '125', 'align' => 'center', 'sortable' => 'false'],
501
    ];
502
503
    if ($courseInfo['show_score'] == 0) {
504
        $columnModel[] = [
505
            'name' => 'others',
506
            'index' => 'others',
507
            'width' => '80',
508
            'align' => 'left',
509
            'sortable' => 'false',
510
        ];
511
        $columns[] = get_lang('Others');
512
    }
513
514
    $params = [
515
        'autowidth' => 'true',
516
        'height' => 'auto',
517
    ];
518
519
    $html = '<script>
520
        $(function() {
521
            '.Display::grid_js('workList', $url, $columns, $columnModel, $params, [], null, true).'
522
        });
523
    </script>';
524
525
    $html .= Display::grid_html('workList');
526
527
    return $html;
528
}
529
530
/**
531
 * Shows the work list (student view).
532
 *
533
 * @return string
534
 */
535
function showStudentAllWorkGrid($withResults = 1)
536
{
537
    $withResults = (int) $withResults;
538
    $url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_all_work_student&with_results='.$withResults;
539
540
    $columns = [
541
        get_lang('Type'),
542
        get_lang('Title'),
543
        get_lang('HandOutDateLimit'),
544
    ];
545
546
    $id = 'workList';
547
    if ($withResults) {
548
        $id = 'workListWithResults';
549
        $columns[] = get_lang('Feedback');
550
        $columns[] = get_lang('LastUpload');
551
    }
552
553
    $columnModel = [
554
        ['name' => 'type', 'index' => 'type', 'width' => '50', 'align' => 'center', 'sortable' => 'false'],
555
        ['name' => 'title', 'index' => 'title', 'width' => '600', 'align' => 'left'],
556
        ['name' => 'expires_on', 'index' => 'expires_on', 'width' => '125', 'align' => 'center', 'sortable' => 'false'],
557
    ];
558
559
    if ($withResults) {
560
        $columnModel[] = [
561
            'name' => 'feedback',
562
            'index' => 'feedback',
563
            'width' => '150',
564
            'align' => 'center',
565
            'sortable' => 'false',
566
        ];
567
        $columnModel[] = [
568
            'name' => 'last_upload',
569
            'index' => 'last_upload',
570
            'width' => '150',
571
            'align' => 'center',
572
            'sortable' => 'false',
573
        ];
574
    }
575
576
    $params = [
577
        'autowidth' => 'true',
578
        'height' => 'auto',
579
    ];
580
581
    $html = '<script>
582
        $(function() {
583
            '.Display::grid_js($id, $url, $columns, $columnModel, $params, [], null, true).'
584
        });
585
    </script>';
586
587
    $html .= Display::grid_html($id);
588
589
    return $html;
590
}
591
592
/**
593
 * Shows the work list (teacher view).
594
 *
595
 * @return string
596
 */
597
function showTeacherWorkGrid()
598
{
599
    $columnModel = [
600
        ['name' => 'type', 'index' => 'type', 'width' => '35', 'align' => 'center', 'sortable' => 'false'],
601
        ['name' => 'title', 'index' => 'title', 'width' => '300', 'align' => 'left', 'wrap_cell' => "true"],
602
        ['name' => 'sent_date', 'index' => 'sent_date', 'width' => '125', 'align' => 'center'],
603
        ['name' => 'expires_on', 'index' => 'expires_on', 'width' => '125', 'align' => 'center'],
604
        ['name' => 'amount', 'index' => 'amount', 'width' => '110', 'align' => 'center', 'sortable' => 'false'],
605
        ['name' => 'actions', 'index' => 'actions', 'width' => '110', 'align' => 'left', 'sortable' => 'false'],
606
    ];
607
    $url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_work_teacher&'.api_get_cidreq();
608
    $deleteUrl = api_get_path(WEB_AJAX_PATH).'work.ajax.php?a=delete_work&'.api_get_cidreq();
609
610
    $columns = [
611
        get_lang('Type'),
612
        get_lang('Title'),
613
        get_lang('SentDate'),
614
        get_lang('HandOutDateLimit'),
615
        get_lang('AmountSubmitted'),
616
        get_lang('Actions'),
617
    ];
618
619
    $params = [
620
        'multiselect' => true,
621
        'autowidth' => 'true',
622
        'height' => 'auto',
623
    ];
624
625
    $html = '<script>
626
    $(function() {
627
        '.Display::grid_js('workList', $url, $columns, $columnModel, $params, [], null, true).'
628
        $("#workList").jqGrid(
629
            "navGrid",
630
            "#workList_pager",
631
            { edit: false, add: false, del: true },
632
            { height:280, reloadAfterSubmit:false }, // edit options
633
            { height:280, reloadAfterSubmit:false }, // add options
634
            { reloadAfterSubmit:false, url: "'.$deleteUrl.'" }, // del options
635
            { width:500 } // search options
636
        );
637
    });
638
    </script>';
639
    $html .= Display::grid_html('workList');
640
641
    return $html;
642
}
643
644
/**
645
 * Builds the form that enables the user to
646
 * move a document from one directory to another
647
 * This function has been copied from the document/document.inc.php library.
648
 *
649
 * @param array  $folders
650
 * @param string $curdirpath
651
 * @param string $move_file
652
 * @param string $group_dir
653
 *
654
 * @return string html form
655
 */
656
function build_work_move_to_selector($folders, $curdirpath, $move_file, $group_dir = '')
657
{
658
    $course_id = api_get_course_int_id();
659
    $move_file = (int) $move_file;
660
    $tbl_work = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
661
    $sql = "SELECT title, url FROM $tbl_work
662
            WHERE c_id = $course_id AND id ='".$move_file."'";
663
    $result = Database::query($sql);
664
    $row = Database::fetch_array($result, 'ASSOC');
665
    $title = empty($row['title']) ? basename($row['url']) : $row['title'];
666
667
    $form = new FormValidator(
668
        'move_to_form',
669
        'post',
670
        api_get_self().'?'.api_get_cidreq().'&curdirpath='.Security::remove_XSS($curdirpath)
671
    );
672
673
    $form->addHeader(get_lang('MoveFile').' - '.Security::remove_XSS($title));
674
    $form->addHidden('item_id', $move_file);
675
    $form->addHidden('action', 'move_to');
676
677
    // Group documents cannot be uploaded in the root
678
    if ($group_dir == '') {
679
        if (is_array($folders)) {
680
            foreach ($folders as $fid => $folder) {
681
                //you cannot move a file to:
682
                //1. current directory
683
                //2. inside the folder you want to move
684
                //3. inside a subfolder of the folder you want to move
685
                if (($curdirpath != $folder) &&
686
                    ($folder != $move_file) &&
687
                    (substr($folder, 0, strlen($move_file) + 1) != $move_file.'/')
688
                ) {
689
                    $options[$fid] = $folder;
690
                }
691
            }
692
        }
693
    } else {
694
        if ($curdirpath != '/') {
695
            $form .= '<option value="0">/ ('.get_lang('Root').')</option>';
696
        }
697
        foreach ($folders as $fid => $folder) {
698
            if (($curdirpath != $folder) && ($folder != $move_file) &&
699
                (substr($folder, 0, strlen($move_file) + 1) != $move_file.'/')
700
            ) {
701
                //cannot copy dir into his own subdir
702
                $display_folder = substr($folder, strlen($group_dir));
703
                $display_folder = ($display_folder == '') ? '/ ('.get_lang('Root').')' : $display_folder;
704
                //$form .= '<option value="'.$fid.'">'.$display_folder.'</option>'."\n";
705
                $options[$fid] = $display_folder;
706
            }
707
        }
708
    }
709
710
    $form->addSelect('move_to_id', get_lang('Select'), $options);
711
    $form->addButtonSend(get_lang('MoveFile'), 'move_file_submit');
712
713
    return $form->returnForm();
714
}
715
716
/**
717
 * creates a new directory trying to find a directory name
718
 * that doesn't already exist.
719
 *
720
 * @author Hugues Peeters <[email protected]>
721
 * @author Bert Vanderkimpen
722
 * @author Yannick Warnier <[email protected]> Adaptation for work tool
723
 *
724
 * @param string $workDir        Base work dir (.../work)
725
 * @param string $desiredDirName complete path of the desired name
726
 *
727
 * @return string actual directory name if it succeeds, boolean false otherwise
728
 */
729
function create_unexisting_work_directory($workDir, $desiredDirName)
730
{
731
    $counter = 0;
732
    $workDir = (substr($workDir, -1, 1) == '/' ? $workDir : $workDir.'/');
733
    $checkDirName = $desiredDirName;
734
    while (file_exists($workDir.$checkDirName)) {
735
        $counter++;
736
        $checkDirName = $desiredDirName.$counter;
737
    }
738
739
    if (@mkdir($workDir.$checkDirName, api_get_permissions_for_new_directories())) {
740
        return $checkDirName;
741
    } else {
742
        return false;
743
    }
744
}
745
746
/**
747
 * Delete a work-tool directory.
748
 *
749
 * @param int $id work directory id to delete
750
 *
751
 * @return int -1 on error
752
 */
753
function deleteDirWork($id)
754
{
755
    $locked = api_resource_is_locked_by_gradebook($id, LINK_STUDENTPUBLICATION);
756
757
    if ($locked == true) {
758
        echo Display::return_message(get_lang('ResourceLockedByGradebook'), 'warning');
759
760
        return false;
761
    }
762
763
    $_course = api_get_course_info();
764
    $id = (int) $id;
765
    $work_data = get_work_data_by_id($id);
766
767
    if (empty($work_data)) {
768
        return false;
769
    }
770
771
    $base_work_dir = api_get_path(SYS_COURSE_PATH).$_course['path'].'/work';
772
    $work_data_url = $base_work_dir.$work_data['url'];
773
    $check = Security::check_abs_path($work_data_url.'/', $base_work_dir.'/');
774
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
775
    $TSTDPUBASG = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
776
    $t_agenda = Database::get_course_table(TABLE_AGENDA);
777
    $course_id = api_get_course_int_id();
778
    $sessionId = api_get_session_id();
779
780
    if (!empty($work_data['url'])) {
781
        if ($check) {
782
            $consideredWorkingTime = api_get_configuration_value('considered_working_time');
783
            if (!empty($consideredWorkingTime)) {
784
                $fieldValue = new ExtraFieldValue('work');
785
                $resultExtra = $fieldValue->getAllValuesForAnItem(
786
                    $work_data['id'],
787
                    true
788
                );
789
790
                $workingTime = null;
791
                foreach ($resultExtra as $field) {
792
                    $field = $field['value'];
793
                    if ($consideredWorkingTime == $field->getField()->getVariable()) {
794
                        $workingTime = $field->getValue();
795
796
                        break;
797
                    }
798
                }
799
800
                $courseUsers = CourseManager::get_user_list_from_course_code($_course['code'], $sessionId);
801
                if (!empty($workingTime)) {
802
                    foreach ($courseUsers as $user) {
803
                        $userWorks = get_work_user_list(
804
                            0,
805
                            100,
806
                            null,
807
                            null,
808
                            $work_data['id'],
809
                            null,
810
                            $user['user_id'],
811
                            false,
812
                            $course_id,
813
                            $sessionId
814
                        );
815
816
                        if (count($userWorks) != 1) {
817
                            continue;
818
                        }
819
                        Event::eventRemoveVirtualCourseTime(
820
                            $course_id,
821
                            $user['user_id'],
822
                            $sessionId,
823
                            $workingTime,
824
                            $work_data['iid']
825
                        );
826
                    }
827
                }
828
            }
829
830
            // Deleting all contents inside the folder
831
            $sql = "UPDATE $table SET active = 2
832
                    WHERE c_id = $course_id AND filetype = 'folder' AND id = $id";
833
            Database::query($sql);
834
835
            $sql = "UPDATE $table SET active = 2
836
                    WHERE c_id = $course_id AND parent_id = $id";
837
            Database::query($sql);
838
839
            $new_dir = $work_data_url.'_DELETED_'.$id;
840
841
            if (api_get_setting('permanently_remove_deleted_files') == 'true') {
842
                my_delete($work_data_url);
843
            } else {
844
                if (file_exists($work_data_url)) {
845
                    rename($work_data_url, $new_dir);
846
                }
847
            }
848
849
            // Gets calendar_id from student_publication_assigment
850
            $sql = "SELECT add_to_calendar FROM $TSTDPUBASG
851
                    WHERE c_id = $course_id AND publication_id = $id";
852
            $res = Database::query($sql);
853
            $calendar_id = Database::fetch_row($res);
854
855
            // delete from agenda if it exists
856
            if (!empty($calendar_id[0])) {
857
                $sql = "DELETE FROM $t_agenda
858
                        WHERE c_id = $course_id AND id = '".$calendar_id[0]."'";
859
                Database::query($sql);
860
            }
861
            $sql = "DELETE FROM $TSTDPUBASG
862
                    WHERE c_id = $course_id AND publication_id = $id";
863
            Database::query($sql);
864
865
            Skill::deleteSkillsFromItem($id, ITEM_TYPE_STUDENT_PUBLICATION);
866
867
            Event::addEvent(
868
                LOG_WORK_DIR_DELETE,
869
                LOG_WORK_DATA,
870
                [
871
                    'id' => $work_data['id'],
872
                    'url' => $work_data['url'],
873
                    'title' => $work_data['title'],
874
                ],
875
                null,
876
                api_get_user_id(),
877
                api_get_course_int_id(),
878
                $sessionId
879
            );
880
881
            $linkInfo = GradebookUtils::isResourceInCourseGradebook(
882
                api_get_course_id(),
883
                3,
884
                $id,
885
                api_get_session_id()
886
            );
887
            $link_id = $linkInfo['id'];
888
            if ($linkInfo !== false) {
889
                GradebookUtils::remove_resource_from_course_gradebook($link_id);
890
            }
891
892
            return true;
893
        }
894
    }
895
}
896
897
/**
898
 * Get the path of a document in the student_publication table (path relative to the course directory).
899
 *
900
 * @param int $id
901
 *
902
 * @return string Path (or -1 on error)
903
 */
904
function get_work_path($id)
905
{
906
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
907
    $course_id = api_get_course_int_id();
908
    $sql = 'SELECT url FROM '.$table.'
909
            WHERE c_id = '.$course_id.' AND id='.(int) $id;
910
    $res = Database::query($sql);
911
    if (Database::num_rows($res)) {
912
        $row = Database::fetch_array($res);
913
914
        return $row['url'];
915
    }
916
917
    return -1;
918
}
919
920
/**
921
 * Update the url of a work in the student_publication table.
922
 *
923
 * @param int    $id        of the work to update
924
 * @param string $new_path  Destination directory where the work has been moved (must end with a '/')
925
 * @param int    $parent_id
926
 *
927
 * @return mixed Int -1 on error, sql query result on success
928
 */
929
function updateWorkUrl($id, $new_path, $parent_id)
930
{
931
    if (empty($id)) {
932
        return -1;
933
    }
934
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
935
    $course_id = api_get_course_int_id();
936
    $id = (int) $id;
937
    $parent_id = (int) $parent_id;
938
939
    $sql = "SELECT * FROM $table
940
            WHERE c_id = $course_id AND id = $id";
941
    $res = Database::query($sql);
942
    if (Database::num_rows($res) != 1) {
943
        return -1;
944
    } else {
945
        $row = Database::fetch_array($res);
946
        $filename = basename($row['url']);
947
        $new_url = $new_path.$filename;
948
        $new_url = Database::escape_string($new_url);
949
950
        $sql = "UPDATE $table SET
951
                   url = '$new_url',
952
                   parent_id = '$parent_id'
953
                WHERE c_id = $course_id AND id = $id";
954
955
        return Database::query($sql);
956
    }
957
}
958
959
/**
960
 * Update the url of a dir in the student_publication table.
961
 *
962
 * @param array  $work_data work original data
963
 * @param string $newPath   Example: "folder1"
964
 *
965
 * @return bool
966
 */
967
function updateDirName($work_data, $newPath)
968
{
969
    $course_id = $work_data['c_id'];
970
    $work_id = (int) ($work_data['iid']);
971
    $oldPath = $work_data['url'];
972
    $originalNewPath = Database::escape_string($newPath);
973
    $newPath = Database::escape_string($newPath);
974
    $newPath = api_replace_dangerous_char($newPath);
975
    $newPath = disable_dangerous_file($newPath);
976
977
    if ($oldPath == '/'.$newPath) {
978
        return true;
979
    }
980
981
    if (!empty($newPath)) {
982
        $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
983
        $sql = "UPDATE $table SET
984
                    title = '".$originalNewPath."'
985
                WHERE
986
                    c_id = $course_id AND
987
                    iid = $work_id";
988
        Database::query($sql);
989
    }
990
}
991
992
/**
993
 * returns all the javascript that is required for easily
994
 * validation when you create a work
995
 * this goes into the $htmlHeadXtra[] array.
996
 */
997
function to_javascript_work()
998
{
999
    return '<script>
1000
        function updateDocumentTitle(value) {
1001
            var temp = value.indexOf("/");
1002
            //linux path
1003
            if(temp != -1){
1004
                temp=value.split("/");
1005
            } else {
1006
                temp=value.split("\\\");
1007
            }
1008
1009
            var fullFilename = temp[temp.length - 1];
1010
            var baseFilename = fullFilename;
1011
1012
            // get file extension
1013
            var fileExtension = "";
1014
            if (fullFilename.match(/\..+/)) {
1015
                fileInfo = fullFilename.match(/(.*)\.([^.]+)$/);
1016
                if (fileInfo.length > 1) {
1017
                    fileExtension = "."+fileInfo[fileInfo.length - 1];
1018
                    baseFilename = fileInfo[fileInfo.length - 2];
1019
                }
1020
            }
1021
1022
            document.getElementById("file_upload").value = baseFilename;
1023
            document.getElementById("file_extension").value = fileExtension;
1024
            $("#contains_file_id").attr("value", 1);
1025
        }
1026
        function setFocus() {
1027
            $("#work_title").focus();
1028
        }
1029
1030
        $(function() {
1031
            setFocus();
1032
            var checked = $("#expiry_date").attr("checked");
1033
            if (checked) {
1034
                $("#option2").show();
1035
            } else {
1036
                $("#option2").hide();
1037
            }
1038
1039
            var checkedEndDate = $("#end_date").attr("checked");
1040
            if (checkedEndDate) {
1041
                $("#option3").show();
1042
                $("#ends_on").attr("checked", true);
1043
            } else {
1044
                $("#option3").hide();
1045
                $("#ends_on").attr("checked", false);
1046
            }
1047
1048
            $("#expiry_date").click(function() {
1049
                $("#option2").toggle();
1050
            });
1051
1052
            $("#end_date").click(function() {
1053
                $("#option3").toggle();
1054
            });
1055
        });
1056
    </script>';
1057
}
1058
1059
/**
1060
 * Gets the id of a student publication with a given path.
1061
 *
1062
 * @param string $path
1063
 *
1064
 * @return true if is found / false if not found
1065
 */
1066
// TODO: The name of this function does not fit with the kind of information it returns.
1067
// Maybe check_work_id() or is_work_id()?
1068
function get_work_id($path)
1069
{
1070
    $TBL_STUDENT_PUBLICATION = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
1071
    $TBL_PROP_TABLE = Database::get_course_table(TABLE_ITEM_PROPERTY);
1072
    $course_id = api_get_course_int_id();
1073
    $path = Database::escape_string($path);
1074
1075
    if (api_is_allowed_to_edit()) {
1076
        $sql = "SELECT work.id
1077
                FROM $TBL_STUDENT_PUBLICATION AS work, $TBL_PROP_TABLE AS props
1078
                WHERE
1079
                    props.c_id = $course_id AND
1080
                    work.c_id = $course_id AND
1081
                    props.tool='work' AND
1082
                    work.id=props.ref AND
1083
                    work.url LIKE 'work/".$path."%' AND
1084
                    work.filetype='file' AND
1085
                    props.visibility<>'2'";
1086
    } else {
1087
        $sql = "SELECT work.id
1088
                FROM $TBL_STUDENT_PUBLICATION AS work, $TBL_PROP_TABLE AS props
1089
                WHERE
1090
                    props.c_id = $course_id AND
1091
                    work.c_id = $course_id AND
1092
                    props.tool='work' AND
1093
                    work.id=props.ref AND
1094
                    work.url LIKE 'work/".$path."%' AND
1095
                    work.filetype='file' AND
1096
                    props.visibility<>'2' AND
1097
                    props.lastedit_user_id = '".api_get_user_id()."'";
1098
    }
1099
    $result = Database::query($sql);
1100
    $num_rows = Database::num_rows($result);
1101
1102
    if ($result && $num_rows > 0) {
1103
        return true;
1104
    } else {
1105
        return false;
1106
    }
1107
}
1108
1109
/**
1110
 * @param int $work_id
1111
 * @param int $onlyMeUserId show only my works
1112
 * @param int $notMeUserId  show works from everyone except me
1113
 *
1114
 * @return int
1115
 */
1116
function get_count_work($work_id, $onlyMeUserId = null, $notMeUserId = null)
1117
{
1118
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
1119
    $iprop_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
1120
    $user_table = Database::get_main_table(TABLE_MAIN_USER);
1121
1122
    $is_allowed_to_edit = api_is_allowed_to_edit(null, true) || api_is_coach();
1123
    $session_id = api_get_session_id();
1124
    $condition_session = api_get_session_condition(
1125
        $session_id,
1126
        true,
1127
        false,
1128
        'work.session_id'
1129
    );
1130
1131
    $group_id = api_get_group_id();
1132
    $course_info = api_get_course_info();
1133
    $course_id = $course_info['real_id'];
1134
    $work_id = (int) $work_id;
1135
1136
    $groupIid = 0;
1137
    if ($group_id) {
1138
        $groupInfo = GroupManager::get_group_properties($group_id);
1139
        if ($groupInfo && isset($groupInfo['iid'])) {
1140
            $groupIid = (int) $groupInfo['iid'];
1141
        }
1142
    }
1143
1144
    if (!empty($group_id)) {
1145
        // set to select only messages posted by the user's group
1146
        $extra_conditions = " work.post_group_id = '".$groupIid."' ";
1147
    } else {
1148
        $extra_conditions = " (work.post_group_id = '0' or work.post_group_id IS NULL) ";
1149
    }
1150
1151
    if ($is_allowed_to_edit) {
1152
        $extra_conditions .= ' AND work.active IN (0, 1) ';
1153
    } else {
1154
        $extra_conditions .= ' AND work.active IN (0, 1) AND accepted = 1';
1155
        if (isset($course_info['show_score']) && $course_info['show_score'] == 1) {
1156
            $extra_conditions .= " AND work.user_id = ".api_get_user_id()." ";
1157
        } else {
1158
            $extra_conditions .= '';
1159
        }
1160
    }
1161
1162
    $extra_conditions .= " AND parent_id  = ".$work_id."  ";
1163
    $where_condition = null;
1164
    if (!empty($notMeUserId)) {
1165
        $where_condition .= " AND u.user_id <> ".intval($notMeUserId);
1166
    }
1167
1168
    if (!empty($onlyMeUserId)) {
1169
        $where_condition .= " AND u.user_id =  ".intval($onlyMeUserId);
1170
    }
1171
1172
    $sql = "SELECT count(*) as count
1173
            FROM $iprop_table prop
1174
            INNER JOIN $work_table work
1175
            ON (
1176
                prop.ref = work.id AND
1177
                prop.c_id = $course_id AND
1178
                prop.tool='work' AND
1179
                prop.visibility <> 2 AND
1180
                work.c_id = $course_id
1181
            )
1182
            INNER JOIN $user_table u
1183
            ON (work.user_id = u.user_id)
1184
            WHERE $extra_conditions $where_condition $condition_session";
1185
1186
    $result = Database::query($sql);
1187
1188
    $users_with_work = 0;
1189
    if (Database::num_rows($result)) {
1190
        $result = Database::fetch_array($result);
1191
        $users_with_work = $result['count'];
1192
    }
1193
1194
    return $users_with_work;
1195
}
1196
1197
/**
1198
 * @param int    $start
1199
 * @param int    $limit
1200
 * @param string $column
1201
 * @param string $direction
1202
 * @param string $where_condition
1203
 * @param bool   $getCount
1204
 *
1205
 * @return array
1206
 */
1207
function getWorkListStudent(
1208
    $start,
1209
    $limit,
1210
    $column,
1211
    $direction,
1212
    $where_condition,
1213
    $getCount = false
1214
) {
1215
    $workTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
1216
    $workTableAssignment = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
1217
    $courseInfo = api_get_course_info();
1218
    $course_id = $courseInfo['real_id'];
1219
    $session_id = api_get_session_id();
1220
    $condition_session = api_get_session_condition($session_id);
1221
    $group_id = api_get_group_id();
1222
    $userId = api_get_user_id();
1223
1224
    $isDrhOfCourse = CourseManager::isUserSubscribedInCourseAsDrh(
1225
        $userId,
1226
        $courseInfo
1227
    );
1228
1229
    if (!in_array($direction, ['asc', 'desc'])) {
1230
        $direction = 'desc';
1231
    }
1232
    if (!empty($where_condition)) {
1233
        $where_condition = ' AND '.$where_condition;
1234
    }
1235
1236
    $column = !empty($column) ? Database::escape_string($column) : 'sent_date';
1237
    $start = (int) $start;
1238
    $limit = (int) $limit;
1239
1240
    $groupIid = 0;
1241
    if ($group_id) {
1242
        $groupInfo = GroupManager::get_group_properties($group_id);
1243
        if ($groupInfo) {
1244
            $groupIid = (int) $groupInfo['iid'];
1245
        }
1246
    }
1247
1248
    if (!empty($groupIid)) {
1249
        $group_query = " WHERE w.c_id = $course_id AND post_group_id = $groupIid";
1250
        $subdirs_query = 'AND parent_id = 0';
1251
    } else {
1252
        $group_query = " WHERE w.c_id = $course_id AND (post_group_id = '0' or post_group_id is NULL)  ";
1253
        $subdirs_query = 'AND parent_id = 0';
1254
    }
1255
1256
    $active_condition = ' AND active IN (1, 0)';
1257
1258
    if ($getCount) {
1259
        $select = 'SELECT count(w.id) as count ';
1260
    } else {
1261
        $select = 'SELECT w.*, a.expires_on, expires_on, ends_on, enable_qualification ';
1262
    }
1263
1264
    $sql = "$select
1265
            FROM $workTable w
1266
            LEFT JOIN $workTableAssignment a
1267
            ON (a.publication_id = w.id AND a.c_id = w.c_id)
1268
                $group_query
1269
                $subdirs_query
1270
                $active_condition
1271
                $condition_session
1272
                $where_condition
1273
            ";
1274
1275
    $sql .= " ORDER BY $column $direction ";
1276
1277
    if (!empty($start) && !empty($limit)) {
1278
        $sql .= " LIMIT $start, $limit";
1279
    }
1280
1281
    $result = Database::query($sql);
1282
1283
    if ($getCount) {
1284
        $row = Database::fetch_array($result);
1285
1286
        return $row['count'];
1287
    }
1288
1289
    $works = [];
1290
    $url = api_get_path(WEB_CODE_PATH).'work/work_list.php?'.api_get_cidreq();
1291
    if ($isDrhOfCourse) {
1292
        $url = api_get_path(WEB_CODE_PATH).'work/work_list_all.php?'.api_get_cidreq();
1293
    }
1294
1295
    $urlOthers = api_get_path(WEB_CODE_PATH).'work/work_list_others.php?'.api_get_cidreq().'&id=';
1296
    while ($work = Database::fetch_array($result, 'ASSOC')) {
1297
        $isSubscribed = userIsSubscribedToWork($userId, $work['id'], $course_id);
1298
        if ($isSubscribed == false) {
1299
            continue;
1300
        }
1301
1302
        $visibility = api_get_item_visibility($courseInfo, 'work', $work['id'], $session_id);
1303
1304
        if ($visibility != 1) {
1305
            continue;
1306
        }
1307
1308
        $work['type'] = Display::return_icon('work.png');
1309
        $work['expires_on'] = empty($work['expires_on']) ? null : api_get_local_time($work['expires_on']);
1310
1311
        if (empty($work['title'])) {
1312
            $work['title'] = basename($work['url']);
1313
        }
1314
1315
        $whereCondition = " AND u.user_id = $userId ";
1316
1317
        $workList = get_work_user_list(
1318
            0,
1319
            1000,
1320
            null,
1321
            null,
1322
            $work['id'],
1323
            $whereCondition
1324
        );
1325
1326
        $count = getTotalWorkComment($workList, $courseInfo);
1327
        $lastWork = getLastWorkStudentFromParentByUser($userId, $work, $courseInfo);
1328
1329
        if (!is_null($count) && !empty($count)) {
1330
            $urlView = api_get_path(WEB_CODE_PATH).'work/view.php?id='.$lastWork['id'].'&'.api_get_cidreq();
1331
1332
            $feedback = '&nbsp;'.Display::url(
1333
                Display::returnFontAwesomeIcon('comments-o'),
1334
                $urlView,
1335
                ['title' => get_lang('View')]
1336
            );
1337
1338
            $work['feedback'] = ' '.Display::label($count.' '.get_lang('Feedback'), 'info').$feedback;
1339
        }
1340
1341
        if (!empty($lastWork)) {
1342
            $work['last_upload'] = (!empty($lastWork['qualification'])) ? $lastWork['qualification_rounded'].' - ' : '';
1343
            $work['last_upload'] .= api_get_local_time($lastWork['sent_date']);
1344
        }
1345
1346
        $work['title'] = Display::url($work['title'], $url.'&id='.$work['id']);
1347
        $work['others'] = Display::url(
1348
            Display::return_icon('group.png', get_lang('Others')),
1349
            $urlOthers.$work['id']
1350
        );
1351
        $works[] = $work;
1352
    }
1353
1354
    return $works;
1355
}
1356
1357
/**
1358
 * @param int    $start
1359
 * @param int    $limit
1360
 * @param string $column
1361
 * @param string $direction
1362
 * @param string $where_condition
1363
 * @param bool   $getCount
1364
 * @param int    $withResults
1365
 *
1366
 * @return array
1367
 */
1368
function getAllWorkListStudent(
1369
    $start,
1370
    $limit,
1371
    $column,
1372
    $direction,
1373
    $where_condition,
1374
    $getCount = false,
1375
    $withResults = 1
1376
) {
1377
    $workTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
1378
    $workTableAssignment = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
1379
    $userId = api_get_user_id();
1380
1381
    if (empty($userId)) {
1382
        return [];
1383
    }
1384
1385
    $courses = CourseManager::get_courses_list_by_user_id($userId, true);
1386
1387
    if (!empty($where_condition)) {
1388
        $where_condition = ' AND '.$where_condition;
1389
    }
1390
1391
    if (!in_array($direction, ['asc', 'desc'])) {
1392
        $direction = 'desc';
1393
    }
1394
1395
    $column = !empty($column) ? Database::escape_string($column) : 'sent_date';
1396
    $start = (int) $start;
1397
    $limit = (int) $limit;
1398
    $courseQuery = [];
1399
    $courseList = [];
1400
    foreach ($courses as $course) {
1401
        $course_id = $course['real_id'];
1402
        $courseInfo = api_get_course_info_by_id($course_id);
1403
        $session_id = isset($course['session_id']) ? $course['session_id'] : 0;
1404
        $conditionSession = api_get_session_condition($session_id, true, false, 'w.session_id');
1405
        $parentCondition = '';
1406
        if ($withResults) {
1407
            $parentCondition = 'AND ww.parent_id is NOT NULL';
1408
        }
1409
        $courseQuery[] = " (w.c_id = $course_id $conditionSession $parentCondition )";
1410
        $courseList[$course_id] = $courseInfo;
1411
    }
1412
1413
    $courseQueryToString = implode(' OR ', $courseQuery);
1414
1415
    if ($getCount) {
1416
        if (empty($courseQuery)) {
1417
            return 0;
1418
        }
1419
        $select = 'SELECT count(DISTINCT(w.id)) as count ';
1420
    } else {
1421
        if (empty($courseQuery)) {
1422
            return [];
1423
        }
1424
        $select = 'SELECT DISTINCT
1425
                        w.title,
1426
                        w.url,
1427
                        w.id,
1428
                        w.c_id,
1429
                        w.session_id,
1430
                        a.expires_on,
1431
                        a.ends_on,
1432
                        a.enable_qualification,
1433
                        w.qualification,
1434
                        a.publication_id';
1435
    }
1436
1437
    $checkSentWork = " LEFT JOIN $workTable ww
1438
                       ON (ww.c_id = w.c_id AND ww.parent_id = w.id AND ww.user_id = $userId ) ";
1439
    $where = ' AND ww.url IS NULL ';
1440
    $expirationCondition = " AND (a.expires_on IS NULL OR a.expires_on > '".api_get_utc_datetime()."') ";
1441
    if ($withResults) {
1442
        $where = '';
1443
        $checkSentWork = " LEFT JOIN $workTable ww
1444
                           ON (
1445
                            ww.c_id = w.c_id AND
1446
                            ww.parent_id = w.id AND
1447
                            ww.user_id = $userId AND
1448
                            a.expires_on IS NULL AND
1449
                            ww.parent_id is NOT NULL
1450
                        ) ";
1451
        $expirationCondition = " OR (
1452
                ww.parent_id is NULL AND
1453
                a.expires_on IS NOT NULL AND
1454
                a.expires_on < '".api_get_utc_datetime()."'
1455
            ) ";
1456
    }
1457
1458
    $sql = "$select
1459
            FROM $workTable w
1460
            LEFT JOIN $workTableAssignment a
1461
            ON (a.publication_id = w.id AND a.c_id = w.c_id)
1462
            $checkSentWork
1463
            WHERE
1464
                w.parent_id = 0 AND
1465
                w.active IN (1, 0) AND
1466
                ($courseQueryToString)
1467
                $where_condition
1468
                $expirationCondition
1469
                $where
1470
            ";
1471
1472
    $sql .= " ORDER BY $column $direction ";
1473
1474
    if (!empty($start) && !empty($limit)) {
1475
        $sql .= " LIMIT $start, $limit";
1476
    }
1477
1478
    $result = Database::query($sql);
1479
1480
    if ($getCount) {
1481
        $row = Database::fetch_array($result);
1482
1483
        if ($row) {
1484
            return (int) $row['count'];
1485
        }
1486
1487
        return 0;
1488
    }
1489
1490
    $works = [];
1491
    while ($work = Database::fetch_array($result, 'ASSOC')) {
1492
        $courseId = $work['c_id'];
1493
        $courseInfo = $courseList[$work['c_id']];
1494
        $courseCode = $courseInfo['code'];
1495
        $sessionId = $work['session_id'];
1496
1497
        $cidReq = api_get_cidreq_params($courseCode, $sessionId);
1498
        $url = api_get_path(WEB_CODE_PATH).'work/work_list.php?'.$cidReq;
1499
        $isSubscribed = userIsSubscribedToWork($userId, $work['id'], $courseId);
1500
        if ($isSubscribed == false) {
1501
            continue;
1502
        }
1503
1504
        $visibility = api_get_item_visibility($courseInfo, 'work', $work['id'], $sessionId);
1505
1506
        if ($visibility != 1) {
1507
            continue;
1508
        }
1509
1510
        $work['type'] = Display::return_icon('work.png');
1511
        $work['expires_on'] = empty($work['expires_on']) ? null : api_get_local_time($work['expires_on']);
1512
1513
        if (empty($work['title'])) {
1514
            $work['title'] = basename($work['url']);
1515
        }
1516
1517
        if ($withResults) {
1518
            $whereCondition = " AND u.user_id = $userId ";
1519
            $workList = get_work_user_list(
1520
                0,
1521
                1000,
1522
                null,
1523
                null,
1524
                $work['id'],
1525
                $whereCondition,
1526
                null,
1527
                false,
1528
                $courseId,
1529
                $sessionId
1530
            );
1531
1532
            $count = getTotalWorkComment($workList, $courseInfo);
1533
            $lastWork = getLastWorkStudentFromParentByUser($userId, $work, $courseInfo);
1534
1535
            if (!is_null($count) && !empty($count)) {
1536
                $urlView = api_get_path(WEB_CODE_PATH).'work/view.php?id='.$lastWork['id'].'&'.$cidReq;
1537
1538
                $feedback = '&nbsp;'.Display::url(
1539
                        Display::returnFontAwesomeIcon('comments-o'),
1540
                        $urlView,
1541
                        ['title' => get_lang('View')]
1542
                    );
1543
1544
                $work['feedback'] = ' '.Display::label($count.' '.get_lang('Feedback'), 'info').$feedback;
1545
            }
1546
1547
            if (!empty($lastWork)) {
1548
                $work['last_upload'] = (!empty($lastWork['qualification'])) ? $lastWork['qualification_rounded'].' - ' : '';
1549
                $work['last_upload'] .= api_get_local_time($lastWork['sent_date']);
1550
            }
1551
        }
1552
1553
        $work['title'] = Display::url($work['title'], $url.'&id='.$work['id']);
1554
        $works[] = $work;
1555
    }
1556
1557
    return $works;
1558
}
1559
1560
/**
1561
 * @param int    $start
1562
 * @param int    $limit
1563
 * @param string $column
1564
 * @param string $direction
1565
 * @param string $where_condition
1566
 * @param bool   $getCount
1567
 *
1568
 * @return array
1569
 */
1570
function getWorkListTeacher(
1571
    $start,
1572
    $limit,
1573
    $column,
1574
    $direction,
1575
    $where_condition,
1576
    $getCount = false,
1577
    $courseInfoParam = []
1578
) {
1579
    $workTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
1580
    $workTableAssignment = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
1581
1582
    $courseInfo = api_get_course_info();
1583
    $course_id = api_get_course_int_id();
1584
    if (!empty($courseInfoParam)) {
1585
        $courseInfo = $courseInfoParam;
1586
        $course_id = $courseInfoParam['real_id'];
1587
    }
1588
1589
    $session_id = api_get_session_id();
1590
    $condition_session = api_get_session_condition($session_id);
1591
    $group_id = api_get_group_id();
1592
    $groupIid = 0;
1593
    if ($group_id) {
1594
        $groupInfo = GroupManager::get_group_properties($group_id);
1595
        $groupIid = $groupInfo['iid'];
1596
    }
1597
    $groupIid = (int) $groupIid;
1598
1599
    $is_allowed_to_edit = api_is_allowed_to_edit() || api_is_coach();
1600
    if (!in_array($direction, ['asc', 'desc'])) {
1601
        $direction = 'desc';
1602
    }
1603
    if (!empty($where_condition)) {
1604
        $where_condition = ' AND '.$where_condition;
1605
    }
1606
1607
    $column = !empty($column) ? Database::escape_string($column) : 'sent_date';
1608
    $start = (int) $start;
1609
    $limit = (int) $limit;
1610
    $works = [];
1611
1612
    // Get list from database
1613
    if ($is_allowed_to_edit) {
1614
        $active_condition = ' active IN (0, 1)';
1615
        if ($getCount) {
1616
            $select = " SELECT count(w.id) as count";
1617
        } else {
1618
            $select = " SELECT w.*, a.expires_on, expires_on, ends_on, enable_qualification ";
1619
        }
1620
        $sql = " $select
1621
                FROM $workTable w
1622
                LEFT JOIN $workTableAssignment a
1623
                ON (a.publication_id = w.id AND a.c_id = w.c_id)
1624
                WHERE
1625
                    w.c_id = $course_id
1626
                    $condition_session AND
1627
                    $active_condition AND
1628
                    parent_id = 0 AND
1629
                    post_group_id = $groupIid
1630
                    $where_condition
1631
                ORDER BY $column $direction
1632
                LIMIT $start, $limit";
1633
1634
        $result = Database::query($sql);
1635
1636
        if ($getCount) {
1637
            $row = Database::fetch_array($result);
1638
1639
            return (int) $row['count'];
1640
        }
1641
1642
        $url = api_get_path(WEB_CODE_PATH).'work/work_list_all.php?'.api_get_cidreq();
1643
        $blockEdition = api_get_configuration_value('block_student_publication_edition');
1644
        while ($work = Database::fetch_array($result, 'ASSOC')) {
1645
            $workId = $work['id'];
1646
            $work['type'] = Display::return_icon('work.png');
1647
            $work['expires_on'] = empty($work['expires_on']) ? null : api_get_local_time($work['expires_on']);
1648
1649
            $countUniqueAttempts = getUniqueStudentAttemptsTotal(
1650
                $workId,
1651
                $group_id,
1652
                $course_id,
1653
                $session_id
1654
            );
1655
1656
            $totalUsers = getStudentSubscribedToWork(
1657
                $workId,
1658
                $course_id,
1659
                $group_id,
1660
                $session_id,
1661
                true
1662
            );
1663
1664
            $work['amount'] = Display::label(
1665
                $countUniqueAttempts.'/'.
1666
                $totalUsers,
1667
                'success'
1668
            );
1669
1670
            $visibility = api_get_item_visibility($courseInfo, 'work', $workId, $session_id);
1671
1672
            if ($visibility == 1) {
1673
                $icon = 'visible.png';
1674
                $text = get_lang('Visible');
1675
                $action = 'invisible';
1676
                $class = '';
1677
            } else {
1678
                $icon = 'invisible.png';
1679
                $text = get_lang('Invisible');
1680
                $action = 'visible';
1681
                $class = 'muted';
1682
            }
1683
1684
            $visibilityLink = Display::url(
1685
                Display::return_icon($icon, $text, [], ICON_SIZE_SMALL),
1686
                api_get_path(WEB_CODE_PATH).'work/work.php?id='.$workId.'&action='.$action.'&'.api_get_cidreq()
1687
            );
1688
1689
            if (empty($work['title'])) {
1690
                $work['title'] = basename($work['url']);
1691
            }
1692
            $work['title'] = Display::url($work['title'], $url.'&id='.$workId, ['class' => $class]);
1693
            $work['title'] .= ' '.Display::label(get_count_work($work['id']), 'success');
1694
            $work['sent_date'] = api_get_local_time($work['sent_date']);
1695
1696
            if ($blockEdition && !api_is_platform_admin()) {
1697
                $editLink = '';
1698
            } else {
1699
                $editLink = Display::url(
1700
                    Display::return_icon('edit.png', get_lang('Edit'), [], ICON_SIZE_SMALL),
1701
                    api_get_path(WEB_CODE_PATH).'work/edit_work.php?id='.$workId.'&'.api_get_cidreq()
1702
                );
1703
            }
1704
1705
            $correctionLink = '&nbsp;'.Display::url(
1706
                Display::return_icon('upload_package.png', get_lang('UploadCorrections'), '', ICON_SIZE_SMALL),
1707
                api_get_path(WEB_CODE_PATH).'work/upload_corrections.php?'.api_get_cidreq().'&id='.$workId
1708
            ).'&nbsp;';
1709
1710
            if ($countUniqueAttempts > 0) {
1711
                $downloadLink = Display::url(
1712
                    Display::return_icon(
1713
                        'save_pack.png',
1714
                        get_lang('Save'),
1715
                        [],
1716
                        ICON_SIZE_SMALL
1717
                    ),
1718
                    api_get_path(WEB_CODE_PATH).'work/downloadfolder.inc.php?id='.$workId.'&'.api_get_cidreq()
1719
                );
1720
            } else {
1721
                $downloadLink = Display::url(
1722
                    Display::return_icon(
1723
                        'save_pack_na.png',
1724
                        get_lang('Save'),
1725
                        [],
1726
                        ICON_SIZE_SMALL
1727
                    ),
1728
                    '#'
1729
                );
1730
            }
1731
            // Remove Delete Work Button from action List
1732
            // Because removeXSS "removes" the onClick JS Event to do the action (See model.ajax.php - Line 1639)
1733
            // But still can use the another jqgrid button to remove works (trash icon)
1734
            //
1735
            // $deleteUrl = api_get_path(WEB_CODE_PATH).'work/work.php?id='.$workId.'&action=delete_dir&'.api_get_cidreq();
1736
            // $deleteLink = '<a href="#" onclick="showConfirmationPopup(this, \'' . $deleteUrl . '\' ) " >' .
1737
            //     Display::return_icon(
1738
            //         'delete.png',
1739
            //         get_lang('Delete'),
1740
            //         [],
1741
            //         ICON_SIZE_SMALL
1742
            //     ) . '</a>';
1743
1744
            if (!api_is_allowed_to_edit()) {
1745
                // $deleteLink = null;
1746
                $editLink = null;
1747
            }
1748
            $work['actions'] = $visibilityLink.$correctionLink.$downloadLink.$editLink;
1749
            $works[] = $work;
1750
        }
1751
    }
1752
1753
    return $works;
1754
}
1755
1756
/**
1757
 * @param int    $start
1758
 * @param int    $limit
1759
 * @param string $column
1760
 * @param string $direction
1761
 * @param int    $workId
1762
 * @param int    $studentId
1763
 * @param string $whereCondition
1764
 * @param bool   $getCount
1765
 *
1766
 * @return array
1767
 */
1768
function get_work_user_list_from_documents(
1769
    $start,
1770
    $limit,
1771
    $column,
1772
    $direction,
1773
    $workId,
1774
    $studentId = null,
1775
    $whereCondition = '',
1776
    $getCount = false
1777
) {
1778
    if ($getCount) {
1779
        $select1 = ' SELECT count(u.user_id) as count ';
1780
        $select2 = ' SELECT count(u.user_id) as count ';
1781
    } else {
1782
        $select1 = ' SELECT DISTINCT
1783
                        u.firstname,
1784
                        u.lastname,
1785
                        u.user_id,
1786
                        w.title,
1787
                        w.parent_id,
1788
                        w.document_id document_id,
1789
                        w.id, qualification,
1790
                        qualificator_id,
1791
                        w.sent_date,
1792
                        w.contains_file,
1793
                        w.url,
1794
                        w.url_correction
1795
                    ';
1796
        $select2 = ' SELECT DISTINCT
1797
                        u.firstname, u.lastname,
1798
                        u.user_id,
1799
                        d.title,
1800
                        w.parent_id,
1801
                        d.id document_id,
1802
                        0,
1803
                        0,
1804
                        0,
1805
                        w.sent_date,
1806
                        w.contains_file,
1807
                        w.url,
1808
                        w.url_correction
1809
                    ';
1810
    }
1811
1812
    $documentTable = Database::get_course_table(TABLE_DOCUMENT);
1813
    $workTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
1814
    $workRelDocument = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_DOCUMENT);
1815
    $userTable = Database::get_main_table(TABLE_MAIN_USER);
1816
1817
    $courseId = api_get_course_int_id();
1818
    $sessionId = api_get_session_id();
1819
1820
    if (empty($studentId)) {
1821
        $studentId = api_get_user_id();
1822
    }
1823
1824
    $studentId = (int) $studentId;
1825
    $workId = (int) $workId;
1826
1827
    $userCondition = " AND u.user_id = $studentId ";
1828
    $sessionCondition = api_get_session_condition($sessionId, true, false, 'w.session_id');
1829
    $workCondition = " AND w_rel.work_id = $workId";
1830
    $workParentCondition = " AND w.parent_id = $workId";
1831
1832
    $sql = "(
1833
                $select1 FROM $userTable u
1834
                INNER JOIN $workTable w
1835
                ON (u.user_id = w.user_id AND w.active IN (0, 1) AND w.filetype = 'file')
1836
                WHERE
1837
                    w.c_id = $courseId
1838
                    $userCondition
1839
                    $sessionCondition
1840
                    $whereCondition
1841
                    $workParentCondition
1842
            ) UNION (
1843
                $select2 FROM $workTable w
1844
                INNER JOIN $workRelDocument w_rel
1845
                ON (w_rel.work_id = w.id AND w.active IN (0, 1) AND w_rel.c_id = w.c_id)
1846
                INNER JOIN $documentTable d
1847
                ON (w_rel.document_id = d.id AND d.c_id = w.c_id)
1848
                INNER JOIN $userTable u ON (u.user_id = $studentId)
1849
                WHERE
1850
                    w.c_id = $courseId
1851
                    $workCondition
1852
                    $sessionCondition AND
1853
                    d.id NOT IN (
1854
                        SELECT w.document_id id
1855
                        FROM $workTable w
1856
                        WHERE
1857
                            user_id = $studentId AND
1858
                            c_id = $courseId AND
1859
                            filetype = 'file' AND
1860
                            active IN (0, 1)
1861
                            $sessionCondition
1862
                            $workParentCondition
1863
                    )
1864
            )";
1865
1866
    $start = (int) $start;
1867
    $limit = (int) $limit;
1868
1869
    $direction = in_array(strtolower($direction), ['desc', 'asc']) ? $direction : 'desc';
1870
    $column = Database::escape_string($column);
1871
1872
    if ($getCount) {
1873
        $result = Database::query($sql);
1874
        $result = Database::fetch_array($result);
1875
1876
        return $result['count'];
1877
    }
1878
1879
    $sql .= " ORDER BY $column $direction";
1880
    $sql .= " LIMIT $start, $limit";
1881
1882
    $result = Database::query($sql);
1883
1884
    $currentUserId = api_get_user_id();
1885
    $work_data = get_work_data_by_id($workId);
1886
    $qualificationExists = false;
1887
    if (!empty($work_data['qualification']) && intval($work_data['qualification']) > 0) {
1888
        $qualificationExists = true;
1889
    }
1890
1891
    $urlAdd = api_get_path(WEB_CODE_PATH).'work/upload_from_template.php?'.api_get_cidreq();
1892
    $urlEdit = api_get_path(WEB_CODE_PATH).'work/edit.php?'.api_get_cidreq();
1893
    $urlDelete = api_get_path(WEB_CODE_PATH).'work/work_list.php?action=delete&'.api_get_cidreq();
1894
    $urlView = api_get_path(WEB_CODE_PATH).'work/view.php?'.api_get_cidreq();
1895
    $urlDownload = api_get_path(WEB_CODE_PATH).'work/download.php?'.api_get_cidreq();
1896
1897
    $correctionIcon = Display::return_icon(
1898
        'check-circle.png',
1899
        get_lang('Correction'),
1900
        null,
1901
        ICON_SIZE_SMALL
1902
    );
1903
    $editIcon = Display::return_icon('edit.png', get_lang('Edit'));
1904
    $addIcon = Display::return_icon('add.png', get_lang('Add'));
1905
    $deleteIcon = Display::return_icon('delete.png', get_lang('Delete'));
1906
    $viewIcon = Display::return_icon('default.png', get_lang('View'));
1907
    $saveIcon = Display::return_icon(
1908
        'save.png',
1909
        get_lang('Save'),
1910
        [],
1911
        ICON_SIZE_SMALL
1912
    );
1913
    $allowEdition = api_get_course_setting('student_delete_own_publication') == 1;
1914
    $cidReq = api_get_cidreq();
1915
    $workList = [];
1916
    while ($row = Database::fetch_array($result, 'ASSOC')) {
1917
        $userId = $row['user_id'];
1918
        $documentId = $row['document_id'];
1919
        $itemId = $row['id'];
1920
        $addLinkShowed = false;
1921
1922
        if (empty($documentId)) {
1923
            $url = $urlEdit.'&item_id='.$row['id'].'&id='.$workId;
1924
            $editLink = Display::url($editIcon, $url);
1925
            if (1 != $allowEdition) {
1926
                $editLink = null;
1927
            }
1928
        } else {
1929
            $documentToWork = getDocumentToWorkPerUser($documentId, $workId, $courseId, $sessionId, $userId);
1930
1931
            if (empty($documentToWork)) {
1932
                $url = $urlAdd.'&document_id='.$documentId.'&id='.$workId;
1933
                $editLink = Display::url($addIcon, $url);
1934
                $addLinkShowed = true;
1935
            } else {
1936
                $row['title'] = $documentToWork['title'];
1937
                $row['sent_date'] = $documentToWork['sent_date'];
1938
                $newWorkId = $documentToWork['id'];
1939
                $url = $urlEdit.'&item_id='.$newWorkId.'&id='.$workId;
1940
                $editLink = Display::url($editIcon, $url);
1941
1942
                if (1 != $allowEdition) {
1943
                    $editLink = '';
1944
                }
1945
            }
1946
        }
1947
1948
        $downloadLink = '';
1949
        // If URL is present then there's a file to download keep BC.
1950
        if ($row['contains_file'] || !empty($row['url'])) {
1951
            $downloadLink = Display::url($saveIcon, $urlDownload.'&id='.$row['id']).'&nbsp;';
1952
        }
1953
1954
        $viewLink = '';
1955
        if (!empty($itemId)) {
1956
            $viewLink = Display::url($viewIcon, $urlView.'&id='.$itemId);
1957
        }
1958
1959
        $deleteLink = '';
1960
        if ($allowEdition == 1 && !empty($itemId)) {
1961
            $deleteLink = Display::url($deleteIcon, $urlDelete.'&item_id='.$itemId.'&id='.$workId);
1962
        }
1963
1964
        $row['type'] = null;
1965
        if ($qualificationExists) {
1966
            if (empty($row['qualificator_id'])) {
1967
                $status = Display::label(get_lang('NotRevised'), 'warning');
1968
            } else {
1969
                $status = Display::label(get_lang('Revised'), 'success');
1970
            }
1971
            $row['qualificator_id'] = $status;
1972
        }
1973
1974
        $hasCorrection = '';
1975
        if (!empty($row['url_correction'])) {
1976
            $hasCorrection = '&nbsp;'.Display::url(
1977
                $correctionIcon,
1978
                api_get_path(WEB_CODE_PATH).'work/download.php?id='.$itemId.'&'.$cidReq.'&correction=1'
1979
            );
1980
        }
1981
1982
        $qualification_string = '';
1983
        if ($qualificationExists) {
1984
            if ($row['qualification'] == '') {
1985
                $qualification_string = Display::label('-');
1986
            } else {
1987
                $qualification_string = formatWorkScore($row['qualification'], $work_data['qualification']);
1988
            }
1989
        }
1990
1991
        $row['qualification'] = $qualification_string.$hasCorrection;
1992
1993
        /*if (!empty($row['qualification'])) {
1994
            $row['qualification'] = Display::label($row['qualification'], 'info');
1995
        }*/
1996
1997
        if (!empty($row['sent_date'])) {
1998
            $row['sent_date'] = Display::dateToStringAgoAndLongDate($row['sent_date']);
1999
        }
2000
2001
        if ($userId == $currentUserId) {
2002
            $row['actions'] = $downloadLink.$viewLink.$editLink.$deleteLink;
2003
        }
2004
2005
        if ($addLinkShowed) {
2006
            $row['qualification'] = '';
2007
            $row['qualificator_id'] = '';
2008
        }
2009
2010
        $workList[] = $row;
2011
    }
2012
2013
    return $workList;
2014
}
2015
2016
/**
2017
 * @param int    $start
2018
 * @param int    $limit
2019
 * @param int    $column
2020
 * @param string $direction
2021
 * @param int    $work_id
2022
 * @param string $whereCondition
2023
 * @param int    $studentId
2024
 * @param bool   $getCount
2025
 * @param int    $courseId
2026
 * @param int    $sessionId
2027
 *
2028
 * @return array
2029
 */
2030
function get_work_user_list(
2031
    $start,
2032
    $limit,
2033
    $column,
2034
    $direction,
2035
    $work_id,
2036
    $whereCondition = '',
2037
    $studentId = null,
2038
    $getCount = false,
2039
    $courseId = 0,
2040
    $sessionId = 0
2041
) {
2042
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
2043
    $user_table = Database::get_main_table(TABLE_MAIN_USER);
2044
2045
    $session_id = $sessionId ? (int) $sessionId : api_get_session_id();
2046
    $group_id = api_get_group_id();
2047
    $course_info = api_get_course_info();
2048
    $course_info = empty($course_info) ? api_get_course_info_by_id($courseId) : $course_info;
2049
    $course_id = isset($course_info['real_id']) ? $course_info['real_id'] : $courseId;
2050
2051
    $work_id = (int) $work_id;
2052
    $start = (int) $start;
2053
    $limit = (int) $limit;
2054
2055
    $column = !empty($column) ? Database::escape_string($column) : 'sent_date';
2056
    $compilation = null;
2057
    if (api_get_configuration_value('allow_compilatio_tool')) {
2058
        $compilation = new Compilatio();
2059
    }
2060
2061
    if (!in_array($direction, ['asc', 'desc'])) {
2062
        $direction = 'desc';
2063
    }
2064
2065
    $work_data = get_work_data_by_id($work_id, $courseId, $sessionId);
2066
    $is_allowed_to_edit = api_is_allowed_to_edit() || api_is_coach();
2067
    $condition_session = api_get_session_condition(
2068
        $session_id,
2069
        true,
2070
        false,
2071
        'work.session_id'
2072
    );
2073
2074
    $locked = api_resource_is_locked_by_gradebook(
2075
        $work_id,
2076
        LINK_STUDENTPUBLICATION,
2077
        $course_info['code']
2078
    );
2079
2080
    $isDrhOfCourse = CourseManager::isUserSubscribedInCourseAsDrh(
2081
        api_get_user_id(),
2082
        $course_info
2083
    );
2084
2085
    $isDrhOfSession = !empty(SessionManager::getSessionFollowedByDrh(api_get_user_id(), $session_id));
2086
2087
    $groupIid = 0;
2088
    if ($group_id) {
2089
        $groupInfo = GroupManager::get_group_properties($group_id);
2090
        if ($groupInfo) {
2091
            $groupIid = $groupInfo['iid'];
2092
        }
2093
    }
2094
2095
    if (!empty($work_data)) {
2096
        if (!empty($group_id)) {
2097
            // set to select only messages posted by the user's group
2098
            $extra_conditions = " work.post_group_id = '".$groupIid."' ";
2099
        } else {
2100
            $extra_conditions = " (work.post_group_id = '0' OR work.post_group_id is NULL) ";
2101
        }
2102
2103
        if ($is_allowed_to_edit || $isDrhOfCourse || $isDrhOfSession) {
2104
            $extra_conditions .= ' AND work.active IN (0, 1) ';
2105
        } else {
2106
            if (isset($course_info['show_score']) &&
2107
                1 == $course_info['show_score']
2108
            ) {
2109
                $extra_conditions .= ' AND (u.user_id = '.api_get_user_id().' AND work.active IN (0, 1)) ';
2110
            } else {
2111
                $extra_conditions .= ' AND work.active IN (0, 1) ';
2112
            }
2113
        }
2114
2115
        $extra_conditions .= " AND parent_id  = $work_id ";
2116
2117
        $select = 'SELECT DISTINCT
2118
                        u.user_id,
2119
                        work.id as id,
2120
                        title as title,
2121
                        description,
2122
                        url,
2123
                        sent_date,
2124
                        contains_file,
2125
                        has_properties,
2126
                        view_properties,
2127
                        qualification,
2128
                        weight,
2129
                        allow_text_assignment,
2130
                        u.firstname,
2131
                        u.lastname,
2132
                        u.username,
2133
                        parent_id,
2134
                        accepted,
2135
                        qualificator_id,
2136
                        url_correction,
2137
                        title_correction
2138
                        ';
2139
        if ($getCount) {
2140
            $select = 'SELECT DISTINCT count(u.user_id) as count ';
2141
        }
2142
2143
        $work_assignment = get_work_assignment_by_id($work_id, $courseId);
2144
2145
        if (!empty($studentId)) {
2146
            $studentId = (int) $studentId;
2147
            $whereCondition .= " AND u.user_id = $studentId ";
2148
        }
2149
2150
        $sql = " $select
2151
                FROM $work_table work
2152
                INNER JOIN $user_table u
2153
                ON (work.user_id = u.user_id)
2154
                WHERE
2155
                    work.c_id = $course_id AND
2156
                    $extra_conditions
2157
                    $whereCondition
2158
                    $condition_session
2159
                    AND u.status != ".INVITEE."
2160
                ORDER BY $column $direction";
2161
2162
        if (!empty($start) && !empty($limit)) {
2163
            $sql .= " LIMIT $start, $limit";
2164
        }
2165
        $result = Database::query($sql);
2166
        $works = [];
2167
2168
        if ($getCount) {
2169
            $work = Database::fetch_array($result, 'ASSOC');
2170
            if ($work) {
2171
                return (int) $work['count'];
2172
            }
2173
2174
            return 0;
2175
        }
2176
2177
        $url = api_get_path(WEB_CODE_PATH).'work/';
2178
        $unoconv = api_get_configuration_value('unoconv.binaries');
2179
        $loadingText = addslashes(get_lang('Loading'));
2180
        $uploadedText = addslashes(get_lang('Uploaded'));
2181
        $failsUploadText = addslashes(get_lang('UplNoFileUploaded'));
2182
        $failsUploadIcon = Display::return_icon(
2183
            'closed-circle.png',
2184
            '',
2185
            [],
2186
            ICON_SIZE_TINY
2187
        );
2188
        $saveIcon = Display::return_icon(
2189
            'save.png',
2190
            get_lang('Save'),
2191
            [],
2192
            ICON_SIZE_SMALL
2193
        );
2194
2195
        $correctionIcon = Display::return_icon(
2196
            'check-circle.png',
2197
            get_lang('Correction'),
2198
            null,
2199
            ICON_SIZE_SMALL
2200
        );
2201
2202
        $correctionIconSmall = Display::return_icon(
2203
            'check-circle.png',
2204
            get_lang('Correction'),
2205
            null,
2206
            ICON_SIZE_TINY
2207
        );
2208
2209
        $rateIcon = Display::return_icon(
2210
            'rate_work.png',
2211
            get_lang('CorrectAndRate'),
2212
            [],
2213
            ICON_SIZE_SMALL
2214
        );
2215
2216
        $blockEdition = api_get_configuration_value('block_student_publication_edition');
2217
        $blockScoreEdition = api_get_configuration_value('block_student_publication_score_edition');
2218
        $loading = Display::returnFontAwesomeIcon('spinner', null, true, 'fa-spin');
2219
        $cidReq = api_get_cidreq();
2220
2221
        $qualification_exists = false;
2222
        if (!empty($work_data['qualification']) &&
2223
            intval($work_data['qualification']) > 0
2224
        ) {
2225
            $qualification_exists = true;
2226
        }
2227
2228
        while ($work = Database::fetch_array($result, 'ASSOC')) {
2229
            $item_id = $work['id'];
2230
            $dbTitle = $work['title'];
2231
            // Get the author ID for that document from the item_property table
2232
            $is_author = false;
2233
            $can_read = false;
2234
            $owner_id = $work['user_id'];
2235
2236
            /* Because a bug found when saving items using the api_item_property_update()
2237
               the field $item_property_data['insert_user_id'] is not reliable. */
2238
            if (!$is_allowed_to_edit && $owner_id == api_get_user_id()) {
2239
                $is_author = true;
2240
            }
2241
2242
            if ($course_info['show_score'] == 0) {
2243
                $can_read = true;
2244
            }
2245
2246
            $qualification_string = '';
2247
            if ($qualification_exists) {
2248
                if ($work['qualification'] == '') {
2249
                    $qualification_string = Display::label('-');
2250
                } else {
2251
                    $qualification_string = formatWorkScore($work['qualification'], $work_data['qualification']);
2252
                }
2253
            }
2254
2255
            $work['qualification_score'] = $work['qualification'];
2256
            $add_string = '';
2257
            $time_expires = '';
2258
            if (!empty($work_assignment['expires_on'])) {
2259
                $time_expires = api_strtotime(
2260
                    $work_assignment['expires_on'],
2261
                    'UTC'
2262
                );
2263
            }
2264
2265
            if (!empty($work_assignment['expires_on']) &&
2266
                !empty($time_expires) && ($time_expires < api_strtotime($work['sent_date'], 'UTC'))) {
2267
                $add_string = Display::label(get_lang('Expired'), 'important').' - ';
2268
            }
2269
2270
            if (($can_read && $work['accepted'] == '1') ||
2271
                ($is_author && in_array($work['accepted'], ['1', '0'])) ||
2272
                ($is_allowed_to_edit || api_is_drh())
2273
            ) {
2274
                // Firstname, lastname, username
2275
                $work['fullname'] = Display::div(
2276
                    api_get_person_name($work['firstname'], $work['lastname']),
2277
                    ['class' => 'work-name']
2278
                );
2279
                // Title
2280
                $work['title_clean'] = $work['title'];
2281
                $work['title'] = Security::remove_XSS($work['title']);
2282
                if (strlen($work['title']) > 30) {
2283
                    $short_title = substr($work['title'], 0, 27).'...';
2284
                    $work['title'] = Display::span($short_title, ['class' => 'work-title', 'title' => $work['title']]);
2285
                } else {
2286
                    $work['title'] = Display::div($work['title'], ['class' => 'work-title']);
2287
                }
2288
2289
                // Type.
2290
                $work['type'] = DocumentManager::build_document_icon_tag('file', $work['url']);
2291
2292
                // File name.
2293
                $linkToDownload = '';
2294
                // If URL is present then there's a file to download keep BC.
2295
                if ($work['contains_file'] || !empty($work['url'])) {
2296
                    $linkToDownload = '<a href="'.$url.'download.php?id='.$item_id.'&'.$cidReq.'">'.$saveIcon.'</a> ';
2297
                }
2298
2299
                $feedback = '';
2300
                $count = getWorkCommentCount($item_id, $course_info);
2301
                if (!is_null($count) && !empty($count)) {
2302
                    if ($qualification_exists) {
2303
                        $feedback .= ' ';
2304
                    }
2305
                    $feedback .= Display::url(
2306
                        $count.' '.Display::returnFontAwesomeIcon('comments-o'),
2307
                        $url.'view.php?'.api_get_cidreq().'&id='.$item_id
2308
                    );
2309
                }
2310
2311
                $correction = '';
2312
                $hasCorrection = '';
2313
                if (!empty($work['url_correction'])) {
2314
                    $hasCorrection = Display::url(
2315
                        $correctionIcon,
2316
                        api_get_path(WEB_CODE_PATH).'work/download.php?id='.$item_id.'&'.$cidReq.'&correction=1'
2317
                    );
2318
                }
2319
2320
                if ($qualification_exists) {
2321
                    $work['qualification'] = $qualification_string.$feedback;
2322
                } else {
2323
                    $work['qualification'] = $qualification_string.$feedback.$hasCorrection;
2324
                }
2325
2326
                $work['qualification_only'] = $qualification_string;
2327
2328
                // Date.
2329
                $work_date = api_get_local_time($work['sent_date']);
2330
                $date = date_to_str_ago($work['sent_date']).' '.$work_date;
2331
                $work['formatted_date'] = $work_date.' '.$add_string;
2332
                $work['expiry_note'] = $add_string;
2333
                $work['sent_date_from_db'] = $work['sent_date'];
2334
                $work['sent_date'] = '<div class="work-date" title="'.$date.'">'.
2335
                    $add_string.' '.Display::dateToStringAgoAndLongDate($work['sent_date']).'</div>';
2336
                $work['status'] = $hasCorrection;
2337
                $work['has_correction'] = $hasCorrection;
2338
2339
                // Actions.
2340
                $action = '';
2341
                if (api_is_allowed_to_edit()) {
2342
                    if ($blockScoreEdition && !api_is_platform_admin() && !empty($work['qualification_score'])) {
2343
                        $rateLink = '';
2344
                    } else {
2345
                        $rateLink = '<a href="'.$url.'view.php?'.$cidReq.'&id='.$item_id.'" title="'.get_lang('View').'">'.
2346
                            $rateIcon.'</a> ';
2347
                    }
2348
                    $action .= $rateLink;
2349
2350
                    if ($unoconv && empty($work['contains_file'])) {
2351
                        $action .= '<a
2352
                            href="'.$url.'work_list_all.php?'.$cidReq.'&id='.$work_id.'&action=export_to_doc&item_id='.$item_id.'"
2353
                            title="'.get_lang('ExportToDoc').'" >'.
2354
                            Display::return_icon('export_doc.png', get_lang('ExportToDoc'), [], ICON_SIZE_SMALL).'</a> ';
2355
                    }
2356
2357
                    $alreadyUploaded = '';
2358
                    if (!empty($work['url_correction'])) {
2359
                        $alreadyUploaded = '<br />'.$work['title_correction'].' '.$correctionIconSmall;
2360
                    }
2361
2362
                    $correction = '
2363
                        <form
2364
                        id="file_upload_'.$item_id.'"
2365
                        class="work_correction_file_upload file_upload_small fileinput-button"
2366
                        action="'.api_get_path(WEB_AJAX_PATH).'work.ajax.php?'.$cidReq.'&a=upload_correction_file&item_id='.$item_id.'"
2367
                        method="POST"
2368
                        enctype="multipart/form-data"
2369
                        >
2370
                        <div id="progress_'.$item_id.'" class="text-center button-load">
2371
                            '.addslashes(get_lang('ClickOrDropOneFileHere')).'
2372
                            '.Display::return_icon('upload_file.png', get_lang('Correction'), [], ICON_SIZE_TINY).'
2373
                            '.$alreadyUploaded.'
2374
                        </div>
2375
                        <input id="file_'.$item_id.'" type="file" name="file" class="" multiple>
2376
                        </form>
2377
                    ';
2378
2379
                    $correction .= "<script>
2380
                    $(function() {
2381
                        $('.work_correction_file_upload').each(function () {
2382
                            $(this).fileupload({
2383
                                dropZone: $(this)
2384
                            });
2385
                        });
2386
2387
                        $('#file_upload_".$item_id."').fileupload({
2388
                            add: function (e, data) {
2389
                                $('#progress_$item_id').html();
2390
                                data.context = $('#progress_$item_id').html('$loadingText <br /> <em class=\"fa fa-spinner fa-pulse fa-fw\"></em>');
2391
                                data.submit();
2392
                                $(this).removeClass('hover');
2393
                            },
2394
                            dragover: function (e, data) {
2395
                                $(this).addClass('hover');
2396
                            },
2397
                            done: function (e, data) {
2398
                                if (data._response.result.name) {
2399
                                    $('#progress_$item_id').html('$uploadedText '+data._response.result.result+'<br />'+data._response.result.name);
2400
                                } else {
2401
                                    $('#progress_$item_id').html('$failsUploadText $failsUploadIcon');
2402
                                }
2403
                                $(this).removeClass('hover');
2404
                            }
2405
                        });
2406
                        $('#file_upload_".$item_id."').on('dragleave', function (e) {
2407
                            // dragleave callback implementation
2408
                            $(this).removeClass('hover');
2409
                        });
2410
                    });
2411
                    </script>";
2412
2413
                    if ($locked) {
2414
                        if ($qualification_exists) {
2415
                            $action .= Display::return_icon(
2416
                                'edit_na.png',
2417
                                get_lang('CorrectAndRate'),
2418
                                [],
2419
                                ICON_SIZE_SMALL
2420
                            );
2421
                        } else {
2422
                            $action .= Display::return_icon('edit_na.png', get_lang('Comment'), [], ICON_SIZE_SMALL);
2423
                        }
2424
                    } else {
2425
                        if ($blockEdition && !api_is_platform_admin()) {
2426
                            $editLink = '';
2427
                        } else {
2428
                            if ($qualification_exists) {
2429
                                $editLink = '<a href="'.$url.'edit.php?'.api_get_cidreq(
2430
                                    ).'&item_id='.$item_id.'&id='.$work['parent_id'].'" title="'.get_lang(
2431
                                        'Edit'
2432
                                    ).'"  >'.
2433
                                    Display::return_icon('edit.png', get_lang('Edit'), [], ICON_SIZE_SMALL).'</a>';
2434
                            } else {
2435
                                $editLink = '<a href="'.$url.'edit.php?'.api_get_cidreq(
2436
                                    ).'&item_id='.$item_id.'&id='.$work['parent_id'].'" title="'.get_lang(
2437
                                        'Modify'
2438
                                    ).'">'.
2439
                                    Display::return_icon('edit.png', get_lang('Edit'), [], ICON_SIZE_SMALL).'</a>';
2440
                            }
2441
                        }
2442
                        $action .= $editLink;
2443
                    }
2444
2445
                    if ($work['contains_file']) {
2446
                        if ($locked) {
2447
                            $action .= Display::return_icon(
2448
                                'move_na.png',
2449
                                get_lang('Move'),
2450
                                [],
2451
                                ICON_SIZE_SMALL
2452
                            );
2453
                        } else {
2454
                            $action .= '<a href="'.$url.'work.php?'.api_get_cidreq().'&action=move&item_id='.$item_id.'&id='.$work['parent_id'].'" title="'.get_lang('Move').'">'.
2455
                                Display::return_icon('move.png', get_lang('Move'), [], ICON_SIZE_SMALL).'</a>';
2456
                        }
2457
                    }
2458
2459
                    if ($work['accepted'] == '1') {
2460
                        $action .= '<a href="'.$url.'work_list_all.php?'.api_get_cidreq().'&id='.$work_id.'&action=make_invisible&item_id='.$item_id.'" title="'.get_lang('Invisible').'" >'.
2461
                            Display::return_icon('visible.png', get_lang('Invisible'), [], ICON_SIZE_SMALL).'</a>';
2462
                    } else {
2463
                        $action .= '<a href="'.$url.'work_list_all.php?'.api_get_cidreq().'&id='.$work_id.'&action=make_visible&item_id='.$item_id.'" title="'.get_lang('Visible').'" >'.
2464
                            Display::return_icon('invisible.png', get_lang('Visible'), [], ICON_SIZE_SMALL).'</a> ';
2465
                    }
2466
2467
                    if ($locked) {
2468
                        $action .= Display::return_icon('delete_na.png', get_lang('Delete'), '', ICON_SIZE_SMALL);
2469
                    } else {
2470
                        $action .= '<a href="'.$url.'work_list_all.php?'.api_get_cidreq().'&id='.$work_id.'&action=delete&item_id='.$item_id.'" onclick="javascript:if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES))."'".')) return false;" title="'.get_lang('Delete').'" >'.
2471
                            Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL).'</a>';
2472
                    }
2473
                } elseif ($is_author && (empty($work['qualificator_id']) || $work['qualificator_id'] == 0)) {
2474
                    $action .= '<a href="'.$url.'view.php?'.api_get_cidreq().'&id='.$item_id.'" title="'.get_lang('View').'">'.
2475
                        Display::return_icon('default.png', get_lang('View'), [], ICON_SIZE_SMALL).'</a>';
2476
2477
                    if (api_get_course_setting('student_delete_own_publication') == 1) {
2478
                        if (api_is_allowed_to_session_edit(false, true)) {
2479
                            $action .= '<a href="'.$url.'edit.php?'.api_get_cidreq().'&item_id='.$item_id.'&id='.$work['parent_id'].'" title="'.get_lang('Modify').'">'.
2480
                                Display::return_icon('edit.png', get_lang('Comment'), [], ICON_SIZE_SMALL).'</a>';
2481
                        }
2482
                        $action .= ' <a href="'.$url.'work_list.php?'.api_get_cidreq().'&action=delete&item_id='.$item_id.'&id='.$work['parent_id'].'" onclick="javascript:if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES))."'".')) return false;" title="'.get_lang('Delete').'"  >'.
2483
                            Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL).'</a>';
2484
                    }
2485
                } else {
2486
                    $action .= '<a href="'.$url.'view.php?'.api_get_cidreq().'&id='.$item_id.'" title="'.get_lang('View').'">'.
2487
                        Display::return_icon('default.png', get_lang('View'), [], ICON_SIZE_SMALL).'</a>';
2488
                }
2489
2490
                // Status.
2491
                if (empty($work['qualificator_id'])) {
2492
                    $qualificator_id = Display::label(get_lang('NotRevised'), 'warning');
2493
                } else {
2494
                    $qualificator_id = Display::label(get_lang('Revised'), 'success');
2495
                }
2496
                $work['qualificator_id'] = $qualificator_id.' '.$hasCorrection;
2497
                $work['actions'] = '<div class="work-action">'.$linkToDownload.$action.'</div>';
2498
                $work['correction'] = $correction;
2499
2500
                if (!empty($compilation) && $is_allowed_to_edit) {
2501
                    $compilationId = $compilation->getCompilatioId($item_id, $course_id);
2502
                    if ($compilationId) {
2503
                        $actionCompilatio = "<div id='id_avancement".$item_id."' class='compilation_block'>
2504
                            ".$loading.'&nbsp;'.get_lang('CompilatioConnectionWithServer').'</div>';
2505
                    } else {
2506
                        $workDirectory = api_get_path(SYS_COURSE_PATH).$course_info['directory'];
2507
                        if (!Compilatio::verifiFileType($dbTitle)) {
2508
                            $actionCompilatio = get_lang('FileFormatNotSupported');
2509
                        } elseif (filesize($workDirectory.'/'.$work['url']) > $compilation->getMaxFileSize()) {
2510
                            $sizeFile = round(filesize($workDirectory.'/'.$work['url']) / 1000000);
2511
                            $actionCompilatio = get_lang('UplFileTooBig').': '.format_file_size($sizeFile).'<br />';
2512
                        } else {
2513
                            $actionCompilatio = "<div id='id_avancement".$item_id."' class='compilation_block'>";
2514
                            $actionCompilatio .= Display::url(
2515
                                get_lang('CompilatioAnalysis'),
2516
                                'javascript:void(0)',
2517
                                [
2518
                                    'class' => 'getSingleCompilatio btn btn-primary btn-xs',
2519
                                    'onclick' => "getSingleCompilatio($item_id);",
2520
                                ]
2521
                            );
2522
                            $actionCompilatio .= get_lang('CompilatioWithCompilatio');
2523
                        }
2524
                    }
2525
                    $work['compilatio'] = $actionCompilatio;
2526
                }
2527
                $works[] = $work;
2528
            }
2529
        }
2530
2531
        return $works;
2532
    }
2533
}
2534
2535
function getAllWork(
2536
    $start,
2537
    $limit,
2538
    $column,
2539
    $direction,
2540
    $whereCondition = '',
2541
    $getCount = false,
2542
    $courseId = 0,
2543
    $status = 0
2544
) {
2545
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
2546
    $user_table = Database::get_main_table(TABLE_MAIN_USER);
2547
    $userId = api_get_user_id();
2548
    if (empty($userId)) {
2549
        return [];
2550
    }
2551
2552
    $courses = CourseManager::get_courses_list_by_user_id($userId, false, false, false);
2553
2554
    if (!empty($whereCondition)) {
2555
        $whereCondition = ' AND '.$whereCondition;
2556
    }
2557
    $whereCondition = Database::escape_string($whereCondition);
2558
2559
    if (!in_array($direction, ['asc', 'desc'])) {
2560
        $direction = 'desc';
2561
    }
2562
2563
    $column = !empty($column) ? Database::escape_string($column) : 'sent_date';
2564
    $start = (int) $start;
2565
    $limit = (int) $limit;
2566
    $courseQuery = [];
2567
    $courseList = [];
2568
    $withResults = 0;
2569
    foreach ($courses as $course) {
2570
        $courseIdItem = $course['real_id'];
2571
        if (!empty($courseId) && $courseIdItem != $courseId) {
2572
            continue;
2573
        }
2574
        $courseInfo = api_get_course_info_by_id($courseIdItem);
2575
        $session_id = isset($course['session_id']) ? $course['session_id'] : 0;
2576
        //$conditionSession = api_get_session_condition($session_id, true, false, 'w.session_id');
2577
        $conditionSession = '';
2578
        $parentCondition = '';
2579
        if ($withResults) {
2580
            $parentCondition = 'AND ww.parent_id is NOT NULL';
2581
        }
2582
        $courseQuery[] = " (work.c_id = $courseIdItem $conditionSession $parentCondition )";
2583
        $courseList[$courseIdItem] = $courseInfo;
2584
    }
2585
2586
    $courseQueryToString = implode(' OR ', $courseQuery);
2587
    $compilation = null;
2588
    /*if (api_get_configuration_value('allow_compilatio_tool')) {
2589
        $compilation = new Compilatio();
2590
    }*/
2591
2592
    $is_allowed_to_edit = api_is_allowed_to_edit() || api_is_coach();
2593
2594
    if ($getCount) {
2595
        if (empty($courseQuery)) {
2596
            return 0;
2597
        }
2598
        $select = 'SELECT DISTINCT count(u.id) as count ';
2599
    } else {
2600
        $select = 'SELECT DISTINCT
2601
                    u.id as user_id,
2602
                    work.id as id,
2603
                    title as title,
2604
                    description,
2605
                    url,
2606
                    sent_date,
2607
                    contains_file,
2608
                    has_properties,
2609
                    view_properties,
2610
                    qualification,
2611
                    weight,
2612
                    allow_text_assignment,
2613
                    u.firstname,
2614
                    u.lastname,
2615
                    u.username,
2616
                    parent_id,
2617
                    accepted,
2618
                    qualificator_id,
2619
                    url_correction,
2620
                    title_correction,
2621
                    work.c_id,
2622
                    work.session_id ';
2623
    }
2624
2625
    $statusCondition = '';
2626
    if (!empty($status)) {
2627
        switch ($status) {
2628
            case 2:
2629
                $statusCondition = ' AND (qualificator_id IS NULL OR qualificator_id = 0) ';
2630
                break;
2631
            case 3:
2632
                $statusCondition = ' AND (qualificator_id <> 0 AND qualificator_id IS NOT NULL) ';
2633
                break;
2634
        }
2635
    }
2636
2637
    $sql = " $select
2638
            FROM $work_table work
2639
            INNER JOIN $user_table u
2640
            ON (work.user_id = u.id)
2641
            WHERE
2642
                work.parent_id <> 0 AND
2643
                work.active IN (1, 0)
2644
                $whereCondition AND
2645
                ($courseQueryToString)
2646
                $statusCondition
2647
                AND u.status != ".INVITEE;
2648
2649
    $sql .= " ORDER BY $column $direction ";
2650
2651
    if (!empty($start) && !empty($limit)) {
2652
        $sql .= " LIMIT $start, $limit";
2653
    }
2654
2655
    $result = Database::query($sql);
2656
    $works = [];
2657
    if ($getCount) {
2658
        $work = Database::fetch_array($result, 'ASSOC');
2659
        if ($work) {
2660
            return (int) $work['count'];
2661
        }
2662
2663
        return 0;
2664
    }
2665
2666
    $url = api_get_path(WEB_CODE_PATH).'work/';
2667
    $unoconv = api_get_configuration_value('unoconv.binaries');
2668
    $loadingText = addslashes(get_lang('Loading'));
2669
    $uploadedText = addslashes(get_lang('Uploaded'));
2670
    $failsUploadText = addslashes(get_lang('UplNoFileUploaded'));
2671
    $failsUploadIcon = Display::return_icon(
2672
        'closed-circle.png',
2673
        '',
2674
        [],
2675
        ICON_SIZE_TINY
2676
    );
2677
    $saveIcon = Display::return_icon(
2678
        'save.png',
2679
        get_lang('Save'),
2680
        [],
2681
        ICON_SIZE_SMALL
2682
    );
2683
2684
    $correctionIcon = Display::return_icon(
2685
        'check-circle.png',
2686
        get_lang('Correction'),
2687
        null,
2688
        ICON_SIZE_SMALL
2689
    );
2690
2691
    $correctionIconSmall = Display::return_icon(
2692
        'check-circle.png',
2693
        get_lang('Correction'),
2694
        null,
2695
        ICON_SIZE_TINY
2696
    );
2697
2698
    $rateIcon = Display::return_icon(
2699
        'rate_work.png',
2700
        get_lang('CorrectAndRate'),
2701
        [],
2702
        ICON_SIZE_SMALL
2703
    );
2704
    $parentList = [];
2705
    $blockEdition = api_get_configuration_value('block_student_publication_edition');
2706
    $blockScoreEdition = api_get_configuration_value('block_student_publication_score_edition');
2707
    $loading = Display::returnFontAwesomeIcon('spinner', null, true, 'fa-spin');
2708
    $qualification_exists = true;
2709
    while ($work = Database::fetch_array($result, 'ASSOC')) {
2710
        $courseId = $work['c_id'];
2711
        $courseInfo = $courseList[$work['c_id']];
2712
        $sessionId = $work['session_id'];
2713
        $cidReq = 'cidReq='.$courseInfo['code'].'&id_session='.$sessionId;
2714
2715
        $item_id = $work_id = $work['id'];
2716
        $dbTitle = $work['title'];
2717
        // Get the author ID for that document from the item_property table
2718
        $is_author = false;
2719
        $can_read = false;
2720
        $owner_id = $work['user_id'];
2721
        $visibility = api_get_item_visibility($courseInfo, 'work', $work['id'], $sessionId);
2722
        if ($visibility != 1) {
2723
            continue;
2724
        }
2725
        /*$locked = api_resource_is_locked_by_gradebook(
2726
            $item_id,
2727
            LINK_STUDENTPUBLICATION,
2728
            $courseInfo['code']
2729
        );*/
2730
        $locked = false;
2731
2732
        /* Because a bug found when saving items using the api_item_property_update()
2733
           the field $item_property_data['insert_user_id'] is not reliable. */
2734
        if (!$is_allowed_to_edit && $owner_id == api_get_user_id()) {
2735
            $is_author = true;
2736
        }
2737
2738
        /*if ($course_info['show_score'] == 0) {
2739
            $can_read = true;
2740
        }*/
2741
2742
        $qualification_string = '';
2743
        if ($qualification_exists) {
2744
            if ($work['qualification'] == '') {
2745
                $qualification_string = Display::label('-');
2746
            } else {
2747
                $qualification_string = formatWorkScore($work['qualification'], $work['qualification']);
2748
            }
2749
        }
2750
2751
        $work['qualification_score'] = $work['qualification'];
2752
        $add_string = '';
2753
        $time_expires = '';
2754
        if (!empty($work_assignment['expires_on'])) {
2755
            $time_expires = api_strtotime(
2756
                $work_assignment['expires_on'],
2757
                'UTC'
2758
            );
2759
        }
2760
2761
        if (!empty($work_assignment['expires_on']) &&
2762
            !empty($time_expires) && ($time_expires < api_strtotime($work['sent_date'], 'UTC'))) {
2763
            $add_string = Display::label(get_lang('Expired'), 'important').' - ';
2764
        }
2765
2766
        if (($can_read && $work['accepted'] == '1') ||
2767
            ($is_author && in_array($work['accepted'], ['1', '0'])) ||
2768
            ($is_allowed_to_edit || api_is_drh())
2769
        ) {
2770
            // Firstname, lastname, username
2771
            $work['fullname'] = Display::div(
2772
                api_get_person_name($work['firstname'], $work['lastname']),
2773
                ['class' => 'work-name']
2774
            );
2775
            // Title
2776
            $work['title_clean'] = $work['title'];
2777
            $work['title'] = Security::remove_XSS($work['title']);
2778
            if (strlen($work['title']) > 30) {
2779
                $short_title = substr($work['title'], 0, 27).'...';
2780
                $work['title'] = Display::span($short_title, ['class' => 'work-title', 'title' => $work['title']]);
2781
            } else {
2782
                $work['title'] = Display::div($work['title'], ['class' => 'work-title']);
2783
            }
2784
2785
            // Type.
2786
            $work['type'] = DocumentManager::build_document_icon_tag('file', $work['url']);
2787
2788
            // File name.
2789
            $linkToDownload = '';
2790
            // If URL is present then there's a file to download keep BC.
2791
            if ($work['contains_file'] || !empty($work['url'])) {
2792
                $linkToDownload = '<a href="'.$url.'download.php?id='.$item_id.'&'.$cidReq.'">'.$saveIcon.'</a> ';
2793
            }
2794
2795
            $feedback = '';
2796
            $count = getWorkCommentCount($item_id, $courseInfo);
2797
            if (!is_null($count) && !empty($count)) {
2798
                if ($qualification_exists) {
2799
                    $feedback .= ' ';
2800
                }
2801
                $feedback .= Display::url(
2802
                    $count.' '.Display::returnFontAwesomeIcon('comments-o'),
2803
                    $url.'view.php?'.$cidReq.'&id='.$item_id
2804
                );
2805
            }
2806
2807
            $correction = '';
2808
            $hasCorrection = '';
2809
            if (!empty($work['url_correction'])) {
2810
                $hasCorrection = Display::url(
2811
                    $correctionIcon,
2812
                    api_get_path(WEB_CODE_PATH).'work/download.php?id='.$item_id.'&'.$cidReq.'&correction=1'
2813
                );
2814
            }
2815
2816
            if ($qualification_exists) {
2817
                $work['qualification'] = $qualification_string.$feedback;
2818
            } else {
2819
                $work['qualification'] = $qualification_string.$feedback.$hasCorrection;
2820
            }
2821
2822
            $work['qualification_only'] = $qualification_string;
2823
2824
            // Date.
2825
            $work_date = api_get_local_time($work['sent_date']);
2826
            $date = date_to_str_ago($work['sent_date']).' '.$work_date;
2827
            $work['formatted_date'] = $work_date.' '.$add_string;
2828
            $work['expiry_note'] = $add_string;
2829
            $work['sent_date_from_db'] = $work['sent_date'];
2830
            $work['sent_date'] = '<div class="work-date" title="'.$date.'">'.
2831
                $add_string.' '.Display::dateToStringAgoAndLongDate($work['sent_date']).'</div>';
2832
            $work['status'] = $hasCorrection;
2833
            $work['has_correction'] = $hasCorrection;
2834
            $work['course'] = $courseInfo['title'];
2835
2836
            if (isset($parentList[$work['parent_id']])) {
2837
                $parent = $parentList[$work['parent_id']];
2838
            } else {
2839
                $parent = get_work_data_by_id($work['parent_id'], $courseId);
2840
            }
2841
            $work['work_name'] = $parent['title'];
2842
2843
            // Actions.
2844
            $action = '';
2845
            if (api_is_allowed_to_edit()) {
2846
                if ($blockScoreEdition && !api_is_platform_admin() && !empty($work['qualification_score'])) {
2847
                    $rateLink = '';
2848
                } else {
2849
                    $rateLink = '<a href="'.$url.'view.php?'.$cidReq.'&id='.$item_id.'" title="'.get_lang('View').'">'.
2850
                        $rateIcon.'</a> ';
2851
                }
2852
                $action .= $rateLink;
2853
2854
                if ($unoconv && empty($work['contains_file'])) {
2855
                    $action .= '<a
2856
                        href="'.$url.'work_list_all.php?'.$cidReq.'&id='.$work_id.'&action=export_to_doc&item_id='.$item_id.'"
2857
                        title="'.get_lang('ExportToDoc').'" >'.
2858
                        Display::return_icon('export_doc.png', get_lang('ExportToDoc'), [], ICON_SIZE_SMALL).'</a> ';
2859
                }
2860
2861
                $alreadyUploaded = '';
2862
                if (!empty($work['url_correction'])) {
2863
                    $alreadyUploaded = '<br />'.$work['title_correction'].' '.$correctionIconSmall;
2864
                }
2865
2866
                $correction = '
2867
                    <form
2868
                    id="file_upload_'.$item_id.'"
2869
                    class="work_correction_file_upload file_upload_small fileinput-button"
2870
                    action="'.api_get_path(WEB_AJAX_PATH).'work.ajax.php?'.$cidReq.'&a=upload_correction_file&item_id='.$item_id.'"
2871
                    method="POST"
2872
                    enctype="multipart/form-data"
2873
                    >
2874
                    <div id="progress_'.$item_id.'" class="text-center button-load">
2875
                        '.addslashes(get_lang('ClickOrDropOneFileHere')).'
2876
                        '.Display::return_icon('upload_file.png', get_lang('Correction'), [], ICON_SIZE_TINY).'
2877
                        '.$alreadyUploaded.'
2878
                    </div>
2879
                    <input id="file_'.$item_id.'" type="file" name="file" class="" multiple>
2880
                    </form>
2881
                ';
2882
2883
                $correction .= "<script>
2884
                $(function() {
2885
                    $('.work_correction_file_upload').each(function () {
2886
                        $(this).fileupload({
2887
                            dropZone: $(this)
2888
                        });
2889
                    });
2890
2891
                    $('#file_upload_".$item_id."').fileupload({
2892
                        add: function (e, data) {
2893
                            $('#progress_$item_id').html();
2894
                            data.context = $('#progress_$item_id').html('$loadingText <br /> <em class=\"fa fa-spinner fa-pulse fa-fw\"></em>');
2895
                            data.submit();
2896
                            $(this).removeClass('hover');
2897
                        },
2898
                        dragover: function (e, data) {
2899
                            $(this).addClass('hover');
2900
                        },
2901
                        done: function (e, data) {
2902
                            if (data._response.result.name) {
2903
                                $('#progress_$item_id').html('$uploadedText '+data._response.result.result+'<br />'+data._response.result.name);
2904
                            } else {
2905
                                $('#progress_$item_id').html('$failsUploadText $failsUploadIcon');
2906
                            }
2907
                            $(this).removeClass('hover');
2908
                        }
2909
                    });
2910
                    $('#file_upload_".$item_id."').on('dragleave', function (e) {
2911
                        // dragleave callback implementation
2912
                        $(this).removeClass('hover');
2913
                    });
2914
                });
2915
                </script>";
2916
2917
                if ($locked) {
2918
                    if ($qualification_exists) {
2919
                        $action .= Display::return_icon(
2920
                            'edit_na.png',
2921
                            get_lang('CorrectAndRate'),
2922
                            [],
2923
                            ICON_SIZE_SMALL
2924
                        );
2925
                    } else {
2926
                        $action .= Display::return_icon('edit_na.png', get_lang('Comment'), [], ICON_SIZE_SMALL);
2927
                    }
2928
                } else {
2929
                    if ($blockEdition && !api_is_platform_admin()) {
2930
                        $editLink = '';
2931
                    } else {
2932
                        $editIcon = Display::return_icon('edit.png', get_lang('Edit'), [], ICON_SIZE_SMALL);
2933
                        if ($qualification_exists) {
2934
                            $editLink = '<a
2935
                                href="'.$url.'edit.php?'.$cidReq.'&item_id='.$item_id.'&id='.$work['parent_id'].'"
2936
                                title="'.get_lang('Edit').'"  >'.
2937
                                $editIcon.
2938
                            '</a>';
2939
                        } else {
2940
                            $editLink = '<a
2941
                                href="'.$url.'edit.php?'.$cidReq.'&item_id='.$item_id.'&id='.$work['parent_id'].'"
2942
                                title="'.get_lang('Modify').'">'.
2943
                                $editIcon.'</a>';
2944
                        }
2945
                    }
2946
                    $action .= $editLink;
2947
                }
2948
2949
                /*if ($work['contains_file']) {
2950
                    if ($locked) {
2951
                        $action .= Display::return_icon(
2952
                            'move_na.png',
2953
                            get_lang('Move'),
2954
                            [],
2955
                            ICON_SIZE_SMALL
2956
                        );
2957
                    } else {
2958
                        $action .= '<a href="'.$url.'work.php?'.$cidReq.'&action=move&item_id='.$item_id.'&id='.$work['parent_id'].'" title="'.get_lang('Move').'">'.
2959
                            Display::return_icon('move.png', get_lang('Move'), [], ICON_SIZE_SMALL).'</a>';
2960
                    }
2961
                }*/
2962
2963
                /*if ($work['accepted'] == '1') {
2964
                    $action .= '<a href="'.$url.'work_list_all.php?'.$cidReq.'&id='.$work_id.'&action=make_invisible&item_id='.$item_id.'" title="'.get_lang('Invisible').'" >'.
2965
                        Display::return_icon('visible.png', get_lang('Invisible'), [], ICON_SIZE_SMALL).'</a>';
2966
                } else {
2967
                    $action .= '<a href="'.$url.'work_list_all.php?'.$cidReq.'&id='.$work_id.'&action=make_visible&item_id='.$item_id.'" title="'.get_lang('Visible').'" >'.
2968
                        Display::return_icon('invisible.png', get_lang('Visible'), [], ICON_SIZE_SMALL).'</a> ';
2969
                }*/
2970
                /*if ($locked) {
2971
                    $action .= Display::return_icon('delete_na.png', get_lang('Delete'), '', ICON_SIZE_SMALL);
2972
                } else {
2973
                    $action .= '<a href="'.$url.'work_list_all.php?'.$cidReq.'&id='.$work_id.'&action=delete&item_id='.$item_id.'" onclick="javascript:if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES))."'".')) return false;" title="'.get_lang('Delete').'" >'.
2974
                        Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL).'</a>';
2975
                }*/
2976
            } elseif ($is_author && (empty($work['qualificator_id']) || $work['qualificator_id'] == 0)) {
2977
                $action .= '<a href="'.$url.'view.php?'.$cidReq.'&id='.$item_id.'" title="'.get_lang('View').'">'.
2978
                    Display::return_icon('default.png', get_lang('View'), [], ICON_SIZE_SMALL).'</a>';
2979
2980
                if (api_get_course_setting('student_delete_own_publication') == 1) {
2981
                    if (api_is_allowed_to_session_edit(false, true)) {
2982
                        $action .= '<a href="'.$url.'edit.php?'.$cidReq.'&item_id='.$item_id.'&id='.$work['parent_id'].'" title="'.get_lang('Modify').'">'.
2983
                            Display::return_icon('edit.png', get_lang('Comment'), [], ICON_SIZE_SMALL).'</a>';
2984
                    }
2985
                    $action .= ' <a href="'.$url.'work_list.php?'.$cidReq.'&action=delete&item_id='.$item_id.'&id='.$work['parent_id'].'" onclick="javascript:if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES))."'".')) return false;" title="'.get_lang('Delete').'"  >'.
2986
                        Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL).'</a>';
2987
                }
2988
            } else {
2989
                $action .= '<a href="'.$url.'view.php?'.$cidReq.'&id='.$item_id.'" title="'.get_lang('View').'">'.
2990
                    Display::return_icon('default.png', get_lang('View'), [], ICON_SIZE_SMALL).'</a>';
2991
            }
2992
2993
            // Status.
2994
            if (empty($work['qualificator_id'])) {
2995
                $qualificator_id = Display::label(get_lang('NotRevised'), 'warning');
2996
            } else {
2997
                $qualificator_id = Display::label(get_lang('Revised'), 'success');
2998
            }
2999
            $work['qualificator_id'] = $qualificator_id.' '.$hasCorrection;
3000
            $work['actions'] = '<div class="work-action">'.$linkToDownload.$action.'</div>';
3001
            $work['correction'] = $correction;
3002
3003
            if (!empty($compilation) && $is_allowed_to_edit) {
3004
                $compilationId = $compilation->getCompilatioId($item_id, $courseId);
3005
                if ($compilationId) {
3006
                    $actionCompilatio = "<div id='id_avancement".$item_id."' class='compilation_block'>
3007
                        ".$loading.'&nbsp;'.get_lang('CompilatioConnectionWithServer').'</div>';
3008
                } else {
3009
                    $workDirectory = api_get_path(SYS_COURSE_PATH).$courseInfo['directory'];
3010
                    if (!Compilatio::verifiFileType($dbTitle)) {
3011
                        $actionCompilatio = get_lang('FileFormatNotSupported');
3012
                    } elseif (filesize($workDirectory.'/'.$work['url']) > $compilation->getMaxFileSize()) {
3013
                        $sizeFile = round(filesize($workDirectory.'/'.$work['url']) / 1000000);
3014
                        $actionCompilatio = get_lang('UplFileTooBig').': '.format_file_size($sizeFile).'<br />';
3015
                    } else {
3016
                        $actionCompilatio = "<div id='id_avancement".$item_id."' class='compilation_block'>";
3017
                        $actionCompilatio .= Display::url(
3018
                            get_lang('CompilatioAnalysis'),
3019
                            'javascript:void(0)',
3020
                            [
3021
                                'class' => 'getSingleCompilatio btn btn-primary btn-xs',
3022
                                'onclick' => "getSingleCompilatio($item_id);",
3023
                            ]
3024
                        );
3025
                        $actionCompilatio .= get_lang('CompilatioWithCompilatio');
3026
                    }
3027
                }
3028
                $work['compilatio'] = $actionCompilatio;
3029
            }
3030
            $works[] = $work;
3031
        }
3032
    }
3033
3034
    return $works;
3035
3036
}
3037
3038
/**
3039
 * Send reminder to users who have not given the task.
3040
 *
3041
 * @param int
3042
 *
3043
 * @return array
3044
 *
3045
 * @author cvargas [email protected] cfasanando, [email protected]
3046
 */
3047
function send_reminder_users_without_publication($task_data)
3048
{
3049
    $_course = api_get_course_info();
3050
    $task_id = $task_data['id'];
3051
    $task_title = !empty($task_data['title']) ? $task_data['title'] : basename($task_data['url']);
3052
    $subject = '['.api_get_setting('siteName').'] ';
3053
3054
    // The body can be as long as you wish, and any combination of text and variables
3055
    $content = get_lang('ReminderToSubmitPendingTask')."\n".get_lang('CourseName').' : '.$_course['name']."\n";
3056
    $content .= get_lang('WorkName').' : '.$task_title."\n";
3057
    $list_users = get_list_users_without_publication($task_id);
3058
    $mails_sent_to = [];
3059
    foreach ($list_users as $user) {
3060
        $name_user = api_get_person_name($user[1], $user[0], null, PERSON_NAME_EMAIL_ADDRESS);
3061
        $dear_line = get_lang('Dear')." ".api_get_person_name($user[1], $user[0]).", \n\n";
3062
        $body = $dear_line.$content;
3063
        MessageManager::send_message($user[3], $subject, $body);
3064
        $mails_sent_to[] = $name_user;
3065
    }
3066
3067
    return $mails_sent_to;
3068
}
3069
3070
/**
3071
 * @param int $workId    The work ID
3072
 * @param int $courseId  The course ID
3073
 * @param int $sessionId Optional. The session ID
3074
 */
3075
function sendEmailToDrhOnHomeworkCreation($workId, $courseId, $sessionId = 0)
3076
{
3077
    $courseInfo = api_get_course_info_by_id($courseId);
3078
    $assignment = get_work_assignment_by_id($workId, $courseId);
3079
    $work = get_work_data_by_id($workId, $courseId, $sessionId);
3080
    $workInfo = array_merge($assignment, $work);
3081
3082
    if (empty($sessionId)) {
3083
        $students = CourseManager::get_student_list_from_course_code($courseInfo['code']);
3084
    } else {
3085
        $students = CourseManager::get_student_list_from_course_code($courseInfo['code'], true, $sessionId);
3086
    }
3087
3088
    $bodyView = new Template(null, false, false, false, false, false);
3089
3090
    foreach ($students as $student) {
3091
        $studentInfo = api_get_user_info($student['user_id']);
3092
        if (empty($studentInfo)) {
3093
            continue;
3094
        }
3095
3096
        $hrms = UserManager::getDrhListFromUser($student['id']);
3097
        foreach ($hrms as $hrm) {
3098
            $hrmName = api_get_person_name($hrm['firstname'], $hrm['lastname'], null, PERSON_NAME_EMAIL_ADDRESS);
3099
3100
            $bodyView->assign('hrm_name', $hrmName);
3101
            $bodyView->assign('student', $studentInfo);
3102
            $bodyView->assign('course', $courseInfo);
3103
            $bodyView->assign('course_link', api_get_course_url($courseInfo['code'], $sessionId));
3104
            $bodyView->assign('work', $workInfo);
3105
3106
            $bodyTemplate = $bodyView->get_template('mail/new_work_alert_hrm.tpl');
3107
3108
            MessageManager::send_message(
3109
                $hrm['id'],
3110
                sprintf(
3111
                    get_lang('StudentXHasBeenAssignedNewWorkInCourseY'),
3112
                    $student['firstname'],
3113
                    $courseInfo['title']
3114
                ),
3115
                $bodyView->fetch($bodyTemplate)
3116
            );
3117
        }
3118
    }
3119
}
3120
3121
/**
3122
 * Sends an email to the students of a course when a homework is created.
3123
 *
3124
 * @param int $workId
3125
 * @param int $courseId
3126
 * @param int $sessionId
3127
 *
3128
 * @author Guillaume Viguier <[email protected]>
3129
 * @author Julio Montoya <[email protected]> Adding session support - 2011
3130
 */
3131
function sendEmailToStudentsOnHomeworkCreation($workId, $courseId, $sessionId = 0)
3132
{
3133
    $courseInfo = api_get_course_info_by_id($courseId);
3134
    $courseCode = $courseInfo['code'];
3135
    // Get the students of the course
3136
    if (empty($sessionId)) {
3137
        $students = CourseManager::get_student_list_from_course_code($courseCode);
3138
    } else {
3139
        $students = CourseManager::get_student_list_from_course_code($courseCode, true, $sessionId);
3140
    }
3141
    $emailsubject = '['.api_get_setting('siteName').'] '.get_lang('HomeworkCreated');
3142
    $currentUser = api_get_user_info(api_get_user_id());
3143
    if (!empty($students)) {
3144
        foreach ($students as $student) {
3145
            $user_info = api_get_user_info($student['user_id']);
3146
            if (!empty($user_info)) {
3147
                $link = api_get_path(WEB_CODE_PATH).'work/work_list.php?'.api_get_cidreq().'&id='.$workId;
3148
                $emailbody = get_lang('Dear')." ".$user_info['complete_name'].",\n\n";
3149
                $emailbody .= get_lang('HomeworkHasBeenCreatedForTheCourse')." ".$courseCode.". "."\n\n".
3150
                    '<a href="'.$link.'">'.get_lang('PleaseCheckHomeworkPage').'</a>';
3151
                $emailbody .= "\n\n".$currentUser['complete_name'];
3152
3153
                $additionalParameters = [
3154
                    'smsType' => SmsPlugin::ASSIGNMENT_BEEN_CREATED_COURSE,
3155
                    'userId' => $student['user_id'],
3156
                    'courseTitle' => $courseCode,
3157
                    'link' => $link,
3158
                ];
3159
3160
                MessageManager::send_message_simple(
3161
                    $student['user_id'],
3162
                    $emailsubject,
3163
                    $emailbody,
3164
                    null,
3165
                    false,
3166
                    false,
3167
                    $additionalParameters,
3168
                    false
3169
                );
3170
            }
3171
        }
3172
    }
3173
}
3174
3175
/**
3176
 * @param string $url
3177
 *
3178
 * @return bool
3179
 */
3180
function is_work_exist_by_url($url)
3181
{
3182
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
3183
    $url = Database::escape_string($url);
3184
    $sql = "SELECT id FROM $table WHERE url='$url'";
3185
    $result = Database::query($sql);
3186
    if (Database::num_rows($result) > 0) {
3187
        $row = Database::fetch_row($result);
3188
        if (empty($row)) {
3189
            return false;
3190
        } else {
3191
            return true;
3192
        }
3193
    } else {
3194
        return false;
3195
    }
3196
}
3197
3198
/**
3199
 * Check if a user is the author of a work document.
3200
 *
3201
 * @param int $itemId
3202
 * @param int $userId
3203
 * @param int $courseId
3204
 * @param int $sessionId
3205
 *
3206
 * @return bool
3207
 */
3208
function user_is_author($itemId, $userId = null, $courseId = 0, $sessionId = 0)
3209
{
3210
    $userId = (int) $userId;
3211
3212
    if (empty($itemId)) {
3213
        return false;
3214
    }
3215
3216
    if (empty($userId)) {
3217
        $userId = api_get_user_id();
3218
    }
3219
3220
    $isAuthor = false;
3221
    $is_allowed_to_edit = api_is_allowed_to_edit();
3222
3223
    if ($is_allowed_to_edit) {
3224
        $isAuthor = true;
3225
    } else {
3226
        if (empty($courseId)) {
3227
            $courseId = api_get_course_int_id();
3228
        }
3229
        if (empty($sessionId)) {
3230
            $sessionId = api_get_session_id();
3231
        }
3232
3233
        $data = api_get_item_property_info($courseId, 'work', $itemId, $sessionId);
3234
        if ($data['insert_user_id'] == $userId) {
3235
            $isAuthor = true;
3236
        }
3237
3238
        $workData = get_work_data_by_id($itemId);
3239
        if ($workData['user_id'] == $userId) {
3240
            $isAuthor = true;
3241
        }
3242
    }
3243
3244
    if (!$isAuthor) {
3245
        return false;
3246
    }
3247
3248
    return $isAuthor;
3249
}
3250
3251
/**
3252
 * Get list of users who have not given the task.
3253
 *
3254
 * @param int
3255
 * @param int
3256
 *
3257
 * @return array
3258
 *
3259
 * @author cvargas
3260
 * @author Julio Montoya <[email protected]> Fixing query
3261
 */
3262
function get_list_users_without_publication($task_id, $studentId = 0)
3263
{
3264
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
3265
    $table_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
3266
    $table_user = Database::get_main_table(TABLE_MAIN_USER);
3267
    $session_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
3268
3269
    $users = getAllUserToWork($task_id, api_get_course_int_id());
3270
    $users = array_column($users, 'user_id');
3271
3272
    // Condition for the session
3273
    $session_id = api_get_session_id();
3274
    $course_id = api_get_course_int_id();
3275
    $task_id = (int) $task_id;
3276
    $sessionCondition = api_get_session_condition($session_id);
3277
3278
    if (0 == $session_id) {
3279
        $sql = "SELECT user_id as id FROM $work_table
3280
                WHERE
3281
                    c_id = $course_id AND
3282
                    parent_id = '$task_id' AND
3283
                    active IN (0, 1)";
3284
    } else {
3285
        $sql = "SELECT user_id as id FROM $work_table
3286
                WHERE
3287
                    c_id = $course_id AND
3288
                    parent_id = '$task_id' $sessionCondition AND
3289
                    active IN (0, 1)";
3290
    }
3291
3292
    $result = Database::query($sql);
3293
    $users_with_tasks = [];
3294
    while ($row = Database::fetch_array($result)) {
3295
        $users_with_tasks[] = $row['id'];
3296
    }
3297
3298
    if (0 == $session_id) {
3299
        $sql_users = "SELECT cu.user_id, u.lastname, u.firstname, u.email
3300
                      FROM $table_course_user AS cu, $table_user AS u
3301
                      WHERE u.status != 1 and cu.c_id='".$course_id."' AND u.user_id = cu.user_id";
3302
    } else {
3303
        $sql_users = "SELECT cu.user_id, u.lastname, u.firstname, u.email
3304
                      FROM $session_course_rel_user AS cu, $table_user AS u
3305
                      WHERE
3306
                        u.status != 1 AND
3307
                        cu.c_id='".$course_id."' AND
3308
                        u.user_id = cu.user_id AND
3309
                        cu.session_id = '".$session_id."'";
3310
    }
3311
3312
    if (!empty($studentId)) {
3313
        $sql_users .= ' AND u.user_id = '.(int) $studentId;
3314
    }
3315
3316
    $group_id = api_get_group_id();
3317
    $new_group_user_list = [];
3318
3319
    if ($group_id) {
3320
        $groupInfo = GroupManager::get_group_properties($group_id);
3321
        $group_user_list = GroupManager::get_subscribed_users($groupInfo);
3322
        if (!empty($group_user_list)) {
3323
            foreach ($group_user_list as $group_user) {
3324
                $new_group_user_list[] = $group_user['user_id'];
3325
            }
3326
        }
3327
    }
3328
3329
    $result_users = Database::query($sql_users);
3330
    $users_without_tasks = [];
3331
    while ($rowUsers = Database::fetch_array($result_users)) {
3332
        $userId = $rowUsers['user_id'];
3333
        if (in_array($userId, $users_with_tasks)) {
3334
            continue;
3335
        }
3336
3337
        if ($group_id && !in_array($userId, $new_group_user_list)) {
3338
            continue;
3339
        }
3340
3341
        if (!empty($users)) {
3342
            if (!in_array($userId, $users)) {
3343
                continue;
3344
            }
3345
        }
3346
3347
        $row_users = [];
3348
        $row_users[0] = $rowUsers['lastname'];
3349
        $row_users[1] = $rowUsers['firstname'];
3350
        $row_users[2] = Display::encrypted_mailto_link($rowUsers['email']);
3351
        $row_users[3] = $userId;
3352
        $users_without_tasks[] = $row_users;
3353
    }
3354
3355
    return $users_without_tasks;
3356
}
3357
3358
/**
3359
 * Display list of users who have not given the task.
3360
 *
3361
 * @param int task id
3362
 * @param int $studentId
3363
 *
3364
 * @author cvargas [email protected] cfasanando, [email protected]
3365
 * @author Julio Montoya <[email protected]> Fixes
3366
 */
3367
function display_list_users_without_publication($task_id, $studentId = null)
3368
{
3369
    $origin = api_get_origin();
3370
    $table_header[] = [get_lang('LastName'), true];
3371
    $table_header[] = [get_lang('FirstName'), true];
3372
    $table_header[] = [get_lang('Email'), true];
3373
3374
    $data = get_list_users_without_publication($task_id);
3375
3376
    $sorting_options = [];
3377
    $sorting_options['column'] = 1;
3378
    $paging_options = [];
3379
    $my_params = [];
3380
3381
    if (isset($_GET['edit_dir'])) {
3382
        $my_params['edit_dir'] = Security::remove_XSS($_GET['edit_dir']);
3383
    }
3384
    if (isset($_GET['list'])) {
3385
        $my_params['list'] = Security::remove_XSS($_GET['list']);
3386
    }
3387
    $my_params['origin'] = $origin;
3388
    $my_params['id'] = (int) ($_GET['id']);
3389
3390
    //$column_show
3391
    $column_show[] = 1;
3392
    $column_show[] = 1;
3393
    $column_show[] = 1;
3394
    Display::display_sortable_config_table(
3395
        'work',
3396
        $table_header,
3397
        $data,
3398
        $sorting_options,
3399
        $paging_options,
3400
        $my_params,
3401
        $column_show
3402
    );
3403
}
3404
3405
/**
3406
 * @param int $documentId
3407
 * @param int $workId
3408
 * @param int $courseId
3409
 */
3410
function addDocumentToWork($documentId, $workId, $courseId)
3411
{
3412
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_DOCUMENT);
3413
    $params = [
3414
        'document_id' => $documentId,
3415
        'work_id' => $workId,
3416
        'c_id' => $courseId,
3417
    ];
3418
    Database::insert($table, $params);
3419
}
3420
3421
/**
3422
 * @param int $documentId
3423
 * @param int $workId
3424
 * @param int $courseId
3425
 *
3426
 * @return array
3427
 */
3428
function getDocumentToWork($documentId, $workId, $courseId)
3429
{
3430
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_DOCUMENT);
3431
    $params = [
3432
        'document_id = ? and work_id = ? and c_id = ?' => [$documentId, $workId, $courseId],
3433
    ];
3434
3435
    return Database::select('*', $table, ['where' => $params]);
3436
}
3437
3438
/**
3439
 * @param int $documentId
3440
 * @param int $workId
3441
 * @param int $courseId
3442
 * @param int $sessionId
3443
 * @param int $userId
3444
 * @param int $active
3445
 *
3446
 * @return array
3447
 */
3448
function getDocumentToWorkPerUser($documentId, $workId, $courseId, $sessionId, $userId, $active = 1)
3449
{
3450
    $workRel = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_DOCUMENT);
3451
    $work = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
3452
3453
    $documentId = (int) $documentId;
3454
    $workId = (int) $workId;
3455
    $courseId = (int) $courseId;
3456
    $userId = (int) $userId;
3457
    $sessionId = (int) $sessionId;
3458
    $active = (int) $active;
3459
    $sessionCondition = api_get_session_condition($sessionId);
3460
3461
    $sql = "SELECT w.* FROM $work w
3462
            INNER JOIN $workRel rel
3463
            ON (w.parent_id = rel.work_id)
3464
            WHERE
3465
                w.document_id = $documentId AND
3466
                w.parent_id = $workId AND
3467
                w.c_id = $courseId
3468
                $sessionCondition AND
3469
                user_id = $userId AND
3470
                active = $active
3471
            ";
3472
3473
    $result = Database::query($sql);
3474
    $workInfo = [];
3475
    if (Database::num_rows($result)) {
3476
        $workInfo = Database::fetch_array($result, 'ASSOC');
3477
    }
3478
3479
    return $workInfo;
3480
}
3481
3482
/**
3483
 * @param int $workId
3484
 * @param int $courseId
3485
 *
3486
 * @return array
3487
 */
3488
function getAllDocumentToWork($workId, $courseId)
3489
{
3490
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_DOCUMENT);
3491
    $params = [
3492
        'work_id = ? and c_id = ?' => [$workId, $courseId],
3493
    ];
3494
3495
    return Database::select('*', $table, ['where' => $params]);
3496
}
3497
3498
/**
3499
 * @param int $documentId
3500
 * @param int $workId
3501
 * @param int $courseId
3502
 */
3503
function deleteDocumentToWork($documentId, $workId, $courseId)
3504
{
3505
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_DOCUMENT);
3506
    $params = [
3507
        'document_id = ? and work_id = ? and c_id = ?' => [$documentId, $workId, $courseId],
3508
    ];
3509
    Database::delete($table, $params);
3510
}
3511
3512
/**
3513
 * @param int $userId
3514
 * @param int $workId
3515
 * @param int $courseId
3516
 */
3517
function addUserToWork($userId, $workId, $courseId)
3518
{
3519
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_USER);
3520
    $params = [
3521
        'user_id' => $userId,
3522
        'work_id' => $workId,
3523
        'c_id' => $courseId,
3524
    ];
3525
    Database::insert($table, $params);
3526
}
3527
3528
/**
3529
 * @param int $userId
3530
 * @param int $workId
3531
 * @param int $courseId
3532
 *
3533
 * @return array
3534
 */
3535
function getUserToWork($userId, $workId, $courseId)
3536
{
3537
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_USER);
3538
    $params = [
3539
        'user_id = ? and work_id = ? and c_id = ?' => [$userId, $workId, $courseId],
3540
    ];
3541
3542
    return Database::select('*', $table, ['where' => $params]);
3543
}
3544
3545
/**
3546
 * @param int  $workId
3547
 * @param int  $courseId
3548
 * @param bool $getCount
3549
 *
3550
 * @return array|int
3551
 */
3552
function getAllUserToWork($workId, $courseId, $getCount = false)
3553
{
3554
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_USER);
3555
    $params = [
3556
        'work_id = ? and c_id = ?' => [$workId, $courseId],
3557
    ];
3558
    if ($getCount) {
3559
        $count = 0;
3560
        $result = Database::select(
3561
            'count(user_id) as count',
3562
            $table,
3563
            ['where' => $params],
3564
            'simple'
3565
        );
3566
        if (!empty($result)) {
3567
            $count = (int) ($result['count']);
3568
        }
3569
3570
        return $count;
3571
    } else {
3572
        return Database::select('*', $table, ['where' => $params]);
3573
    }
3574
}
3575
3576
/**
3577
 * @param int $userId
3578
 * @param int $workId
3579
 * @param int $courseId
3580
 */
3581
function deleteUserToWork($userId, $workId, $courseId)
3582
{
3583
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_USER);
3584
    $params = [
3585
        'user_id = ? and work_id = ? and c_id = ?' => [$userId, $workId, $courseId],
3586
    ];
3587
    Database::delete($table, $params);
3588
}
3589
3590
/**
3591
 * @param int $userId
3592
 * @param int $workId
3593
 * @param int $courseId
3594
 *
3595
 * @return bool
3596
 */
3597
function userIsSubscribedToWork($userId, $workId, $courseId)
3598
{
3599
    $subscribedUsers = getAllUserToWork($workId, $courseId);
3600
3601
    if (empty($subscribedUsers)) {
3602
        return true;
3603
    } else {
3604
        $subscribedUsersList = [];
3605
        foreach ($subscribedUsers as $item) {
3606
            $subscribedUsersList[] = $item['user_id'];
3607
        }
3608
        if (in_array($userId, $subscribedUsersList)) {
3609
            return true;
3610
        }
3611
    }
3612
3613
    return false;
3614
}
3615
3616
/**
3617
 * Get the list of students that have to submit their work.
3618
 *
3619
 * @param int  $workId    The internal ID of the assignment
3620
 * @param int  $courseId  The course ID
3621
 * @param int  $groupId   The group ID, if any
3622
 * @param int  $sessionId The session ID, if any
3623
 * @param bool $getCount  Whether we want just the amount or the full result
3624
 *
3625
 * @return array|int An integer (if we just asked for the count) or an array of users
3626
 */
3627
function getStudentSubscribedToWork(
3628
    $workId,
3629
    $courseId,
3630
    $groupId = null,
3631
    $sessionId = null,
3632
    $getCount = false
3633
) {
3634
    $usersInWork = null;
3635
    $usersInCourse = null;
3636
3637
    if (empty($groupId)) {
3638
        $courseInfo = api_get_course_info_by_id($courseId);
3639
        $status = STUDENT;
3640
        if (!empty($sessionId)) {
3641
            $status = 0;
3642
        }
3643
        $usersInCourse = CourseManager::get_user_list_from_course_code(
3644
            $courseInfo['code'],
3645
            $sessionId,
3646
            null,
3647
            null,
3648
            $status,
3649
            $getCount
3650
        );
3651
    } else {
3652
        $usersInCourse = GroupManager::get_users(
3653
            $groupId,
3654
            false,
3655
            null,
3656
            null,
3657
            $getCount,
3658
            $courseId
3659
        );
3660
    }
3661
3662
    $usersInWork = getAllUserToWork($workId, $courseId, $getCount);
3663
3664
    if (empty($usersInWork)) {
3665
        return $usersInCourse;
3666
    } else {
3667
        return $usersInWork;
3668
    }
3669
}
3670
3671
/**
3672
 * @param int  $userId
3673
 * @param int  $workId
3674
 * @param int  $courseId
3675
 * @param bool $forceAccessForCourseAdmins
3676
 *
3677
 * @return bool
3678
 */
3679
function allowOnlySubscribedUser($userId, $workId, $courseId, $forceAccessForCourseAdmins = false)
3680
{
3681
    if (api_is_platform_admin() || api_is_allowed_to_edit()) {
3682
        return true;
3683
    }
3684
3685
    if ($forceAccessForCourseAdmins) {
3686
        if (api_is_course_admin() || api_is_coach()) {
3687
            return true;
3688
        }
3689
    }
3690
3691
    return userIsSubscribedToWork($userId, $workId, $courseId);
3692
}
3693
3694
/**
3695
 * @param int   $workId
3696
 * @param array $courseInfo
3697
 * @param int   $documentId
3698
 *
3699
 * @return array
3700
 */
3701
function getDocumentTemplateFromWork($workId, $courseInfo, $documentId)
3702
{
3703
    $documents = getAllDocumentToWork($workId, $courseInfo['real_id']);
3704
    if (!empty($documents)) {
3705
        foreach ($documents as $doc) {
3706
            if ($documentId != $doc['document_id']) {
3707
                continue;
3708
            }
3709
            $docData = DocumentManager::get_document_data_by_id($doc['document_id'], $courseInfo['code']);
3710
            $fileInfo = pathinfo($docData['path']);
3711
            if ('html' == $fileInfo['extension']) {
3712
                if (file_exists($docData['absolute_path']) && is_file($docData['absolute_path'])) {
3713
                    $docData['file_content'] = file_get_contents($docData['absolute_path']);
3714
3715
                    return $docData;
3716
                }
3717
            }
3718
        }
3719
    }
3720
3721
    return [];
3722
}
3723
3724
/**
3725
 * @param int   $workId
3726
 * @param array $courseInfo
3727
 *
3728
 * @return string
3729
 */
3730
function getAllDocumentsFromWorkToString($workId, $courseInfo)
3731
{
3732
    $documents = getAllDocumentToWork($workId, $courseInfo['real_id']);
3733
    $content = null;
3734
    if (!empty($documents)) {
3735
        $content .= '<ul class="nav nav-list well">';
3736
        $content .= '<li class="nav-header">'.get_lang('Documents').'</li>';
3737
        foreach ($documents as $doc) {
3738
            $docData = DocumentManager::get_document_data_by_id($doc['document_id'], $courseInfo['code']);
3739
            if ($docData) {
3740
                $content .= '<li><a class="link_to_download" target="_blank" href="'.$docData['url'].'">'.$docData['title'].'</a></li>';
3741
            }
3742
        }
3743
        $content .= '</ul><br />';
3744
    }
3745
3746
    return $content;
3747
}
3748
3749
/**
3750
 * Returns fck editor toolbar.
3751
 *
3752
 * @return array
3753
 */
3754
function getWorkDescriptionToolbar()
3755
{
3756
    return [
3757
        'ToolbarStartExpanded' => 'true',
3758
        'ToolbarSet' => 'Work',
3759
        'Width' => '100%',
3760
        'Height' => '400',
3761
    ];
3762
}
3763
3764
/**
3765
 * @param array $work
3766
 *
3767
 * @return array
3768
 */
3769
function getWorkComments($work)
3770
{
3771
    $commentTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT_COMMENT);
3772
    $userTable = Database::get_main_table(TABLE_MAIN_USER);
3773
3774
    $courseId = (int) $work['c_id'];
3775
    $workId = (int) $work['id'];
3776
3777
    if (empty($courseId) || empty($workId)) {
3778
        return [];
3779
    }
3780
3781
    $sql = "SELECT
3782
                c.id,
3783
                c.user_id
3784
            FROM $commentTable c
3785
            INNER JOIN $userTable u
3786
            ON (u.id = c.user_id)
3787
            WHERE c_id = $courseId AND work_id = $workId
3788
            ORDER BY sent_at
3789
            ";
3790
    $result = Database::query($sql);
3791
    $comments = Database::store_result($result, 'ASSOC');
3792
    if (!empty($comments)) {
3793
        foreach ($comments as &$comment) {
3794
            $userInfo = api_get_user_info($comment['user_id']);
3795
            $comment['picture'] = $userInfo['avatar'];
3796
            $comment['complete_name'] = $userInfo['complete_name_with_username'];
3797
            $commentInfo = getWorkComment($comment['id']);
3798
            if (!empty($commentInfo)) {
3799
                $comment = array_merge($comment, $commentInfo);
3800
            }
3801
        }
3802
    }
3803
3804
    return $comments;
3805
}
3806
3807
/**
3808
 * Get total score from a work list.
3809
 *
3810
 * @param $workList
3811
 *
3812
 * @return int|null
3813
 */
3814
function getTotalWorkScore($workList)
3815
{
3816
    $count = 0;
3817
    foreach ($workList as $data) {
3818
        $count += $data['qualification_score'];
3819
    }
3820
3821
    return $count;
3822
}
3823
3824
/**
3825
 * Get comment count from a work list (docs sent by students).
3826
 *
3827
 * @param array $workList
3828
 * @param array $courseInfo
3829
 *
3830
 * @return int|null
3831
 */
3832
function getTotalWorkComment($workList, $courseInfo = [])
3833
{
3834
    if (empty($courseInfo)) {
3835
        $courseInfo = api_get_course_info();
3836
    }
3837
3838
    $count = 0;
3839
    foreach ($workList as $data) {
3840
        $count += getWorkCommentCount($data['id'], $courseInfo);
3841
    }
3842
3843
    return $count;
3844
}
3845
3846
/**
3847
 * Get comment count for a specific work sent by a student.
3848
 *
3849
 * @param int   $id
3850
 * @param array $courseInfo
3851
 *
3852
 * @return int
3853
 */
3854
function getWorkCommentCount($id, $courseInfo = [])
3855
{
3856
    if (empty($courseInfo)) {
3857
        $courseInfo = api_get_course_info();
3858
    }
3859
3860
    $commentTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT_COMMENT);
3861
    $id = (int) $id;
3862
3863
    $sql = "SELECT count(*) as count
3864
            FROM $commentTable
3865
            WHERE work_id = $id AND c_id = ".$courseInfo['real_id'];
3866
3867
    $result = Database::query($sql);
3868
    if (Database::num_rows($result)) {
3869
        $comment = Database::fetch_array($result);
3870
3871
        return $comment['count'];
3872
    }
3873
3874
    return 0;
3875
}
3876
3877
/**
3878
 * Get comment count for a specific parent.
3879
 *
3880
 * @param int   $parentId
3881
 * @param array $courseInfo
3882
 * @param int   $sessionId
3883
 *
3884
 * @return int
3885
 */
3886
function getWorkCommentCountFromParent(
3887
    $parentId,
3888
    $courseInfo = [],
3889
    $sessionId = 0
3890
) {
3891
    if (empty($courseInfo)) {
3892
        $courseInfo = api_get_course_info();
3893
    }
3894
3895
    if (empty($sessionId)) {
3896
        $sessionId = api_get_session_id();
3897
    } else {
3898
        $sessionId = (int) $sessionId;
3899
    }
3900
3901
    $work = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
3902
    $commentTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT_COMMENT);
3903
    $parentId = (int) $parentId;
3904
    $sessionCondition = api_get_session_condition($sessionId, false, false, 'w.session_id');
3905
3906
    $sql = "SELECT count(*) as count
3907
            FROM $commentTable c INNER JOIN $work w
3908
            ON c.c_id = w.c_id AND w.id = c.work_id
3909
            WHERE
3910
                $sessionCondition AND
3911
                parent_id = $parentId AND
3912
                w.c_id = ".$courseInfo['real_id'];
3913
3914
    $result = Database::query($sql);
3915
    if (Database::num_rows($result)) {
3916
        $comment = Database::fetch_array($result);
3917
3918
        return $comment['count'];
3919
    }
3920
3921
    return 0;
3922
}
3923
3924
/**
3925
 * Get last work information from parent.
3926
 *
3927
 * @param int   $parentId
3928
 * @param array $courseInfo
3929
 * @param int   $sessionId
3930
 *
3931
 * @return int
3932
 */
3933
function getLastWorkStudentFromParent(
3934
    $parentId,
3935
    $courseInfo = [],
3936
    $sessionId = 0
3937
) {
3938
    if (empty($courseInfo)) {
3939
        $courseInfo = api_get_course_info();
3940
    }
3941
3942
    if (empty($sessionId)) {
3943
        $sessionId = api_get_session_id();
3944
    } else {
3945
        $sessionId = (int) $sessionId;
3946
    }
3947
3948
    $work = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
3949
    $sessionCondition = api_get_session_condition($sessionId, false);
3950
    $commentTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT_COMMENT);
3951
    $parentId = (int) $parentId;
3952
3953
    $sql = "SELECT w.*
3954
            FROM $commentTable c INNER JOIN $work w
3955
            ON c.c_id = w.c_id AND w.id = c.work_id
3956
            WHERE
3957
                $sessionCondition AND
3958
                parent_id = $parentId AND
3959
                w.c_id = ".$courseInfo['real_id'].'
3960
            ORDER BY w.sent_date
3961
            LIMIT 1
3962
            ';
3963
3964
    $result = Database::query($sql);
3965
    if (Database::num_rows($result)) {
3966
        return Database::fetch_array($result, 'ASSOC');
3967
    }
3968
3969
    return [];
3970
}
3971
3972
/**
3973
 * Get last work information from parent.
3974
 *
3975
 * @param int   $userId
3976
 * @param array $parentInfo
3977
 * @param array $courseInfo
3978
 * @param int   $sessionId
3979
 *
3980
 * @return int
3981
 */
3982
function getLastWorkStudentFromParentByUser(
3983
    $userId,
3984
    $parentInfo,
3985
    $courseInfo = [],
3986
    $sessionId = 0
3987
) {
3988
    if (empty($courseInfo)) {
3989
        $courseInfo = api_get_course_info();
3990
    }
3991
3992
    if (empty($sessionId)) {
3993
        $sessionId = api_get_session_id();
3994
    } else {
3995
        $sessionId = (int) $sessionId;
3996
    }
3997
3998
    $userId = (int) $userId;
3999
    $work = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
4000
    if (empty($parentInfo)) {
4001
        return false;
4002
    }
4003
    $parentId = $parentInfo['id'];
4004
4005
    $sessionCondition = api_get_session_condition($sessionId);
4006
4007
    $sql = "SELECT *
4008
            FROM $work
4009
            WHERE
4010
                user_id = $userId
4011
                $sessionCondition AND
4012
                parent_id = $parentId AND
4013
                c_id = ".$courseInfo['real_id']."
4014
            ORDER BY sent_date DESC
4015
            LIMIT 1
4016
            ";
4017
    $result = Database::query($sql);
4018
    if (Database::num_rows($result)) {
4019
        $work = Database::fetch_array($result, 'ASSOC');
4020
        $work['qualification_rounded'] = formatWorkScore($work['qualification'], $parentInfo['qualification']);
4021
4022
        return $work;
4023
    }
4024
4025
    return [];
4026
}
4027
4028
/**
4029
 * @param float $score
4030
 * @param int   $weight
4031
 *
4032
 * @return string
4033
 */
4034
function formatWorkScore($score, $weight)
4035
{
4036
    $label = 'info';
4037
    $weight = (int) $weight;
4038
    $relativeScore = 0;
4039
    if (!empty($weight)) {
4040
        $relativeScore = $score / $weight;
4041
    }
4042
4043
    if ($relativeScore < 0.5) {
4044
        $label = 'important';
4045
    } elseif ($relativeScore < 0.75) {
4046
        $label = 'warning';
4047
    }
4048
4049
    $scoreBasedInModel = ExerciseLib::convertScoreToModel($relativeScore * 100);
4050
    if (empty($scoreBasedInModel)) {
4051
        $finalScore = api_number_format($score, 1).' / '.$weight;
4052
4053
        return Display::label(
4054
            $finalScore,
4055
            $label
4056
        );
4057
    } else {
4058
        return $scoreBasedInModel;
4059
    }
4060
}
4061
4062
/**
4063
 * @param int   $id         comment id
4064
 * @param array $courseInfo
4065
 *
4066
 * @return string
4067
 */
4068
function getWorkComment($id, $courseInfo = [])
4069
{
4070
    if (empty($courseInfo)) {
4071
        $courseInfo = api_get_course_info();
4072
    }
4073
4074
    if (empty($courseInfo['real_id'])) {
4075
        return [];
4076
    }
4077
4078
    $commentTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT_COMMENT);
4079
    $id = intval($id);
4080
4081
    $sql = "SELECT * FROM $commentTable
4082
            WHERE id = $id AND c_id = ".$courseInfo['real_id'];
4083
    $result = Database::query($sql);
4084
    $comment = [];
4085
    if (Database::num_rows($result)) {
4086
        $comment = Database::fetch_array($result, 'ASSOC');
4087
        $filePath = null;
4088
        $fileUrl = null;
4089
        $deleteUrl = null;
4090
        $fileName = null;
4091
        if (!empty($comment['file'])) {
4092
            $work = get_work_data_by_id($comment['work_id']);
4093
            $workParent = get_work_data_by_id($work['parent_id']);
4094
            $filePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/work/'.$workParent['url'].'/'.$comment['file'];
4095
            $fileUrl = api_get_path(WEB_CODE_PATH).'work/download_comment_file.php?comment_id='.$id.'&'.api_get_cidreq();
4096
            $deleteUrl = api_get_path(WEB_CODE_PATH).'work/view.php?'.api_get_cidreq().'&id='.$comment['work_id'].'&action=delete_attachment&comment_id='.$id;
4097
            $fileParts = explode('_', $comment['file']);
4098
            $fileName = str_replace($fileParts[0].'_'.$fileParts[1].'_', '', $comment['file']);
4099
        }
4100
        $comment['delete_file_url'] = $deleteUrl;
4101
        $comment['file_path'] = $filePath;
4102
        $comment['file_url'] = $fileUrl;
4103
        $comment['file_name_to_show'] = $fileName;
4104
        $comment['sent_at_with_label'] = Display::dateToStringAgoAndLongDate($comment['sent_at']);
4105
    }
4106
4107
    return $comment;
4108
}
4109
4110
/**
4111
 * @param int   $id
4112
 * @param array $courseInfo
4113
 */
4114
function deleteCommentFile($id, $courseInfo = [])
4115
{
4116
    $workComment = getWorkComment($id, $courseInfo);
4117
    if (isset($workComment['file']) && !empty($workComment['file'])) {
4118
        if (file_exists($workComment['file_path'])) {
4119
            $result = my_delete($workComment['file_path']);
4120
            if ($result) {
4121
                $commentTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT_COMMENT);
4122
                $params = ['file' => ''];
4123
                Database::update(
4124
                    $commentTable,
4125
                    $params,
4126
                    ['id = ? AND c_id = ? ' => [$workComment['id'], $workComment['c_id']]]
4127
                );
4128
            }
4129
        }
4130
    }
4131
}
4132
4133
/**
4134
 * Adds a comments to the work document.
4135
 *
4136
 * @param array $courseInfo
4137
 * @param int   $userId
4138
 * @param array $parentWork
4139
 * @param array $work
4140
 * @param array $data
4141
 *
4142
 * @return int
4143
 */
4144
function addWorkComment($courseInfo, $userId, $parentWork, $work, $data)
4145
{
4146
    $fileData = isset($data['attachment']) ? $data['attachment'] : null;
4147
    $commentTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT_COMMENT);
4148
4149
    // If no attachment and no comment then don't save comment
4150
    if (empty($fileData['name']) && empty($data['comment'])) {
4151
        return false;
4152
    }
4153
4154
    $params = [
4155
        'work_id' => $work['id'],
4156
        'c_id' => $work['c_id'],
4157
        'user_id' => $userId,
4158
        'comment' => $data['comment'],
4159
        'sent_at' => api_get_utc_datetime(),
4160
    ];
4161
4162
    $commentId = Database::insert($commentTable, $params);
4163
4164
    if ($commentId) {
4165
        Display::addFlash(
4166
            Display::return_message(get_lang('CommentAdded'))
4167
        );
4168
4169
        $sql = "UPDATE $commentTable SET id = iid WHERE iid = $commentId";
4170
        Database::query($sql);
4171
    }
4172
4173
    $userIdListToSend = [];
4174
    if (api_is_allowed_to_edit()) {
4175
        if (isset($data['send_email']) && $data['send_email']) {
4176
            // Teacher sends a feedback
4177
            $userIdListToSend = [$work['user_id']];
4178
        }
4179
    } else {
4180
        $sessionId = api_get_session_id();
4181
        if (empty($sessionId)) {
4182
            $teachers = CourseManager::get_teacher_list_from_course_code(
4183
                $courseInfo['code']
4184
            );
4185
            if (!empty($teachers)) {
4186
                $userIdListToSend = array_keys($teachers);
4187
            }
4188
        } else {
4189
            $teachers = SessionManager::getCoachesByCourseSession(
4190
                $sessionId,
4191
                $courseInfo['real_id']
4192
            );
4193
4194
            if (!empty($teachers)) {
4195
                $userIdListToSend = array_values($teachers);
4196
            }
4197
        }
4198
4199
        $sendNotification = api_get_course_setting('email_to_teachers_on_new_work_feedback');
4200
        if ($sendNotification != 1) {
4201
            $userIdListToSend = [];
4202
        }
4203
    }
4204
4205
    $url = api_get_path(WEB_CODE_PATH).'work/view.php?'.api_get_cidreq().'&id='.$work['id'];
4206
    $subject = sprintf(get_lang('ThereIsANewWorkFeedback'), $parentWork['title']);
4207
    $content = sprintf(get_lang('ThereIsANewWorkFeedbackInWorkXHere'), $work['title'], $url);
4208
4209
    if (!empty($data['comment'])) {
4210
        $content .= '<br /><b>'.get_lang('Comment').':</b><br />'.$data['comment'];
4211
    }
4212
4213
    if (!empty($userIdListToSend)) {
4214
        foreach ($userIdListToSend as $userIdToSend) {
4215
            MessageManager::send_message_simple(
4216
                $userIdToSend,
4217
                $subject,
4218
                $content
4219
            );
4220
        }
4221
    }
4222
4223
    if (!empty($commentId) && !empty($fileData)) {
4224
        $workParent = get_work_data_by_id($work['parent_id']);
4225
        if (!empty($workParent)) {
4226
            $uploadDir = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/work'.$workParent['url'];
4227
            $newFileName = 'comment_'.$commentId.'_'.php2phps(api_replace_dangerous_char($fileData['name']));
4228
            $newFilePath = $uploadDir.'/'.$newFileName;
4229
            $result = move_uploaded_file($fileData['tmp_name'], $newFilePath);
4230
            if ($result) {
4231
                $params = ['file' => $newFileName];
4232
                Database::update(
4233
                    $commentTable,
4234
                    $params,
4235
                    ['id = ? AND c_id = ? ' => [$commentId, $work['c_id']]]
4236
                );
4237
            }
4238
        }
4239
    }
4240
}
4241
4242
/**
4243
 * @param array $work
4244
 * @param array $workParent
4245
 *
4246
 * @return string
4247
 */
4248
function getWorkCommentForm($work, $workParent)
4249
{
4250
    $url = api_get_path(WEB_CODE_PATH).'work/view.php?id='.$work['id'].'&action=send_comment&'.api_get_cidreq();
4251
    $form = new FormValidator(
4252
        'work_comment',
4253
        'post',
4254
        $url,
4255
        '',
4256
        ['enctype' => "multipart/form-data"]
4257
    );
4258
4259
    $qualification = $workParent['qualification'];
4260
4261
    $isCourseManager = api_is_platform_admin() || api_is_coach() || api_is_allowed_to_edit(false, false, true);
4262
    $allowEdition = false;
4263
    if ($isCourseManager) {
4264
        $allowEdition = true;
4265
        if (!empty($work['qualification']) && api_get_configuration_value('block_student_publication_score_edition')) {
4266
            $allowEdition = false;
4267
        }
4268
    }
4269
4270
    if (api_is_platform_admin()) {
4271
        $allowEdition = true;
4272
    }
4273
4274
    if ($allowEdition) {
4275
        if (!empty($qualification) && intval($qualification) > 0) {
4276
            $model = ExerciseLib::getCourseScoreModel();
4277
            if (empty($model)) {
4278
                $form->addFloat(
4279
                    'qualification',
4280
                    [get_lang('Qualification'), " / ".$qualification],
4281
                    false,
4282
                    [],
4283
                    false,
4284
                    0,
4285
                    $qualification
4286
                );
4287
            } else {
4288
                ExerciseLib::addScoreModelInput(
4289
                    $form,
4290
                    'qualification',
4291
                    $qualification,
4292
                    $work['qualification']
4293
                );
4294
            }
4295
            $form->addFile('file', get_lang('Correction'));
4296
            $form->setDefaults(['qualification' => $work['qualification']]);
4297
        }
4298
    }
4299
4300
    Skill::addSkillsToUserForm($form, ITEM_TYPE_STUDENT_PUBLICATION, $workParent['id'], $work['user_id'], $work['id']);
4301
    $form->addHtmlEditor('comment', get_lang('Comment'), false);
4302
    $form->addFile('attachment', get_lang('Attachment'));
4303
    $form->addElement('hidden', 'id', $work['id']);
4304
4305
    if (api_is_allowed_to_edit()) {
4306
        $form->addCheckBox(
4307
            'send_email',
4308
            null,
4309
            get_lang('SendMailToStudent')
4310
        );
4311
    }
4312
4313
    $form->addButtonSend(get_lang('Send'), 'button');
4314
4315
    return $form->returnForm();
4316
}
4317
4318
/**
4319
 * @param array $homework result of get_work_assignment_by_id()
4320
 *
4321
 * @return array
4322
 */
4323
function getWorkDateValidationStatus($homework)
4324
{
4325
    $message = null;
4326
    $has_expired = false;
4327
    $has_ended = false;
4328
4329
    if (!empty($homework)) {
4330
        if (!empty($homework['expires_on']) || !empty($homework['ends_on'])) {
4331
            $time_now = time();
4332
4333
            if (!empty($homework['expires_on'])) {
4334
                $time_expires = api_strtotime($homework['expires_on'], 'UTC');
4335
                $difference = $time_expires - $time_now;
4336
                if ($difference < 0) {
4337
                    $has_expired = true;
4338
                }
4339
            }
4340
4341
            if (empty($homework['expires_on'])) {
4342
                $has_expired = false;
4343
            }
4344
4345
            if (!empty($homework['ends_on'])) {
4346
                $time_ends = api_strtotime($homework['ends_on'], 'UTC');
4347
                $difference2 = $time_ends - $time_now;
4348
                if ($difference2 < 0) {
4349
                    $has_ended = true;
4350
                }
4351
            }
4352
4353
            $ends_on = api_convert_and_format_date($homework['ends_on']);
4354
            $expires_on = api_convert_and_format_date($homework['expires_on']);
4355
        }
4356
4357
        if ($has_ended) {
4358
            $message = Display::return_message(get_lang('EndDateAlreadyPassed').' '.$ends_on, 'error');
4359
        } elseif ($has_expired) {
4360
            $message = Display::return_message(get_lang('ExpiryDateAlreadyPassed').' '.$expires_on, 'warning');
4361
        } else {
4362
            if ($has_expired) {
4363
                $message = Display::return_message(get_lang('ExpiryDateToSendWorkIs').' '.$expires_on);
4364
            }
4365
        }
4366
    }
4367
4368
    return [
4369
        'message' => $message,
4370
        'has_ended' => $has_ended,
4371
        'has_expired' => $has_expired,
4372
    ];
4373
}
4374
4375
/**
4376
 * @param FormValidator $form
4377
 * @param int           $uploadFormType
4378
 */
4379
function setWorkUploadForm($form, $uploadFormType = 0)
4380
{
4381
    $form->addHeader(get_lang('UploadADocument'));
4382
    $form->addHidden('contains_file', 0, ['id' => 'contains_file_id']);
4383
    $form->addHidden('active', 1);
4384
    $form->addHidden('accepted', 1);
4385
    $form->addElement('text', 'title', get_lang('Title'), ['id' => 'file_upload']);
4386
    $form->addElement(
4387
        'text',
4388
        'extension',
4389
        get_lang('FileExtension'),
4390
        ['id' => 'file_extension', 'readonly' => 'readonly']
4391
    );
4392
    $form->addRule('title', get_lang('ThisFieldIsRequired'), 'required');
4393
4394
    switch ($uploadFormType) {
4395
        case 0:
4396
            // File and text.
4397
            $form->addElement(
4398
                'file',
4399
                'file',
4400
                get_lang('UploadADocument'),
4401
                'size="40" onchange="updateDocumentTitle(this.value)"'
4402
            );
4403
            $form->addProgress();
4404
            $form->addHtmlEditor('description', get_lang('Description'), false, false, getWorkDescriptionToolbar());
4405
            break;
4406
        case 1:
4407
            // Only text.
4408
            $form->addHtmlEditor('description', get_lang('Description'), false, false, getWorkDescriptionToolbar());
4409
            $form->addRule('description', get_lang('ThisFieldIsRequired'), 'required');
4410
            break;
4411
        case 2:
4412
            // Only file.
4413
            $form->addElement(
4414
                'file',
4415
                'file',
4416
                get_lang('UploadADocument'),
4417
                'size="40" onchange="updateDocumentTitle(this.value)"'
4418
            );
4419
            $form->addProgress();
4420
            $form->addRule('file', get_lang('ThisFieldIsRequired'), 'required');
4421
            break;
4422
    }
4423
4424
    $form->addButtonUpload(get_lang('Upload'), 'submitWork');
4425
}
4426
4427
/**
4428
 * @param array $my_folder_data
4429
 * @param array $_course
4430
 * @param bool  $isCorrection
4431
 * @param array $workInfo
4432
 * @param array $file
4433
 *
4434
 * @return array
4435
 */
4436
function uploadWork($my_folder_data, $_course, $isCorrection = false, $workInfo = [], $file = [])
4437
{
4438
    if (isset($_FILES['file']) && !empty($_FILES['file'])) {
4439
        $file = $_FILES['file'];
4440
    }
4441
4442
    if (empty($file['size'])) {
4443
        return [
4444
            'error' => Display:: return_message(
4445
                get_lang('UplUploadFailedSizeIsZero'),
4446
                'error'
4447
            ),
4448
        ];
4449
    }
4450
    $updir = api_get_path(SYS_COURSE_PATH).$_course['path'].'/work/'; //directory path to upload
4451
4452
    // Try to add an extension to the file if it has'nt one
4453
    $filename = add_ext_on_mime(stripslashes($file['name']), $file['type']);
4454
4455
    // Replace dangerous characters
4456
    $filename = api_replace_dangerous_char($filename);
4457
4458
    // Transform any .php file in .phps fo security
4459
    $filename = php2phps($filename);
4460
    $filesize = filesize($file['tmp_name']);
4461
4462
    if (empty($filesize)) {
4463
        return [
4464
            'error' => Display::return_message(
4465
                get_lang('UplUploadFailedSizeIsZero'),
4466
                'error'
4467
            ),
4468
        ];
4469
    } elseif (!filter_extension($new_file_name)) {
4470
        return [
4471
            'error' => Display::return_message(
4472
                get_lang('UplUnableToSaveFileFilteredExtension'),
4473
                'error'
4474
            ),
4475
        ];
4476
    }
4477
4478
    $totalSpace = DocumentManager::documents_total_space($_course['real_id']);
4479
    $course_max_space = DocumentManager::get_course_quota($_course['code']);
4480
    $total_size = $filesize + $totalSpace;
4481
4482
    if ($total_size > $course_max_space) {
4483
        return [
4484
            'error' => Display::return_message(get_lang('NoSpace'), 'error'),
4485
        ];
4486
    }
4487
4488
    // Compose a unique file name to avoid any conflict
4489
    $new_file_name = api_get_unique_id();
4490
4491
    if ($isCorrection) {
4492
        if (!empty($workInfo['url'])) {
4493
            $new_file_name = basename($workInfo['url']).'_correction';
4494
        } else {
4495
            $new_file_name = $new_file_name.'_correction';
4496
        }
4497
    }
4498
4499
    $curdirpath = basename($my_folder_data['url']);
4500
4501
    // If we come from the group tools the groupid will be saved in $work_table
4502
    if (is_dir($updir.$curdirpath) || empty($curdirpath)) {
4503
        $result = move_uploaded_file(
4504
            $file['tmp_name'],
4505
            $updir.$curdirpath.'/'.$new_file_name
4506
        );
4507
    } else {
4508
        return [
4509
            'error' => Display :: return_message(
4510
                get_lang('FolderDoesntExistsInFileSystem'),
4511
                'error'
4512
            ),
4513
        ];
4514
    }
4515
4516
    if ($result) {
4517
        $url = 'work/'.$curdirpath.'/'.$new_file_name;
4518
    } else {
4519
        return false;
4520
    }
4521
4522
    return [
4523
        'url' => $url,
4524
        'filename' => $filename,
4525
        'filesize' => $filesize,
4526
        'error' => '',
4527
    ];
4528
}
4529
4530
/**
4531
 * Send an e-mail to users related to this work.
4532
 *
4533
 * @param array $workInfo
4534
 * @param int   $workId
4535
 * @param array $courseInfo
4536
 * @param int   $sessionId
4537
 */
4538
function sendAlertToUsers($workInfo, $workId, $courseInfo, $sessionId = 0)
4539
{
4540
    $sessionId = (int) $sessionId;
4541
4542
    if (empty($workInfo) || empty($courseInfo) || empty($workId)) {
4543
        return false;
4544
    }
4545
4546
    $courseCode = $courseInfo['code'];
4547
4548
    $workData = get_work_data_by_id($workId, $courseInfo['real_id'], $sessionId);
4549
    // last value is to check this is not "just" an edit
4550
    // YW Tis part serve to send a e-mail to the tutors when a new file is sent
4551
    $send = api_get_course_setting('email_alert_manager_on_new_doc');
4552
4553
    $userList = [];
4554
    if ($send == SEND_EMAIL_EVERYONE || $send == SEND_EMAIL_TEACHERS) {
4555
        // Lets predefine some variables. Be sure to change the from address!
4556
        if (empty($sessionId)) {
4557
            // Teachers
4558
            $userList = CourseManager::get_user_list_from_course_code(
4559
                $courseCode,
4560
                null,
4561
                null,
4562
                null,
4563
                COURSEMANAGER
4564
            );
4565
        } else {
4566
            // Coaches
4567
            $userList = CourseManager::get_user_list_from_course_code(
4568
                $courseCode,
4569
                $sessionId,
4570
                null,
4571
                null,
4572
                2
4573
            );
4574
        }
4575
    }
4576
4577
    if ($send == SEND_EMAIL_EVERYONE || $send == SEND_EMAIL_STUDENTS) {
4578
        // Send mail only to sender
4579
        $studentList = [[
4580
           'user_id' => api_get_user_id(),
4581
        ]];
4582
        $userList = array_merge($userList, $studentList);
4583
    }
4584
4585
    if ($send) {
4586
        $folderUrl = api_get_path(WEB_CODE_PATH)."work/work_list_all.php?cidReq=".$courseInfo['code']."&id_session=".$sessionId."&id=".$workInfo['id'];
4587
        $fileUrl = api_get_path(WEB_CODE_PATH)."work/view.php?cidReq=".$courseInfo['code']."&id_session=".$sessionId."&id=".$workData['id'];
4588
4589
        foreach ($userList as $userData) {
4590
            $userId = $userData['user_id'];
4591
            $userInfo = api_get_user_info($userId);
4592
            if (empty($userInfo)) {
4593
                continue;
4594
            }
4595
4596
            $userPostedADocument = sprintf(
4597
                get_lang('UserXPostedADocumentInCourseX'),
4598
                $userInfo['complete_name'],
4599
                $courseInfo['name']
4600
            );
4601
4602
            $subject = "[".api_get_setting('siteName')."] ".$userPostedADocument;
4603
            $message = $userPostedADocument."<br />";
4604
            $message .= get_lang('DateSent')." : ".api_format_date(api_get_local_time())."<br />";
4605
            $message .= get_lang('AssignmentName')." : ".Display::url($workInfo['title'], $folderUrl)."<br />";
4606
            $message .= get_lang('Filename')." : ".$workData['title']."<br />";
4607
            $message .= '<a href="'.$fileUrl.'">'.get_lang('DownloadLink')."</a><br />";
4608
4609
            MessageManager::send_message_simple(
4610
                $userId,
4611
                $subject,
4612
                $message,
4613
                0,
4614
                false,
4615
                false,
4616
                [],
4617
                false
4618
            );
4619
        }
4620
    }
4621
}
4622
4623
/**
4624
 * Check if the current uploaded work filename already exists in the current assement.
4625
 *
4626
 * @param string $filename
4627
 * @param int    $workId
4628
 *
4629
 * @return array
4630
 */
4631
function checkExistingWorkFileName($filename, $workId)
4632
{
4633
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
4634
    $filename = Database::escape_string($filename);
4635
    $workId = (int) $workId;
4636
4637
    $sql = "SELECT title FROM $table
4638
            WHERE parent_id = $workId AND title = '$filename' AND active = 1";
4639
    $result = Database::query($sql);
4640
4641
    return Database::fetch_assoc($result);
4642
}
4643
4644
/**
4645
 * @param array $workInfo
4646
 * @param array $values
4647
 * @param array $courseInfo
4648
 * @param int   $sessionId
4649
 * @param int   $groupId
4650
 * @param int   $userId
4651
 * @param array $file
4652
 * @param bool  $checkDuplicated
4653
 * @param bool  $showFlashMessage
4654
 *
4655
 * @return string|null
4656
 */
4657
function processWorkForm(
4658
    $workInfo,
4659
    $values,
4660
    $courseInfo,
4661
    $sessionId,
4662
    $groupId,
4663
    $userId,
4664
    $file = [],
4665
    $checkDuplicated = false,
4666
    $showFlashMessage = true
4667
) {
4668
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
4669
4670
    $courseId = $courseInfo['real_id'];
4671
    $groupId = (int) $groupId;
4672
    $sessionId = (int) $sessionId;
4673
    $userId = (int) $userId;
4674
4675
    $extension = '';
4676
    if (isset($values['extension'])) {
4677
        $extension = $values['extension'];
4678
    } else {
4679
        $fileInfo = pathinfo($values['title']);
4680
        if (isset($fileInfo['extension']) && !empty($fileInfo['extension'])) {
4681
            $extension = '.'.$fileInfo['extension'];
4682
            $values['title'] = $fileInfo['filename'];
4683
        }
4684
    }
4685
4686
    $title = $values['title'].$extension;
4687
    $description = isset($values['description']) ? $values['description'] : '';
4688
    $containsFile = isset($values['contains_file']) && !empty($values['contains_file']) ? (int) $values['contains_file'] : 0;
4689
4690
    $saveWork = true;
4691
    $filename = null;
4692
    $url = null;
4693
    $filesize = null;
4694
    $workData = [];
4695
    $message = null;
4696
4697
    if ($containsFile) {
4698
        $saveWork = false;
4699
        if ($checkDuplicated) {
4700
            if (checkExistingWorkFileName($file['name'], $workInfo['id'])) {
4701
                $saveWork = false;
4702
                $result['error'] = get_lang('YouAlreadySentThisFile');
4703
                $workData['error'] = get_lang('UplAlreadyExists');
4704
            } else {
4705
                $result = uploadWork($workInfo, $courseInfo, false, [], $file);
4706
            }
4707
        } else {
4708
            $result = uploadWork($workInfo, $courseInfo, false, [], $file);
4709
        }
4710
4711
        if (isset($result['error'])) {
4712
            $saveWork = false;
4713
            if ($showFlashMessage) {
4714
                $message = $result['error'];
4715
            }
4716
            if (empty($result['error']) && isset($result['url']) && !empty($result['url'])) {
4717
                $saveWork = true;
4718
            }
4719
        }
4720
    }
4721
4722
    if ($saveWork) {
4723
        $filename = isset($result['filename']) ? $result['filename'] : null;
4724
        if (empty($title)) {
4725
            $title = isset($result['title']) && !empty($result['title']) ? $result['title'] : get_lang('Untitled');
4726
        }
4727
        $filesize = isset($result['filesize']) ? $result['filesize'] : null;
4728
        $url = isset($result['url']) ? $result['url'] : null;
4729
    }
4730
4731
    if (empty($title)) {
4732
        $title = get_lang('Untitled');
4733
    }
4734
4735
    $groupIid = 0;
4736
    $groupInfo = [];
4737
    if ($groupId) {
4738
        $groupInfo = GroupManager::get_group_properties($groupId);
4739
        $groupIid = $groupInfo['iid'];
4740
    }
4741
4742
    if ($saveWork) {
4743
        $active = '1';
4744
        $params = [
4745
            'c_id' => $courseId,
4746
            'url' => $url,
4747
            'filetype' => 'file',
4748
            'title' => $title,
4749
            'description' => $description,
4750
            'contains_file' => $containsFile,
4751
            'active' => $active,
4752
            'accepted' => '1',
4753
            'qualificator_id' => 0,
4754
            'document_id' => 0,
4755
            'weight' => 0,
4756
            'allow_text_assignment' => 0,
4757
            'post_group_id' => $groupIid,
4758
            'sent_date' => api_get_utc_datetime(),
4759
            'parent_id' => $workInfo['id'],
4760
            'session_id' => $sessionId ? $sessionId : null,
4761
            'user_id' => $userId,
4762
            'has_properties' => 0,
4763
            'qualification' => 0,
4764
            //'filesize' => $filesize
4765
        ];
4766
        $workId = Database::insert($work_table, $params);
4767
4768
        if ($workId) {
4769
            $sql = "UPDATE $work_table SET id = iid WHERE iid = $workId ";
4770
            Database::query($sql);
4771
4772
            if (array_key_exists('filename', $workInfo) && !empty($filename)) {
4773
                $filename = Database::escape_string($filename);
4774
                $sql = "UPDATE $work_table SET
4775
                            filename = '$filename'
4776
                        WHERE iid = $workId";
4777
                Database::query($sql);
4778
            }
4779
4780
            if (array_key_exists('document_id', $workInfo)) {
4781
                $documentId = isset($values['document_id']) ? (int) $values['document_id'] : 0;
4782
                $sql = "UPDATE $work_table SET
4783
                            document_id = '$documentId'
4784
                        WHERE iid = $workId";
4785
                Database::query($sql);
4786
            }
4787
4788
            api_item_property_update(
4789
                $courseInfo,
4790
                'work',
4791
                $workId,
4792
                'DocumentAdded',
4793
                $userId,
4794
                $groupInfo
4795
            );
4796
            sendAlertToUsers($workInfo, $workId, $courseInfo, $sessionId);
4797
            Event::event_upload($workId);
4798
4799
            // The following feature requires the creation of a work-type
4800
            // extra_field and the following setting in the configuration file
4801
            // (until moved to the database). It allows te teacher to set a
4802
            // "considered work time", meaning the time we assume a student
4803
            // would have spent, approximately, to prepare the task before
4804
            // handing it in Chamilo, adding this time to the student total
4805
            // course use time, as a register of time spent *before* his
4806
            // connection to the platform to hand the work in.
4807
            $consideredWorkingTime = api_get_configuration_value('considered_working_time');
4808
4809
            if (!empty($consideredWorkingTime)) {
4810
                // Get the "considered work time" defined for this work
4811
                $fieldValue = new ExtraFieldValue('work');
4812
                $resultExtra = $fieldValue->getAllValuesForAnItem(
4813
                    $workInfo['iid'], //the ID of the work *folder*, not the document uploaded by the student
4814
                    true
4815
                );
4816
4817
                $workingTime = null;
4818
                foreach ($resultExtra as $field) {
4819
                    $field = $field['value'];
4820
                    if ($consideredWorkingTime == $field->getField()->getVariable()) {
4821
                        $workingTime = $field->getValue();
4822
                    }
4823
                }
4824
4825
                // If no time was defined, or a time of "0" was set, do nothing
4826
                if (!empty($workingTime)) {
4827
                    // If some time is set, get the list of docs handed in by
4828
                    // this student (to make sure we count the time only once)
4829
                    $userWorks = get_work_user_list(
4830
                        0,
4831
                        100,
4832
                        null,
4833
                        null,
4834
                        $workInfo['id'],
4835
                        null,
4836
                        $userId,
4837
                        false,
4838
                        $courseId,
4839
                        $sessionId
4840
                    );
4841
4842
                    if (1 == count($userWorks)) {
4843
                        // The student only uploaded one doc so far, so add the
4844
                        // considered work time to his course connection time
4845
                        Event::eventAddVirtualCourseTime(
4846
                            $courseId,
4847
                            $userId,
4848
                            $sessionId,
4849
                            $workingTime,
4850
                            $workInfo['iid']
4851
                        );
4852
                    }
4853
                }
4854
            }
4855
            $workData = get_work_data_by_id($workId);
4856
            if ($workData && $showFlashMessage) {
4857
                Display::addFlash(Display::return_message(get_lang('DocAdd')));
4858
            }
4859
        }
4860
    } else {
4861
        if ($showFlashMessage) {
4862
            Display::addFlash(
4863
                Display::return_message(
4864
                    $message ? $message : get_lang('ImpossibleToSaveTheDocument'),
4865
                    'error'
4866
                )
4867
            );
4868
        }
4869
    }
4870
4871
    return $workData;
4872
}
4873
4874
/**
4875
 * Creates a new task (directory) in the assignment tool.
4876
 *
4877
 * @param array $formValues
4878
 * @param int   $user_id
4879
 * @param array $courseInfo
4880
 * @param int   $groupId
4881
 * @param int   $sessionId
4882
 *
4883
 * @return bool|int
4884
 * @note $params can have the following elements, but should at least have the 2 first ones: (
4885
 *       'new_dir' => 'some-name',
4886
 *       'description' => 'some-desc',
4887
 *       'qualification' => 20 (e.g. 20),
4888
 *       'weight' => 50 (percentage) to add to gradebook (e.g. 50),
4889
 *       'allow_text_assignment' => 0/1/2,
4890
 *
4891
 * @todo Rename createAssignment or createWork, or something like that
4892
 */
4893
function addDir($formValues, $user_id, $courseInfo, $groupId, $sessionId = 0)
4894
{
4895
    $em = Database::getManager();
4896
4897
    $user_id = (int) $user_id;
4898
    $groupId = (int) $groupId;
4899
    $sessionId = (int) $sessionId;
4900
4901
    $groupIid = 0;
4902
    $groupInfo = [];
4903
    if (!empty($groupId)) {
4904
        $groupInfo = GroupManager::get_group_properties($groupId);
4905
        $groupIid = $groupInfo['iid'];
4906
    }
4907
    $session = $em->find('ChamiloCoreBundle:Session', $sessionId);
4908
4909
    $base_work_dir = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/work';
4910
    $course_id = $courseInfo['real_id'];
4911
4912
    $directory = api_replace_dangerous_char($formValues['new_dir']);
4913
    $directory = disable_dangerous_file($directory);
4914
4915
    $created_dir = create_unexisting_work_directory($base_work_dir, $directory);
4916
4917
    if (empty($created_dir)) {
4918
        return false;
4919
    }
4920
4921
    $enableEndDate = isset($formValues['enableEndDate']) ? true : false;
4922
    $enableExpiryDate = isset($formValues['enableExpiryDate']) ? true : false;
4923
4924
    if ($enableEndDate && $enableExpiryDate) {
4925
        if ($formValues['expires_on'] > $formValues['ends_on']) {
4926
            Display::addFlash(
4927
                Display::return_message(
4928
                    get_lang('DateExpiredNotBeLessDeadLine'),
4929
                    'warning'
4930
                )
4931
            );
4932
4933
            return false;
4934
        }
4935
    }
4936
4937
    $dirName = '/'.$created_dir;
4938
    $today = new DateTime(api_get_utc_datetime(), new DateTimeZone('UTC'));
4939
    $title = isset($formValues['work_title']) ? $formValues['work_title'] : $formValues['new_dir'];
4940
4941
    $workTable = new CStudentPublication();
4942
    $workTable
4943
        ->setCId($course_id)
4944
        ->setUrl($dirName)
4945
        ->setTitle($title)
4946
        ->setDescription($formValues['description'])
4947
        ->setActive(true)
4948
        ->setAccepted(true)
4949
        ->setFiletype('folder')
4950
        ->setPostGroupId($groupIid)
4951
        ->setSentDate($today)
4952
        ->setQualification($formValues['qualification'] != '' ? $formValues['qualification'] : 0)
4953
        ->setParentId(0)
4954
        ->setQualificatorId(0)
4955
        ->setWeight(!empty($formValues['weight']) ? $formValues['weight'] : 0)
4956
        ->setSession($session)
4957
        ->setAllowTextAssignment($formValues['allow_text_assignment'])
4958
        ->setContainsFile(0)
4959
        ->setUserId($user_id)
4960
        ->setHasProperties(0)
4961
        ->setDocumentId(0);
4962
4963
    $em->persist($workTable);
4964
    $em->flush();
4965
4966
    $workTable->setId($workTable->getIid());
4967
    $em->merge($workTable);
4968
    $em->flush();
4969
4970
    // Folder created
4971
    api_item_property_update(
4972
        $courseInfo,
4973
        'work',
4974
        $workTable->getIid(),
4975
        'DirectoryCreated',
4976
        $user_id,
4977
        $groupInfo
4978
    );
4979
4980
    updatePublicationAssignment(
4981
        $workTable->getIid(),
4982
        $formValues,
4983
        $courseInfo,
4984
        $groupIid
4985
    );
4986
4987
    // Added the new Work ID to the extra field values
4988
    $formValues['item_id'] = $workTable->getIid();
4989
4990
    $workFieldValue = new ExtraFieldValue('work');
4991
    $workFieldValue->saveFieldValues($formValues);
4992
4993
    $sendEmailAlert = api_get_course_setting('email_alert_students_on_new_homework');
4994
4995
    switch ($sendEmailAlert) {
4996
        case 1:
4997
            sendEmailToStudentsOnHomeworkCreation(
4998
                $workTable->getIid(),
4999
                $course_id,
5000
                $sessionId
5001
            );
5002
            //no break
5003
        case 2:
5004
            sendEmailToDrhOnHomeworkCreation(
5005
                $workTable->getIid(),
5006
                $course_id,
5007
                $sessionId
5008
            );
5009
            break;
5010
    }
5011
5012
    return $workTable->getIid();
5013
}
5014
5015
/**
5016
 * @param int   $workId
5017
 * @param array $courseInfo
5018
 *
5019
 * @return int
5020
 */
5021
function agendaExistsForWork($workId, $courseInfo)
5022
{
5023
    $workTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
5024
    $courseId = $courseInfo['real_id'];
5025
    $workId = (int) $workId;
5026
5027
    $sql = "SELECT add_to_calendar FROM $workTable
5028
            WHERE c_id = $courseId AND publication_id = ".$workId;
5029
    $res = Database::query($sql);
5030
    if (Database::num_rows($res)) {
5031
        $row = Database::fetch_array($res, 'ASSOC');
5032
        if (!empty($row['add_to_calendar'])) {
5033
            return $row['add_to_calendar'];
5034
        }
5035
    }
5036
5037
    return 0;
5038
}
5039
5040
/**
5041
 * Update work description, qualification, weight, allow_text_assignment.
5042
 *
5043
 * @param int   $workId     (iid)
5044
 * @param array $params
5045
 * @param array $courseInfo
5046
 * @param int   $sessionId
5047
 */
5048
function updateWork($workId, $params, $courseInfo, $sessionId = 0)
5049
{
5050
    $workTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
5051
    $filteredParams = [
5052
        'description' => $params['description'],
5053
        'qualification' => $params['qualification'],
5054
        'weight' => $params['weight'],
5055
        'allow_text_assignment' => $params['allow_text_assignment'],
5056
    ];
5057
5058
    Database::update(
5059
        $workTable,
5060
        $filteredParams,
5061
        [
5062
            'iid = ? AND c_id = ?' => [
5063
                $workId,
5064
                $courseInfo['real_id'],
5065
            ],
5066
        ]
5067
    );
5068
5069
    $workFieldValue = new ExtraFieldValue('work');
5070
    $workFieldValue->saveFieldValues($params);
5071
}
5072
5073
/**
5074
 * @param int   $workId
5075
 * @param array $params
5076
 * @param array $courseInfo
5077
 * @param int   $groupId
5078
 */
5079
function updatePublicationAssignment($workId, $params, $courseInfo, $groupId)
5080
{
5081
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
5082
    $workTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
5083
    $workId = (int) $workId;
5084
    $now = api_get_utc_datetime();
5085
    $course_id = $courseInfo['real_id'];
5086
5087
    // Insert into agenda
5088
    $agendaId = 0;
5089
    if (isset($params['add_to_calendar']) && $params['add_to_calendar'] == 1) {
5090
        // Setting today date
5091
        $date = $end_date = $now;
5092
5093
        if (isset($params['enableExpiryDate'])) {
5094
            $end_date = $params['expires_on'];
5095
            $date = $end_date;
5096
        }
5097
5098
        $title = sprintf(get_lang('HandingOverOfTaskX'), $params['new_dir']);
5099
        $description = isset($params['description']) ? $params['description'] : '';
5100
        $content = '<a href="'.api_get_path(WEB_CODE_PATH).'work/work_list.php?'.api_get_cidreq().'&id='.$workId.'">'
5101
            .$params['new_dir'].'</a>'.$description;
5102
5103
        $agendaId = agendaExistsForWork($workId, $courseInfo);
5104
5105
        // Add/edit agenda
5106
        $agenda = new Agenda('course');
5107
        $agenda->set_course($courseInfo);
5108
5109
        if (!empty($agendaId)) {
5110
            // add_to_calendar is set but it doesnt exists then invalidate
5111
            $eventInfo = $agenda->get_event($agendaId);
5112
            if (empty($eventInfo)) {
5113
                $agendaId = 0;
5114
            }
5115
        }
5116
5117
        $eventColor = $agenda->eventStudentPublicationColor;
5118
5119
        if (empty($agendaId)) {
5120
            $agendaId = $agenda->addEvent(
5121
                $date,
5122
                $end_date,
5123
                'false',
5124
                $title,
5125
                $content,
5126
                ['GROUP:'.$groupId],
5127
                false,
5128
                null,
5129
                [],
5130
                [],
5131
                null,
5132
                $eventColor
5133
            );
5134
        } else {
5135
            $agenda->editEvent(
5136
                $agendaId,
5137
                $end_date,
5138
                $end_date,
5139
                'false',
5140
                $title,
5141
                $content,
5142
                [],
5143
                [],
5144
                [],
5145
                null,
5146
                $eventColor
5147
            );
5148
        }
5149
    }
5150
5151
    $qualification = isset($params['qualification']) && !empty($params['qualification']) ? 1 : 0;
5152
    $expiryDate = isset($params['enableExpiryDate']) && (int) $params['enableExpiryDate'] == 1 ? api_get_utc_datetime($params['expires_on']) : '';
5153
    $endDate = isset($params['enableEndDate']) && (int) $params['enableEndDate'] == 1 ? api_get_utc_datetime($params['ends_on']) : '';
5154
    $data = get_work_assignment_by_id($workId, $course_id);
5155
    if (!empty($expiryDate)) {
5156
        $expiryDateCondition = "expires_on = '".Database::escape_string($expiryDate)."', ";
5157
    } else {
5158
        $expiryDateCondition = "expires_on = null, ";
5159
    }
5160
5161
    if (!empty($endDate)) {
5162
        $endOnCondition = "ends_on = '".Database::escape_string($endDate)."', ";
5163
    } else {
5164
        $endOnCondition = 'ends_on = null, ';
5165
    }
5166
5167
    if (empty($data)) {
5168
        $sql = "INSERT INTO $table SET
5169
                c_id = $course_id ,
5170
                $expiryDateCondition
5171
                $endOnCondition
5172
                add_to_calendar = $agendaId,
5173
                enable_qualification = '$qualification',
5174
                publication_id = '$workId'";
5175
        Database::query($sql);
5176
        $my_last_id = Database::insert_id();
5177
5178
        if ($my_last_id) {
5179
            $sql = "UPDATE $table SET
5180
                        id = iid
5181
                    WHERE iid = $my_last_id";
5182
            Database::query($sql);
5183
5184
            $sql = "UPDATE $workTable SET
5185
                        has_properties  = $my_last_id,
5186
                        view_properties = 1
5187
                    WHERE c_id = $course_id AND id = $workId";
5188
            Database::query($sql);
5189
        }
5190
    } else {
5191
        $sql = "UPDATE $table SET
5192
                    $expiryDateCondition
5193
                    $endOnCondition
5194
                    add_to_calendar  = $agendaId,
5195
                    enable_qualification = '".$qualification."'
5196
                WHERE
5197
                    publication_id = $workId AND
5198
                    c_id = $course_id AND
5199
                    iid = ".$data['iid'];
5200
        Database::query($sql);
5201
    }
5202
5203
    if (!empty($params['category_id'])) {
5204
        $link_info = GradebookUtils::isResourceInCourseGradebook(
5205
            $courseInfo['code'],
5206
            LINK_STUDENTPUBLICATION,
5207
            $workId,
5208
            api_get_session_id()
5209
        );
5210
5211
        $linkId = null;
5212
        if (!empty($link_info)) {
5213
            $linkId = $link_info['id'];
5214
        }
5215
5216
        if (isset($params['make_calification']) &&
5217
            $params['make_calification'] == 1
5218
        ) {
5219
            if (empty($linkId)) {
5220
                GradebookUtils::add_resource_to_course_gradebook(
5221
                    $params['category_id'],
5222
                    $courseInfo['code'],
5223
                    LINK_STUDENTPUBLICATION,
5224
                    $workId,
5225
                    $params['new_dir'],
5226
                    api_float_val($params['weight']),
5227
                    api_float_val($params['qualification']),
5228
                    $params['description'],
5229
                    1,
5230
                    api_get_session_id()
5231
                );
5232
            } else {
5233
                GradebookUtils::updateResourceFromCourseGradebook(
5234
                    $linkId,
5235
                    $courseInfo['code'],
5236
                    $params['weight']
5237
                );
5238
            }
5239
        } else {
5240
            // Delete everything of the gradebook for this $linkId
5241
            GradebookUtils::remove_resource_from_course_gradebook($linkId);
5242
        }
5243
    }
5244
}
5245
5246
/**
5247
 * Delete all work by student.
5248
 *
5249
 * @param int   $userId
5250
 * @param array $courseInfo
5251
 *
5252
 * @return array return deleted items
5253
 */
5254
function deleteAllWorkPerUser($userId, $courseInfo)
5255
{
5256
    $deletedItems = [];
5257
    $workPerUser = getWorkPerUser($userId);
5258
    if (!empty($workPerUser)) {
5259
        foreach ($workPerUser as $work) {
5260
            $work = $work['work'];
5261
            foreach ($work->user_results as $userResult) {
5262
                $result = deleteWorkItem($userResult['id'], $courseInfo);
5263
                if ($result) {
5264
                    $deletedItems[] = $userResult;
5265
                }
5266
            }
5267
        }
5268
    }
5269
5270
    return $deletedItems;
5271
}
5272
5273
/**
5274
 * @param int   $item_id
5275
 * @param array $courseInfo course info
5276
 *
5277
 * @return bool
5278
 */
5279
function deleteWorkItem($item_id, $courseInfo)
5280
{
5281
    $item_id = (int) $item_id;
5282
5283
    if (empty($item_id) || empty($courseInfo)) {
5284
        return false;
5285
    }
5286
5287
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
5288
    $TSTDPUBASG = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
5289
    $currentCourseRepositorySys = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/';
5290
    $is_allowed_to_edit = api_is_allowed_to_edit();
5291
    $file_deleted = false;
5292
    $is_author = user_is_author($item_id);
5293
    $work_data = get_work_data_by_id($item_id);
5294
    $locked = api_resource_is_locked_by_gradebook($work_data['parent_id'], LINK_STUDENTPUBLICATION);
5295
    $course_id = $courseInfo['real_id'];
5296
5297
    if (($is_allowed_to_edit && $locked == false) ||
5298
        (
5299
            $locked == false &&
5300
            $is_author &&
5301
            api_get_course_setting('student_delete_own_publication') == 1 &&
5302
            $work_data['qualificator_id'] == 0
5303
        )
5304
    ) {
5305
        // We found the current user is the author
5306
        $sql = "SELECT url, contains_file, user_id, session_id, parent_id
5307
                FROM $work_table
5308
                WHERE c_id = $course_id AND id = $item_id";
5309
        $result = Database::query($sql);
5310
        $row = Database::fetch_array($result);
5311
        $count = Database::num_rows($result);
5312
5313
        if ($count > 0) {
5314
            // If the "considered_working_time" option is enabled, check
5315
            // whether some time should be removed from track_e_course_access
5316
            $consideredWorkingTime = api_get_configuration_value('considered_working_time');
5317
            if ($consideredWorkingTime) {
5318
                $userWorks = get_work_user_list(
5319
                    0,
5320
                    100,
5321
                    null,
5322
                    null,
5323
                    $row['parent_id'],
5324
                    null,
5325
                    $row['user_id'],
5326
                    false,
5327
                    $course_id,
5328
                    $row['session_id']
5329
                );
5330
                // We're only interested in deleting the time if this is the latest work sent
5331
                if (count($userWorks) == 1) {
5332
                    // Get the "considered work time" defined for this work
5333
                    $fieldValue = new ExtraFieldValue('work');
5334
                    $resultExtra = $fieldValue->getAllValuesForAnItem(
5335
                        $row['parent_id'],
5336
                        true
5337
                    );
5338
5339
                    $workingTime = null;
5340
                    foreach ($resultExtra as $field) {
5341
                        $field = $field['value'];
5342
5343
                        if ($consideredWorkingTime == $field->getField()->getVariable()) {
5344
                            $workingTime = $field->getValue();
5345
                        }
5346
                    }
5347
                    // If no time was defined, or a time of "0" was set, do nothing
5348
                    if (!empty($workingTime)) {
5349
                        $sessionId = empty($row['session_id']) ? 0 : $row['session_id'];
5350
                        // Getting false from the following call would mean the
5351
                        // time record
5352
                        Event::eventRemoveVirtualCourseTime(
5353
                            $course_id,
5354
                            $row['user_id'],
5355
                            $sessionId,
5356
                            $workingTime,
5357
                            $row['parent_id']
5358
                        );
5359
                    }
5360
                }
5361
            } // end of considered_working_time check section
5362
5363
            $sql = "UPDATE $work_table SET active = 2
5364
                    WHERE c_id = $course_id AND id = $item_id";
5365
            Database::query($sql);
5366
            $sql = "DELETE FROM $TSTDPUBASG
5367
                    WHERE c_id = $course_id AND publication_id = $item_id";
5368
            Database::query($sql);
5369
5370
            Compilatio::plagiarismDeleteDoc($course_id, $item_id);
5371
5372
            api_item_property_update(
5373
                $courseInfo,
5374
                'work',
5375
                $item_id,
5376
                'DocumentDeleted',
5377
                api_get_user_id()
5378
            );
5379
5380
            Event::addEvent(
5381
                LOG_WORK_FILE_DELETE,
5382
                LOG_WORK_DATA,
5383
                [
5384
                    'id' => $work_data['id'],
5385
                    'url' => $work_data['url'],
5386
                    'title' => $work_data['title'],
5387
                ],
5388
                null,
5389
                api_get_user_id(),
5390
                api_get_course_int_id(),
5391
                api_get_session_id()
5392
            );
5393
5394
            $work = $row['url'];
5395
5396
            if ($row['contains_file'] == 1) {
5397
                if (!empty($work)) {
5398
                    if (api_get_setting('permanently_remove_deleted_files') === 'true') {
5399
                        my_delete($currentCourseRepositorySys.'/'.$work);
5400
                        $file_deleted = true;
5401
                    } else {
5402
                        $extension = pathinfo($work, PATHINFO_EXTENSION);
5403
                        $new_dir = $work.'_DELETED_'.$item_id.'.'.$extension;
5404
5405
                        if (file_exists($currentCourseRepositorySys.'/'.$work)) {
5406
                            rename($currentCourseRepositorySys.'/'.$work, $currentCourseRepositorySys.'/'.$new_dir);
5407
                            $file_deleted = true;
5408
                        }
5409
                    }
5410
                }
5411
            } else {
5412
                $file_deleted = true;
5413
            }
5414
        }
5415
    }
5416
5417
    return $file_deleted;
5418
}
5419
5420
/**
5421
 * @param FormValidator $form
5422
 * @param array         $defaults
5423
 * @param int           $workId
5424
 *
5425
 * @return FormValidator
5426
 */
5427
function getFormWork($form, $defaults = [], $workId = 0)
5428
{
5429
    $sessionId = api_get_session_id();
5430
    if (!empty($defaults)) {
5431
        if (isset($defaults['submit'])) {
5432
            unset($defaults['submit']);
5433
        }
5434
    }
5435
5436
    // Create the form that asks for the directory name
5437
    $form->addText('new_dir', get_lang('AssignmentName'));
5438
    $form->addHtmlEditor(
5439
        'description',
5440
        get_lang('Description'),
5441
        false,
5442
        false,
5443
        getWorkDescriptionToolbar()
5444
    );
5445
    $form->addButtonAdvancedSettings('advanced_params', get_lang('AdvancedParameters'));
5446
5447
    if (!empty($defaults) && (isset($defaults['enableEndDate']) || isset($defaults['enableExpiryDate']))) {
5448
        $form->addHtml('<div id="advanced_params_options" style="display:block">');
5449
    } else {
5450
        $form->addHtml('<div id="advanced_params_options" style="display:none">');
5451
    }
5452
5453
    // QualificationOfAssignment
5454
    $form->addElement('text', 'qualification', get_lang('QualificationNumeric'));
5455
5456
    if (($sessionId != 0 && Gradebook::is_active()) || $sessionId == 0) {
5457
        $form->addElement(
5458
            'checkbox',
5459
            'make_calification',
5460
            null,
5461
            get_lang('MakeQualifiable'),
5462
            [
5463
                'id' => 'make_calification_id',
5464
                'onclick' => "javascript: if(this.checked) { document.getElementById('option1').style.display='block';}else{document.getElementById('option1').style.display='none';}",
5465
            ]
5466
        );
5467
    } else {
5468
        // QualificationOfAssignment
5469
        $form->addElement('hidden', 'make_calification', false);
5470
    }
5471
5472
    if (!empty($defaults) && isset($defaults['category_id'])) {
5473
        $form->addHtml('<div id=\'option1\' style="display:block">');
5474
    } else {
5475
        $form->addHtml('<div id=\'option1\' style="display:none">');
5476
    }
5477
5478
    // Loading Gradebook select
5479
    GradebookUtils::load_gradebook_select_in_tool($form);
5480
5481
    $form->addElement('text', 'weight', get_lang('WeightInTheGradebook'));
5482
    $form->addHtml('</div>');
5483
5484
    $form->addElement('checkbox', 'enableExpiryDate', null, get_lang('EnableExpiryDate'), 'id="expiry_date"');
5485
    if (isset($defaults['enableExpiryDate']) && $defaults['enableExpiryDate']) {
5486
        $form->addHtml('<div id="option2" style="display: block;">');
5487
    } else {
5488
        $form->addHtml('<div id="option2" style="display: none;">');
5489
    }
5490
5491
    $timeNextWeek = time() + 86400 * 7;
5492
    $nextWeek = substr(api_get_local_time($timeNextWeek), 0, 10);
5493
    if (!isset($defaults['expires_on'])) {
5494
        $date = substr($nextWeek, 0, 10);
5495
        $defaults['expires_on'] = $date.' 23:59';
5496
    }
5497
5498
    $form->addElement('date_time_picker', 'expires_on', get_lang('ExpiresAt'));
5499
    $form->addHtml('</div>');
5500
    $form->addElement('checkbox', 'enableEndDate', null, get_lang('EnableEndDate'), 'id="end_date"');
5501
5502
    if (!isset($defaults['ends_on'])) {
5503
        $nextDay = substr(api_get_local_time($timeNextWeek + 86400), 0, 10);
5504
        $date = substr($nextDay, 0, 10);
5505
        $defaults['ends_on'] = $date.' 23:59';
5506
    }
5507
    if (isset($defaults['enableEndDate']) && $defaults['enableEndDate']) {
5508
        $form->addHtml('<div id="option3" style="display: block;">');
5509
    } else {
5510
        $form->addHtml('<div id="option3" style="display: none;">');
5511
    }
5512
5513
    $form->addElement('date_time_picker', 'ends_on', get_lang('EndsAt'));
5514
    $form->addHtml('</div>');
5515
5516
    $form->addElement('checkbox', 'add_to_calendar', null, get_lang('AddToCalendar'));
5517
    $form->addElement('select', 'allow_text_assignment', get_lang('DocumentType'), getUploadDocumentType());
5518
5519
    // Extra fields
5520
    $extraField = new ExtraField('work');
5521
    $extra = $extraField->addElements($form, $workId);
5522
5523
    $htmlHeadXtra[] = '
5524
        <script>
5525
        $(function() {
5526
            '.$extra['jquery_ready_content'].'
5527
        });
5528
        </script>';
5529
5530
    $form->addHtml('</div>');
5531
5532
    $skillList = Skill::addSkillsToForm($form, ITEM_TYPE_STUDENT_PUBLICATION, $workId);
5533
5534
    if (!empty($defaults)) {
5535
        $defaults['skills'] = array_keys($skillList);
5536
        $form->setDefaults($defaults);
5537
    }
5538
5539
    return $form;
5540
}
5541
5542
/**
5543
 * @return array
5544
 */
5545
function getUploadDocumentType()
5546
{
5547
    return [
5548
        0 => get_lang('AllowFileOrText'),
5549
        1 => get_lang('AllowOnlyText'),
5550
        2 => get_lang('AllowOnlyFiles'),
5551
    ];
5552
}
5553
5554
/**
5555
 * @param int   $itemId
5556
 * @param array $course_info
5557
 *
5558
 * @return bool
5559
 */
5560
function makeVisible($itemId, $course_info)
5561
{
5562
    $itemId = (int) $itemId;
5563
    if (empty($course_info) || empty($itemId)) {
5564
        return false;
5565
    }
5566
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
5567
    $course_id = $course_info['real_id'];
5568
5569
    $sql = "UPDATE $work_table SET accepted = 1
5570
            WHERE c_id = $course_id AND id = $itemId";
5571
    Database::query($sql);
5572
    api_item_property_update($course_info, 'work', $itemId, 'visible', api_get_user_id());
5573
5574
    return true;
5575
}
5576
5577
/**
5578
 * @param int   $itemId
5579
 * @param array $course_info
5580
 *
5581
 * @return int
5582
 */
5583
function makeInvisible($itemId, $course_info)
5584
{
5585
    $itemId = (int) $itemId;
5586
    if (empty($course_info) || empty($itemId)) {
5587
        return false;
5588
    }
5589
5590
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
5591
    $course_id = $course_info['real_id'];
5592
    $sql = "UPDATE $table
5593
            SET accepted = 0
5594
            WHERE c_id = $course_id AND id = '".$itemId."'";
5595
    Database::query($sql);
5596
    api_item_property_update(
5597
        $course_info,
5598
        'work',
5599
        $itemId,
5600
        'invisible',
5601
        api_get_user_id()
5602
    );
5603
5604
    return true;
5605
}
5606
5607
/**
5608
 * @param int    $item_id
5609
 * @param string $path
5610
 * @param array  $courseInfo
5611
 * @param int    $groupId    iid
5612
 * @param int    $sessionId
5613
 *
5614
 * @return string
5615
 */
5616
function generateMoveForm($item_id, $path, $courseInfo, $groupId, $sessionId)
5617
{
5618
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
5619
    $courseId = $courseInfo['real_id'];
5620
    $folders = [];
5621
    $session_id = (int) $sessionId;
5622
    $groupId = (int) $groupId;
5623
    $sessionCondition = empty($sessionId) ? ' AND (session_id = 0 OR session_id IS NULL) ' : " AND session_id='".$session_id."'";
5624
5625
    $groupIid = 0;
5626
    if ($groupId) {
5627
        $groupInfo = GroupManager::get_group_properties($groupId);
5628
        $groupIid = $groupInfo['iid'];
5629
    }
5630
5631
    $sql = "SELECT id, url, title
5632
            FROM $work_table
5633
            WHERE
5634
                c_id = $courseId AND
5635
                active IN (0, 1) AND
5636
                url LIKE '/%' AND
5637
                post_group_id = $groupIid
5638
                $sessionCondition";
5639
    $res = Database::query($sql);
5640
    while ($folder = Database::fetch_array($res)) {
5641
        $title = empty($folder['title']) ? basename($folder['url']) : $folder['title'];
5642
        $folders[$folder['id']] = $title;
5643
    }
5644
5645
    return build_work_move_to_selector($folders, $path, $item_id);
5646
}
5647
5648
/**
5649
 * @param int $workId
5650
 *
5651
 * @return string
5652
 */
5653
function showStudentList($workId)
5654
{
5655
    $columnModel = [
5656
        [
5657
            'name' => 'student',
5658
            'index' => 'student',
5659
            'width' => '350px',
5660
            'align' => 'left',
5661
            'sortable' => 'false',
5662
        ],
5663
        [
5664
            'name' => 'works',
5665
            'index' => 'works',
5666
            'align' => 'center',
5667
            'sortable' => 'false',
5668
        ],
5669
    ];
5670
    $token = null;
5671
    $url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_work_student_list_overview&work_id='.$workId.'&'.api_get_cidreq();
5672
5673
    $columns = [
5674
        get_lang('Students'),
5675
        get_lang('Works'),
5676
    ];
5677
5678
    $order = api_is_western_name_order() ? 'firstname' : 'lastname';
5679
    $params = [
5680
        'autowidth' => 'true',
5681
        'height' => 'auto',
5682
        'rowNum' => 5,
5683
        'sortname' => $order,
5684
        'sortorder' => 'asc',
5685
    ];
5686
5687
    $html = '<script>
5688
    $(function() {
5689
        '.Display::grid_js('studentList', $url, $columns, $columnModel, $params, [], null, true).'
5690
        $("#workList").jqGrid(
5691
            "navGrid",
5692
            "#studentList_pager",
5693
            { edit: false, add: false, del: false },
5694
            { height:280, reloadAfterSubmit:false }, // edit options
5695
            { height:280, reloadAfterSubmit:false }, // add options
5696
            { width:500 } // search options
5697
        );
5698
    });
5699
    </script>';
5700
    $html .= Display::grid_html('studentList');
5701
5702
    return $html;
5703
}
5704
5705
/**
5706
 * @param string $courseCode
5707
 * @param int    $sessionId
5708
 * @param int    $groupId
5709
 * @param int    $start
5710
 * @param int    $limit
5711
 * @param string $sidx
5712
 * @param string $sord
5713
 * @param $getCount
5714
 *
5715
 * @return array|int
5716
 */
5717
function getWorkUserList($courseCode, $sessionId, $groupId, $start, $limit, $sidx, $sord, $getCount = false)
5718
{
5719
    if (!empty($groupId)) {
5720
        $userList = GroupManager::get_users(
5721
            $groupId,
5722
            false,
5723
            $start,
5724
            $limit,
5725
            $getCount,
5726
            null,
5727
            $sidx,
5728
            $sord
5729
        );
5730
    } else {
5731
        $limitString = null;
5732
        if (!empty($start) && !empty($limit)) {
5733
            $start = (int) $start;
5734
            $limit = (int) $limit;
5735
            $limitString = " LIMIT $start, $limit";
5736
        }
5737
5738
        $orderBy = null;
5739
5740
        if (!empty($sidx) && !empty($sord)) {
5741
            if (in_array($sidx, ['firstname', 'lastname'])) {
5742
                $orderBy = "ORDER BY $sidx $sord";
5743
            }
5744
        }
5745
5746
        if (empty($sessionId)) {
5747
            $userList = CourseManager::get_user_list_from_course_code(
5748
                $courseCode,
5749
                $sessionId,
5750
                $limitString,
5751
                $orderBy,
5752
                STUDENT,
5753
                $getCount
5754
            );
5755
        } else {
5756
            $userList = CourseManager::get_user_list_from_course_code(
5757
                $courseCode,
5758
                $sessionId,
5759
                $limitString,
5760
                $orderBy,
5761
                0,
5762
                $getCount
5763
            );
5764
        }
5765
5766
        if ($getCount == false) {
5767
            $userList = array_keys($userList);
5768
        }
5769
    }
5770
5771
    return $userList;
5772
}
5773
5774
/**
5775
 * @param int    $workId
5776
 * @param string $courseCode
5777
 * @param int    $sessionId
5778
 * @param int    $groupId
5779
 * @param int    $start
5780
 * @param int    $limit
5781
 * @param int    $sidx
5782
 * @param string $sord
5783
 * @param bool   $getCount
5784
 *
5785
 * @return array|int
5786
 */
5787
function getWorkUserListData(
5788
    $workId,
5789
    $courseCode,
5790
    $sessionId,
5791
    $groupId,
5792
    $start,
5793
    $limit,
5794
    $sidx,
5795
    $sord,
5796
    $getCount = false
5797
) {
5798
    $my_folder_data = get_work_data_by_id($workId);
5799
    $workParents = [];
5800
    if (empty($my_folder_data)) {
5801
        $workParents = getWorkList($workId, $my_folder_data, null);
5802
    }
5803
5804
    $workIdList = [];
5805
    if (!empty($workParents)) {
5806
        foreach ($workParents as $work) {
5807
            $workIdList[] = $work->id;
5808
        }
5809
    }
5810
5811
    $courseInfo = api_get_course_info($courseCode);
5812
5813
    $userList = getWorkUserList(
5814
        $courseCode,
5815
        $sessionId,
5816
        $groupId,
5817
        $start,
5818
        $limit,
5819
        $sidx,
5820
        $sord,
5821
        $getCount
5822
    );
5823
5824
    if ($getCount) {
5825
        return $userList;
5826
    }
5827
    $results = [];
5828
    if (!empty($userList)) {
5829
        foreach ($userList as $userId) {
5830
            $user = api_get_user_info($userId);
5831
            $link = api_get_path(WEB_CODE_PATH).'work/student_work.php?'.api_get_cidreq().'&studentId='.$user['user_id'];
5832
            $url = Display::url(api_get_person_name($user['firstname'], $user['lastname']), $link);
5833
            $userWorks = 0;
5834
            if (!empty($workIdList)) {
5835
                $userWorks = getUniqueStudentAttempts(
5836
                    $workIdList,
5837
                    $groupId,
5838
                    $courseInfo['real_id'],
5839
                    $sessionId,
5840
                    $user['user_id']
5841
                );
5842
            }
5843
            $works = $userWorks." / ".count($workParents);
5844
            $results[] = [
5845
                'student' => $url,
5846
                'works' => Display::url($works, $link),
5847
            ];
5848
        }
5849
    }
5850
5851
    return $results;
5852
}
5853
5854
/**
5855
 * @param int   $id
5856
 * @param array $course_info
5857
 * @param bool  $isCorrection
5858
 *
5859
 * @return bool
5860
 */
5861
function downloadFile($id, $course_info, $isCorrection)
5862
{
5863
    return getFile($id, $course_info, true, $isCorrection, true);
5864
}
5865
5866
/**
5867
 * @param int   $id
5868
 * @param array $course_info
5869
 * @param bool  $download
5870
 * @param bool  $isCorrection
5871
 * @param bool  $forceAccessForCourseAdmins
5872
 *
5873
 * @return bool
5874
 */
5875
function getFile($id, $course_info, $download = true, $isCorrection = false, $forceAccessForCourseAdmins = false)
5876
{
5877
    $file = getFileContents($id, $course_info, 0, $isCorrection, $forceAccessForCourseAdmins);
5878
    if (!empty($file) && is_array($file)) {
5879
        return DocumentManager::file_send_for_download(
5880
            $file['path'],
5881
            $download,
5882
            $file['title']
5883
        );
5884
    }
5885
5886
    return false;
5887
}
5888
5889
/**
5890
 * Get the file contents for an assigment.
5891
 *
5892
 * @param int   $id
5893
 * @param array $courseInfo
5894
 * @param int   $sessionId
5895
 * @param bool  $correction
5896
 * @param bool  $forceAccessForCourseAdmins
5897
 *
5898
 * @return array|bool
5899
 */
5900
function getFileContents($id, $courseInfo, $sessionId = 0, $correction = false, $forceAccessForCourseAdmins = false)
5901
{
5902
    $id = (int) $id;
5903
    if (empty($courseInfo) || empty($id)) {
5904
        return false;
5905
    }
5906
    if (empty($sessionId)) {
5907
        $sessionId = api_get_session_id();
5908
    }
5909
5910
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
5911
    if (!empty($courseInfo['real_id'])) {
5912
        $sql = "SELECT *
5913
                FROM $table
5914
                WHERE c_id = ".$courseInfo['real_id']." AND id = $id";
5915
5916
        $result = Database::query($sql);
5917
        if ($result && Database::num_rows($result)) {
5918
            $row = Database::fetch_array($result, 'ASSOC');
5919
5920
            if ($correction) {
5921
                $row['url'] = $row['url_correction'];
5922
            }
5923
5924
            if (empty($row['url'])) {
5925
                return false;
5926
            }
5927
5928
            $full_file_name = api_get_path(SYS_COURSE_PATH).api_get_course_path().'/'.$row['url'];
5929
5930
            $item_info = api_get_item_property_info(
5931
                api_get_course_int_id(),
5932
                'work',
5933
                $row['id'],
5934
                $sessionId
5935
            );
5936
5937
            if (empty($item_info)) {
5938
                return false;
5939
            }
5940
5941
            $isAllow = allowOnlySubscribedUser(
5942
                api_get_user_id(),
5943
                $row['parent_id'],
5944
                $courseInfo['real_id'],
5945
                $forceAccessForCourseAdmins
5946
            );
5947
5948
            if (empty($isAllow)) {
5949
                return false;
5950
            }
5951
5952
            /*
5953
            field show_score in table course :
5954
                0 =>    New documents are visible for all users
5955
                1 =>    New documents are only visible for the teacher(s)
5956
            field visibility in table item_property :
5957
                0 => eye closed, invisible for all students
5958
                1 => eye open
5959
            field accepted in table c_student_publication :
5960
                0 => eye closed, invisible for all students
5961
                1 => eye open
5962
            ( We should have visibility == accepted, otherwise there is an
5963
            inconsistency in the Database)
5964
            field value in table c_course_setting :
5965
                0 => Allow learners to delete their own publications = NO
5966
                1 => Allow learners to delete their own publications = YES
5967
5968
            +------------------+-------------------------+------------------------+
5969
            |Can download work?| doc visible for all = 0 | doc visible for all = 1|
5970
            +------------------+-------------------------+------------------------+
5971
            |  visibility = 0  | editor only             | editor only            |
5972
            |                  |                         |                        |
5973
            +------------------+-------------------------+------------------------+
5974
            |  visibility = 1  | editor                  | editor                 |
5975
            |                  | + owner of the work     | + any student          |
5976
            +------------------+-------------------------+------------------------+
5977
            (editor = teacher + admin + anybody with right api_is_allowed_to_edit)
5978
            */
5979
5980
            $work_is_visible = $item_info['visibility'] == 1 && $row['accepted'] == 1;
5981
            $doc_visible_for_all = (int) $courseInfo['show_score'] === 0;
5982
5983
            $is_editor = api_is_allowed_to_edit(true, true, true);
5984
            $student_is_owner_of_work = user_is_author($row['id'], api_get_user_id());
5985
5986
            if (($forceAccessForCourseAdmins && $isAllow) ||
5987
                $is_editor ||
5988
                $student_is_owner_of_work ||
5989
                ($doc_visible_for_all && $work_is_visible)
5990
            ) {
5991
                $title = $row['title'];
5992
                if ($correction) {
5993
                    $title = $row['title_correction'];
5994
                }
5995
                if (array_key_exists('filename', $row) && !empty($row['filename'])) {
5996
                    $title = $row['filename'];
5997
                }
5998
5999
                $title = str_replace(' ', '_', $title);
6000
6001
                if ($correction == false) {
6002
                    $userInfo = api_get_user_info($row['user_id']);
6003
                    if ($userInfo) {
6004
                        $date = api_get_local_time($row['sent_date']);
6005
                        $date = str_replace([':', '-', ' '], '_', $date);
6006
                        $title = $date.'_'.$userInfo['username'].'_'.$title;
6007
                    }
6008
                }
6009
6010
                if (Security::check_abs_path(
6011
                    $full_file_name,
6012
                    api_get_path(SYS_COURSE_PATH).api_get_course_path().'/'
6013
                )) {
6014
                    Event::event_download($title);
6015
6016
                    return [
6017
                        'path' => $full_file_name,
6018
                        'title' => $title,
6019
                        'title_correction' => $row['title_correction'],
6020
                    ];
6021
                }
6022
            }
6023
        }
6024
    }
6025
6026
    return false;
6027
}
6028
6029
/**
6030
 * @param int    $userId
6031
 * @param array  $courseInfo
6032
 * @param string $format
6033
 *
6034
 * @return bool
6035
 */
6036
function exportAllWork($userId, $courseInfo, $format = 'pdf')
6037
{
6038
    $userInfo = api_get_user_info($userId);
6039
    if (empty($userInfo) || empty($courseInfo)) {
6040
        return false;
6041
    }
6042
6043
    $workPerUser = getWorkPerUser($userId);
6044
6045
    switch ($format) {
6046
        case 'pdf':
6047
            if (!empty($workPerUser)) {
6048
                $pdf = new PDF();
6049
6050
                $content = null;
6051
                foreach ($workPerUser as $work) {
6052
                    $work = $work['work'];
6053
                    foreach ($work->user_results as $userResult) {
6054
                        $content .= $userResult['title'];
6055
                        // No need to use api_get_local_time()
6056
                        $content .= $userResult['sent_date'];
6057
                        $content .= $userResult['qualification'];
6058
                        $content .= $userResult['description'];
6059
                    }
6060
                }
6061
6062
                if (!empty($content)) {
6063
                    $pdf->content_to_pdf(
6064
                        $content,
6065
                        null,
6066
                        api_replace_dangerous_char($userInfo['complete_name']),
6067
                        $courseInfo['code']
6068
                    );
6069
                }
6070
            }
6071
            break;
6072
    }
6073
}
6074
6075
/**
6076
 * @param int    $workId
6077
 * @param array  $courseInfo
6078
 * @param int    $sessionId
6079
 * @param string $format
6080
 *
6081
 * @return bool
6082
 */
6083
function exportAllStudentWorkFromPublication(
6084
    $workId,
6085
    $courseInfo,
6086
    $sessionId,
6087
    $format = 'pdf'
6088
) {
6089
    if (empty($courseInfo)) {
6090
        return false;
6091
    }
6092
6093
    $workData = get_work_data_by_id($workId);
6094
    if (empty($workData)) {
6095
        return false;
6096
    }
6097
6098
    $assignment = get_work_assignment_by_id($workId);
6099
6100
    $courseCode = $courseInfo['code'];
6101
    $header = get_lang('Course').': '.$courseInfo['title'];
6102
    $teachers = CourseManager::getTeacherListFromCourseCodeToString(
6103
        $courseCode
6104
    );
6105
6106
    if (!empty($sessionId)) {
6107
        $sessionInfo = api_get_session_info($sessionId);
6108
        if (!empty($sessionInfo)) {
6109
            $header .= ' - '.$sessionInfo['name'];
6110
            $header .= '<br />'.$sessionInfo['description'];
6111
            $teachers = SessionManager::getCoachesByCourseSessionToString(
6112
                $sessionId,
6113
                $courseInfo['real_id']
6114
            );
6115
        }
6116
    }
6117
6118
    $header .= '<br />'.get_lang('Teachers').': '.$teachers.'<br />';
6119
    $header .= '<br />'.get_lang('Date').': '.api_get_local_time().'<br />';
6120
    $header .= '<br />'.get_lang('WorkName').': '.$workData['title'].'<br />';
6121
6122
    $content = null;
6123
    $expiresOn = null;
6124
6125
    if (!empty($assignment) && isset($assignment['expires_on'])) {
6126
        $content .= '<br /><strong>'.get_lang('PostedExpirationDate').'</strong>: '.api_get_local_time($assignment['expires_on']);
6127
        $expiresOn = api_get_local_time($assignment['expires_on']);
6128
    }
6129
6130
    if (!empty($workData['description'])) {
6131
        $content .= '<br /><strong>'.get_lang('Description').'</strong>: '.$workData['description'];
6132
    }
6133
6134
    $workList = get_work_user_list(null, null, null, null, $workId);
6135
6136
    switch ($format) {
6137
        case 'pdf':
6138
            if (!empty($workList)) {
6139
                $table = new HTML_Table(['class' => 'table table-hover table-striped data_table']);
6140
                $headers = [
6141
                    get_lang('Name'),
6142
                    get_lang('User'),
6143
                    get_lang('HandOutDateLimit'),
6144
                    get_lang('SentDate'),
6145
                    get_lang('FileName'),
6146
                    get_lang('Score'),
6147
                    get_lang('Feedback'),
6148
                ];
6149
6150
                $column = 0;
6151
                foreach ($headers as $header) {
6152
                    $table->setHeaderContents(0, $column, $header);
6153
                    $column++;
6154
                }
6155
6156
                $row = 1;
6157
6158
                //$pdf->set_custom_header($header);
6159
                foreach ($workList as $work) {
6160
                    $content .= '<hr />';
6161
                    // getWorkComments need c_id
6162
                    $work['c_id'] = $courseInfo['real_id'];
6163
6164
                    //$content .= get_lang('Date').': '.api_get_local_time($work['sent_date_from_db']).'<br />';
6165
                    $score = null;
6166
                    if (!empty($work['qualification_only'])) {
6167
                        $score = $work['qualification_only'];
6168
                    }
6169
6170
                    $comments = getWorkComments($work);
6171
6172
                    $feedback = null;
6173
                    if (!empty($comments)) {
6174
                        $content .= '<h4>'.get_lang('Feedback').': </h4>';
6175
                        foreach ($comments as $comment) {
6176
                            $feedback .= get_lang('User').': '.$comment['complete_name'].
6177
                                '<br />';
6178
                            $feedback .= $comment['comment'].'<br />';
6179
                        }
6180
                    }
6181
                    $table->setCellContents($row, 0, strip_tags($workData['title']));
6182
                    $table->setCellContents($row, 1, strip_tags($work['fullname']));
6183
                    $table->setCellContents($row, 2, $expiresOn);
6184
                    $table->setCellContents($row, 3, api_get_local_time($work['sent_date_from_db']));
6185
                    $table->setCellContents($row, 4, strip_tags($work['title']));
6186
                    $table->setCellContents($row, 5, $score);
6187
                    $table->setCellContents($row, 6, $feedback);
6188
6189
                    $row++;
6190
                }
6191
6192
                $content = $table->toHtml();
6193
6194
                if (!empty($content)) {
6195
                    $params = [
6196
                        'filename' => $workData['title'].'_'.api_get_local_time(),
6197
                        'pdf_title' => api_replace_dangerous_char($workData['title']),
6198
                        'course_code' => $courseInfo['code'],
6199
                    ];
6200
                    $pdf = new PDF('A4', null, $params);
6201
                    $pdf->html_to_pdf_with_template($content);
6202
                }
6203
                exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

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

Loading history...
6204
            }
6205
            break;
6206
    }
6207
}
6208
6209
/**
6210
 * Downloads all user files per user.
6211
 *
6212
 * @param int   $userId
6213
 * @param array $courseInfo
6214
 *
6215
 * @return bool
6216
 */
6217
function downloadAllFilesPerUser($userId, $courseInfo)
6218
{
6219
    $userInfo = api_get_user_info($userId);
6220
6221
    if (empty($userInfo) || empty($courseInfo)) {
6222
        return false;
6223
    }
6224
6225
    $tempZipFile = api_get_path(SYS_ARCHIVE_PATH).api_get_unique_id().".zip";
6226
    $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/work/';
6227
    $zip = new PclZip($tempZipFile);
6228
    $workPerUser = getWorkPerUser($userId);
6229
6230
    if (!empty($workPerUser)) {
6231
        $files = [];
6232
        foreach ($workPerUser as $work) {
6233
            $work = $work['work'];
6234
            foreach ($work->user_results as $userResult) {
6235
                if (empty($userResult['url']) || empty($userResult['contains_file'])) {
6236
                    continue;
6237
                }
6238
                $data = getFileContents($userResult['id'], $courseInfo);
6239
                if (!empty($data) && isset($data['path'])) {
6240
                    $files[basename($data['path'])] = [
6241
                        'title' => $data['title'],
6242
                        'path' => $data['path'],
6243
                    ];
6244
                }
6245
            }
6246
        }
6247
6248
        if (!empty($files)) {
6249
            Session::write('files', $files);
6250
            foreach ($files as $data) {
6251
                $zip->add(
6252
                    $data['path'],
6253
                    PCLZIP_OPT_REMOVE_PATH,
6254
                    $coursePath,
6255
                    PCLZIP_CB_PRE_ADD,
6256
                    'preAddAllWorkStudentCallback'
6257
                );
6258
            }
6259
        }
6260
6261
        // Start download of created file
6262
        $name = basename(api_replace_dangerous_char($userInfo['complete_name'])).'.zip';
6263
        Event::event_download($name.'.zip (folder)');
6264
        if (Security::check_abs_path($tempZipFile, api_get_path(SYS_ARCHIVE_PATH))) {
6265
            DocumentManager::file_send_for_download($tempZipFile, true, $name);
6266
            @unlink($tempZipFile);
6267
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

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

Loading history...
6268
        }
6269
    }
6270
    exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

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

Loading history...
6271
}
6272
6273
/**
6274
 * @param $p_event
6275
 * @param array $p_header
6276
 *
6277
 * @return int
6278
 */
6279
function preAddAllWorkStudentCallback($p_event, &$p_header)
6280
{
6281
    $files = Session::read('files');
6282
    if (isset($files[basename($p_header['stored_filename'])])) {
6283
        $p_header['stored_filename'] = $files[basename($p_header['stored_filename'])]['title'];
6284
6285
        return 1;
6286
    }
6287
6288
    return 0;
6289
}
6290
6291
/**
6292
 * Get all work created by a user.
6293
 *
6294
 * @param int $user_id
6295
 * @param int $courseId
6296
 * @param int $sessionId
6297
 *
6298
 * @return array
6299
 */
6300
function getWorkCreatedByUser($user_id, $courseId, $sessionId)
6301
{
6302
    $items = api_get_item_property_list_by_tool_by_user(
6303
        $user_id,
6304
        'work',
6305
        $courseId,
6306
        $sessionId
6307
    );
6308
6309
    $list = [];
6310
    if (!empty($items)) {
6311
        foreach ($items as $work) {
6312
            $item = get_work_data_by_id(
6313
                $work['ref'],
6314
                $courseId,
6315
                $sessionId
6316
            );
6317
            if (!empty($item)) {
6318
                $list[] = [
6319
                    $item['title'],
6320
                    api_get_local_time($work['insert_date']),
6321
                    api_get_local_time($work['lastedit_date']),
6322
                ];
6323
            }
6324
        }
6325
    }
6326
6327
    return $list;
6328
}
6329
6330
/**
6331
 * @param array $courseInfo
6332
 * @param int   $workId
6333
 *
6334
 * @return bool
6335
 */
6336
function protectWork($courseInfo, $workId)
6337
{
6338
    $userId = api_get_user_id();
6339
    $groupId = api_get_group_id();
6340
    $sessionId = api_get_session_id();
6341
    $workData = get_work_data_by_id($workId);
6342
6343
    if (empty($workData) || empty($courseInfo)) {
6344
        api_not_allowed(true);
6345
    }
6346
6347
    if (api_is_platform_admin() || api_is_allowed_to_edit()) {
6348
        return true;
6349
    }
6350
6351
    $workId = $workData['id'];
6352
6353
    if ($workData['active'] != 1) {
6354
        api_not_allowed(true);
6355
    }
6356
6357
    $visibility = api_get_item_visibility($courseInfo, 'work', $workId, $sessionId);
6358
6359
    if ($visibility != 1) {
6360
        api_not_allowed(true);
6361
    }
6362
6363
    $isAllow = allowOnlySubscribedUser($userId, $workId, $courseInfo['real_id']);
6364
    if (empty($isAllow)) {
6365
        api_not_allowed(true);
6366
    }
6367
6368
    $groupInfo = GroupManager::get_group_properties($groupId);
6369
6370
    if (!empty($groupId)) {
6371
        $showWork = GroupManager::user_has_access(
6372
            $userId,
6373
            $groupInfo['iid'],
6374
            GroupManager::GROUP_TOOL_WORK
6375
        );
6376
        if (!$showWork) {
6377
            api_not_allowed(true);
6378
        }
6379
    }
6380
}
6381
6382
/**
6383
 * @param array $courseInfo
6384
 * @param array $work
6385
 */
6386
function deleteCorrection($courseInfo, $work)
6387
{
6388
    if (isset($work['url_correction']) && !empty($work['url_correction']) && isset($work['iid'])) {
6389
        $id = $work['iid'];
6390
        $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
6391
        $sql = "UPDATE $table SET
6392
                    url_correction = '',
6393
                    title_correction = ''
6394
                WHERE iid = $id";
6395
        Database::query($sql);
6396
        $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/';
6397
        if (file_exists($coursePath.$work['url_correction'])) {
6398
            if (Security::check_abs_path($coursePath.$work['url_correction'], $coursePath)) {
6399
                unlink($coursePath.$work['url_correction']);
6400
            }
6401
        }
6402
    }
6403
}
6404
6405
/**
6406
 * @param int $workId
6407
 *
6408
 * @return string
6409
 */
6410
function workGetExtraFieldData($workId)
6411
{
6412
    $sessionField = new ExtraField('work');
6413
    $extraFieldData = $sessionField->getDataAndFormattedValues($workId);
6414
    $result = '';
6415
    if (!empty($extraFieldData)) {
6416
        $result .= '<div class="well">';
6417
        foreach ($extraFieldData as $data) {
6418
            $result .= $data['text'].': <b>'.$data['value'].'</b>';
6419
        }
6420
        $result .= '</div>';
6421
    }
6422
6423
    return $result;
6424
}
6425