Passed
Push — master ( 1cf373...d04f46 )
by Julito
09:24
created

downloadAllFilesPerUser()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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

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

    return false;
}

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

Loading history...
5449
        /** @var CStudentPublication $studentPublication */
5450
        $studentPublication = $file['entity'];
5451
    }
5452
5453
    return false;
5454
}
5455
5456
/**
5457
 * Get the file contents for an assigment.
5458
 *
5459
 * @param int   $id
5460
 * @param array $courseInfo
5461
 * @param int   $sessionId
5462
 * @param bool  $correction
5463
 * @param bool  $forceAccessForCourseAdmins
5464
 *
5465
 * @return array|bool
5466
 */
5467
function getFileContents($id, $courseInfo, $sessionId = 0, $correction = false, $forceAccessForCourseAdmins = false)
5468
{
5469
    $id = (int) $id;
5470
5471
    if (empty($courseInfo) || empty($id)) {
5472
        return false;
5473
    }
5474
    if (empty($sessionId)) {
5475
        $sessionId = api_get_session_id();
5476
    }
5477
5478
    $courseEntity = api_get_course_entity($courseInfo['real_id']);
5479
    $sessionEntity = api_get_session_entity($sessionId);
5480
5481
    $repo = Container::getStudentPublicationRepository();
5482
    /** @var CStudentPublication $studentPublication */
5483
    $studentPublication = $repo->find($id);
5484
5485
    if (empty($studentPublication)) {
5486
        return false;
5487
    }
5488
5489
    if ($correction) {
5490
        //$row['url'] = $row['url_correction'];
5491
    }
5492
    $hasFile = $studentPublication->getResourceNode()->hasResourceFile();
5493
    if (!$hasFile) {
5494
        return false;
5495
    }
5496
5497
    /*
5498
    $item_info = api_get_item_property_info(
5499
        api_get_course_int_id(),
5500
        'work',
5501
        $row['iid'],
5502
        $sessionId
5503
    );
5504
5505
    if (empty($item_info)) {
5506
        return false;
5507
    }*/
5508
5509
    $isAllow = allowOnlySubscribedUser(
5510
        api_get_user_id(),
5511
        $studentPublication->getParentId(),
5512
        $courseInfo['real_id'],
5513
        $forceAccessForCourseAdmins
5514
    );
5515
5516
    if (empty($isAllow)) {
5517
        return false;
5518
    }
5519
5520
    /*
5521
    field show_score in table course :
5522
        0 =>    New documents are visible for all users
5523
        1 =>    New documents are only visible for the teacher(s)
5524
    field visibility in table item_property :
5525
        0 => eye closed, invisible for all students
5526
        1 => eye open
5527
    field accepted in table c_student_publication :
5528
        0 => eye closed, invisible for all students
5529
        1 => eye open
5530
    ( We should have visibility == accepted, otherwise there is an
5531
    inconsistency in the Database)
5532
    field value in table c_course_setting :
5533
        0 => Allow learners to delete their own publications = NO
5534
        1 => Allow learners to delete their own publications = YES
5535
5536
    +------------------+-------------------------+------------------------+
5537
    |Can download work?| doc visible for all = 0 | doc visible for all = 1|
5538
    +------------------+-------------------------+------------------------+
5539
    |  visibility = 0  | editor only             | editor only            |
5540
    |                  |                         |                        |
5541
    +------------------+-------------------------+------------------------+
5542
    |  visibility = 1  | editor                  | editor                 |
5543
    |                  | + owner of the work     | + any student          |
5544
    +------------------+-------------------------+------------------------+
5545
    (editor = teacher + admin + anybody with right api_is_allowed_to_edit)
5546
    */
5547
5548
    $work_is_visible = $studentPublication->isVisible($courseEntity, $sessionEntity) && $studentPublication->getAccepted();
5549
    $doc_visible_for_all = 0 === (int) $courseInfo['show_score'];
5550
5551
    $is_editor = api_is_allowed_to_edit(true, true, true);
5552
    $student_is_owner_of_work = user_is_author($studentPublication->getIid(), api_get_user_id());
5553
5554
    if (($forceAccessForCourseAdmins && $isAllow) ||
5555
        $is_editor ||
5556
        $student_is_owner_of_work ||
5557
        ($doc_visible_for_all && $work_is_visible)
5558
    ) {
5559
        $title = $studentPublication->getTitle();
5560
        if ($correction) {
5561
            $title = $studentPublication->getTitleCorrection();
5562
        }
5563
        if ($hasFile) {
5564
            $title = $studentPublication->getResourceNode()->getResourceFile()->getName();
5565
        }
5566
5567
        $title = str_replace(' ', '_', $title);
5568
5569
        if (false == $correction) {
5570
            $userInfo = api_get_user_info($studentPublication->getUserId());
5571
            if ($userInfo) {
5572
                $date = api_get_local_time($studentPublication->getSentDate()->format('Y-m-d H:i:s'));
5573
                $date = str_replace([':', '-', ' '], '_', $date);
5574
                $title = $date.'_'.$userInfo['username'].'_'.$title;
5575
            }
5576
        }
5577
5578
        return [
5579
            //'path' => $full_file_name,
5580
            'title' => $title,
5581
            'title_correction' => $studentPublication->getTitleCorrection(),
5582
            'entity' => $studentPublication,
5583
        ];
5584
    }
5585
5586
    return false;
5587
}
5588
5589
/**
5590
 * @param int    $userId
5591
 * @param array  $courseInfo
5592
 * @param string $format
5593
 *
5594
 * @return bool
5595
 */
