Completed
Push — master ( cbfb7e...6f5084 )
by Julito
20:33
created

deleteDirWork()   C

Complexity

Conditions 15
Paths 88

Size

Total Lines 134
Code Lines 86

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 15
eloc 86
nc 88
nop 1
dl 0
loc 134
rs 5.0387
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

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