Issues (1784)

public/main/work/work.lib.php (6 issues)

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