5596
function exportAllWork($userId, $courseInfo, $format = 'pdf')
5597
{
5598
    $userInfo = api_get_user_info($userId);
5599
    if (empty($userInfo) || empty($courseInfo)) {
5600
        return false;
5601
    }
5602
5603
    $workPerUser = getWorkPerUser($userId);
5604
5605
    switch ($format) {
5606
        case 'pdf':
5607
            if (!empty($workPerUser)) {
5608
                $pdf = new PDF();
5609
5610
                $content = null;
5611
                foreach ($workPerUser as $work) {
5612
                    $work = $work['work'];
5613
                    foreach ($work->user_results as $userResult) {
5614
                        $content .= $userResult['title'];
5615
                        // No need to use api_get_local_time()
5616
                        $content .= $userResult['sent_date'];
5617
                        $content .= $userResult['qualification'];
5618
                        $content .= $userResult['description'];
5619
                    }
5620
                }
5621
5622
                if (!empty($content)) {
5623
                    $pdf->content_to_pdf(
5624
                        $content,
5625
                        null,
5626
                        api_replace_dangerous_char($userInfo['complete_name']),
5627
                        $courseInfo['code']
5628
                    );
5629
                }
5630
            }
5631
5632
            break;
5633
    }
5634
}
5635
5636
/**
5637
 * @param int    $workId
5638
 * @param array  $courseInfo
5639
 * @param int    $sessionId
5640
 * @param string $format
5641
 *
5642
 * @return bool
5643
 */
5644
function exportAllStudentWorkFromPublication(
5645
    $workId,
5646
    $courseInfo,
5647
    $sessionId,
5648
    $format = 'pdf'
5649
) {
5650
    if (empty($courseInfo)) {
5651
        return false;
5652
    }
5653
5654
    $workData = get_work_data_by_id($workId);
5655
    if (empty($workData)) {
5656
        return false;
5657
    }
5658
5659
    $assignment = get_work_assignment_by_id($workId);
5660
5661
    $courseCode = $courseInfo['code'];
5662
    $header = get_lang('Course').': '.$courseInfo['title'];
5663
    $teachers = CourseManager::getTeacherListFromCourseCodeToString(
5664
        $courseCode
5665
    );
5666
5667
    if (!empty($sessionId)) {
5668
        $sessionInfo = api_get_session_info($sessionId);
5669
        if (!empty($sessionInfo)) {
5670
            $header .= ' - '.$sessionInfo['name'];
5671
            $header .= '<br />'.$sessionInfo['description'];
5672
            $teachers = SessionManager::getCoachesByCourseSessionToString(
5673
                $sessionId,
5674
                $courseInfo['real_id']
5675
            );
5676
        }
5677
    }
5678
5679
    $header .= '<br />'.get_lang('Trainers').': '.$teachers.'<br />';
5680
    $header .= '<br />'.get_lang('Date').': '.api_get_local_time().'<br />';
5681
    $header .= '<br />'.get_lang('Assignment name').': '.$workData['title'].'<br />';
5682
5683
    $content = null;
5684
    $expiresOn = null;
5685
5686
    if (!empty($assignment) && isset($assignment['expires_on'])) {
5687
        $content .= '<br /><strong>'.get_lang('Posted deadline for sending the work (Visible to the learner)').'</strong>: '.api_get_local_time($assignment['expires_on']);
5688
        $expiresOn = api_get_local_time($assignment['expires_on']);
5689
    }
5690
5691
    if (!empty($workData['description'])) {
5692
        $content .= '<br /><strong>'.get_lang('Description').'</strong>: '.$workData['description'];
5693
    }
5694
5695
    $workList = get_work_user_list(null, null, null, null, $workId);
5696
5697
    switch ($format) {
5698
        case 'pdf':
5699
            if (!empty($workList)) {
5700
                $table = new HTML_Table(['class' => 'data_table']);
5701
                $headers = [
5702
                    get_lang('Name'),
5703
                    get_lang('User'),
5704
                    get_lang('Deadline'),
5705
                    get_lang('Sent date'),
5706
                    get_lang('Filename'),
5707
                    get_lang('Score'),
5708
                    get_lang('Feedback'),
5709
                ];
5710
5711
                $column = 0;
5712
                foreach ($headers as $header) {
5713
                    $table->setHeaderContents(0, $column, $header);
5714
                    $column++;
5715
                }
5716
5717
                $row = 1;
5718
5719
                //$pdf->set_custom_header($header);
5720
                foreach ($workList as $work) {
5721
                    $content .= '<hr />';
5722
                    // getWorkComments need c_id
5723
                    $work['c_id'] = $courseInfo['real_id'];
5724
5725
                    //$content .= get_lang('Date').': '.api_get_local_time($work['sent_date_from_db']).'<br />';
5726
                    $score = null;
5727
                    if (!empty($work['qualification_only'])) {
5728
                        $score = $work['qualification_only'];
5729
                    }
5730
5731
                    $comments = getWorkComments($work);
5732
5733
                    $feedback = null;
5734
                    if (!empty($comments)) {
5735
                        $content .= '<h4>'.get_lang('Feedback').': </h4>';
5736
                        foreach ($comments as $comment) {
5737
                            $feedback .= get_lang('User').': '.$comment['complete_name'].
5738
                                '<br />';
5739
                            $feedback .= $comment['comment'].'<br />';
5740
                        }
5741
                    }
5742
                    $table->setCellContents($row, 0, strip_tags($workData['title']));
5743
                    $table->setCellContents($row, 1, strip_tags($work['fullname']));
5744
                    $table->setCellContents($row, 2, $expiresOn);
5745
                    $table->setCellContents($row, 3, api_get_local_time($work['sent_date_from_db']));
5746
                    $table->setCellContents($row, 4, strip_tags($work['title']));
5747
                    $table->setCellContents($row, 5, $score);
5748
                    $table->setCellContents($row, 6, $feedback);
5749
5750
                    $row++;
5751
                }
5752
5753
                $content = $table->toHtml();
5754
5755
                if (!empty($content)) {
5756
                    $params = [
5757
                        'filename' => $workData['title'].'_'.api_get_local_time(),
5758
                        'pdf_title' => api_replace_dangerous_char($workData['title']),
5759
                        'course_code' => $courseInfo['code'],
5760
                    ];
5761
                    $pdf = new PDF('A4', null, $params);
5762
                    $pdf->html_to_pdf_with_template($content);
5763
                }
5764
                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...
5765
            }
5766
5767
            break;
5768
    }
5769
}
5770
5771
/**
5772
 * Downloads all user files per user.
5773
 *
5774
 * @param int   $userId
5775
 * @param array $courseInfo
5776
 *
5777
 * @return bool
5778
 */
5779
function downloadAllFilesPerUser($userId, $courseInfo)
5780
{
5781
    throw new Exception('downloadAllFilesPerUser');
5782
    /*
5783
    $userInfo = api_get_user_info($userId);
5784
5785
    if (empty($userInfo) || empty($courseInfo)) {
5786
        return false;
5787
    }
5788
5789
    $tempZipFile = api_get_path(SYS_ARCHIVE_PATH).api_get_unique_id().'.zip';
5790
    $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/work/';
5791
    $zip = new PclZip($tempZipFile);
5792
    $workPerUser = getWorkPerUser($userId);
5793
5794
    if (!empty($workPerUser)) {
5795
        $files = [];
5796
        foreach ($workPerUser as $work) {
5797
            $work = $work['work'];
5798
            foreach ($work->user_results as $userResult) {
5799
                if (empty($userResult['url']) || empty($userResult['contains_file'])) {
5800
                    continue;
5801
                }
5802
                $data = getFileContents($userResult['iid'], $courseInfo);
5803
                if (!empty($data) && isset($data['path'])) {
5804
                    $files[basename($data['path'])] = [
5805
                        'title' => $data['title'],
5806
                        'path' => $data['path'],
5807
                    ];
5808
                }
5809
            }
5810
        }
5811
5812
        if (!empty($files)) {
5813
            Session::write('files', $files);
5814
            foreach ($files as $data) {
5815
                $zip->add(
5816
                    $data['path'],
5817
                    PCLZIP_OPT_REMOVE_PATH,
5818
                    $coursePath,
5819
                    PCLZIP_CB_PRE_ADD,
5820
                    'preAddAllWorkStudentCallback'
5821
                );
5822
            }
5823
        }
5824
5825
        // Start download of created file
5826
        $name = basename(api_replace_dangerous_char($userInfo['complete_name'])).'.zip';
5827
        Event::event_download($name.'.zip (folder)');
5828
        if (Security::check_abs_path($tempZipFile, api_get_path(SYS_ARCHIVE_PATH))) {
5829
            DocumentManager::file_send_for_download($tempZipFile, true, $name);
5830
            @unlink($tempZipFile);
5831
            exit;
5832
        }
5833
    }
5834
    exit;*/
5835
}
5836
5837
/**
5838
 * @param $p_event
5839
 * @param array $p_header
5840
 *
5841
 * @return int
5842
 */
5843
function preAddAllWorkStudentCallback($p_event, &$p_header)
5844
{
5845
    $files = Session::read('files');
5846
    if (isset($files[basename($p_header['stored_filename'])])) {
5847
        $p_header['stored_filename'] = $files[basename($p_header['stored_filename'])]['title'];
5848
5849
        return 1;
5850
    }
5851
5852
    return 0;
5853
}
5854
5855
/**
5856
 * Get all work created by a user.
5857
 *
5858
 * @param int $user_id
5859
 * @param int $courseId
5860
 * @param int $sessionId
5861
 *
5862
 * @return array
5863
 */
5864
function getWorkCreatedByUser($user_id, $courseId, $sessionId)
5865
{
5866
    $items = api_get_item_property_list_by_tool_by_user(
5867
        $user_id,
5868
        'work',
5869
        $courseId,
5870
        $sessionId
5871
    );
5872
5873
    $list = [];
5874
    if (!empty($items)) {
5875
        foreach ($items as $work) {
5876
            $item = get_work_data_by_id(
5877
                $work['ref'],
5878
                $courseId,
5879
                $sessionId
5880
            );
5881
            if (!empty($item)) {
5882
                $list[] = [
5883
                    $item['title'],
5884
                    api_get_local_time($work['insert_date']),
5885
                    api_get_local_time($work['lastedit_date']),
5886
                ];
5887
            }
5888
        }
5889
    }
5890
5891
    return $list;
5892
}
5893
5894
/**
5895
 * @param array $courseInfo
5896
 * @param int   $workId
5897
 *
5898
 * @return bool
5899
 */
5900
function protectWork($courseInfo, $workId)
5901
{
5902
    $userId = api_get_user_id();
5903
    $groupId = api_get_group_id();
5904
    $sessionId = api_get_session_id();
5905
    $workData = get_work_data_by_id($workId);
5906
5907
    if (empty($workData) || empty($courseInfo)) {
5908
        api_not_allowed(true);
5909
    }
5910
5911
    if (api_is_platform_admin() || api_is_allowed_to_edit()) {
5912
        return true;
5913
    }
5914
5915
    $workId = $workData['iid'];
5916
5917
    if (1 != $workData['active']) {
5918
        api_not_allowed(true);
5919
    }
5920
5921
    /*$visibility = api_get_item_visibility($courseInfo, 'work', $workId, $sessionId);
5922
    if ($visibility != 1) {
5923
        api_not_allowed(true);
5924
    }*/
5925
5926
    $isAllow = allowOnlySubscribedUser($userId, $workId, $courseInfo['real_id']);
5927
    if (empty($isAllow)) {
5928
        api_not_allowed(true);
5929
    }
5930
5931
    $groupInfo = GroupManager::get_group_properties($groupId);
5932
5933
    if (!empty($groupId)) {
5934
        $showWork = GroupManager::user_has_access(
5935
            $userId,
5936
            $groupInfo['iid'],
5937
            GroupManager::GROUP_TOOL_WORK
5938
        );
5939
        if (!$showWork) {
5940
            api_not_allowed(true);
5941
        }
5942
    }
5943
}
5944
5945
/**
5946
 * @param array $courseInfo
5947
 * @param array $work
5948
 */
5949
function deleteCorrection($courseInfo, $work)
5950
{
5951
    throw new Exception('deleteCorrection');
5952
    /*
5953
    if (isset($work['url_correction']) && !empty($work['url_correction']) && isset($work['iid'])) {
5954
        $id = $work['iid'];
5955
        $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
5956
        $sql = "UPDATE $table SET
5957
                    url_correction = '',
5958
                    title_correction = ''
5959
                WHERE iid = $id";
5960
        Database::query($sql);
5961
        $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/';
5962
        if (file_exists($coursePath.$work['url_correction'])) {
5963
            if (Security::check_abs_path($coursePath.$work['url_correction'], $coursePath)) {
5964
                unlink($coursePath.$work['url_correction']);
5965
            }
5966
        }
5967
    }*/
5968
}
5969
5970
/**
5971
 * @param int $workId
5972
 *
5973
 * @return string
5974
 */
5975
function workGetExtraFieldData($workId)
5976
{
5977
    $sessionField = new ExtraField('work');
5978
    $extraFieldData = $sessionField->getDataAndFormattedValues($workId);
5979
    $result = '';
5980
    if (!empty($extraFieldData)) {
5981
        $result .= '<div class="well">';
5982
        foreach ($extraFieldData as $data) {
5983
            $result .= $data['text'].': <b>'.$data['value'].'</b>';
5984
        }
5985
        $result .= '</div>';
5986
    }
5987
5988
    return $result;
5989
}
5990