Passed
Push — master ( 8ac4a8...f1b610 )
by Julito
11:04
created

getAllWork()   F

Complexity

Conditions 63
Paths > 20000

Size

Total Lines 507
Code Lines 260

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 63
eloc 260
c 2
b 0
f 0
nc 311470177
nop 8
dl 0
loc 507
rs 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

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

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

Loading history...
5972
    if (!empty($file) && isset($file['entity'])) {
0 ignored issues
show
Unused Code introduced by
IfNode is not reachable.

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

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

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

    return false;
}

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

Loading history...
5973
        /** @var CStudentPublication $studentPublication */
5974
        $studentPublication = $file['entity'];
5975
    }
5976
5977
    return false;
5978
}
5979
5980
/**
5981
 * Get the file contents for an assigment.
5982
 *
5983
 * @param int   $id
5984
 * @param array $courseInfo
5985
 * @param int   $sessionId
5986
 * @param bool  $correction
5987
 * @param bool  $forceAccessForCourseAdmins
5988
 *
5989
 * @return array|bool
5990
 */
5991
function getFileContents($id, $courseInfo, $sessionId = 0, $correction = false, $forceAccessForCourseAdmins = false)
5992
{
5993
    $id = (int) $id;
5994
5995
    if (empty($courseInfo) || empty($id)) {
5996
        return false;
5997
    }
5998
    if (empty($sessionId)) {
5999
        $sessionId = api_get_session_id();
6000
    }
6001
6002
    $courseEntity = api_get_course_entity($courseInfo['real_id']);
6003
    $sessionEntity = api_get_session_entity($sessionId);
6004
6005
    $repo = Container::getStudentPublicationRepository();
6006
    /** @var CStudentPublication $studentPublication */
6007
    $studentPublication = $repo->find($id);
6008
6009
    if (empty($studentPublication)) {
6010
        return false;
6011
    }
6012
6013
    if ($correction) {
6014
        //$row['url'] = $row['url_correction'];
6015
    }
6016
    $hasFile = $studentPublication->getResourceNode()->hasResourceFile();
6017
    if (!$hasFile) {
6018
        return false;
6019
    }
6020
6021
    /*
6022
    $item_info = api_get_item_property_info(
6023
        api_get_course_int_id(),
6024
        'work',
6025
        $row['iid'],
6026
        $sessionId
6027
    );
6028
6029
    if (empty($item_info)) {
6030
        return false;
6031
    }*/
6032
6033
    $isAllow = allowOnlySubscribedUser(
6034
        api_get_user_id(),
6035
        $studentPublication->getParentId(),
6036
        $courseInfo['real_id'],
6037
        $forceAccessForCourseAdmins
6038
    );
6039
6040
    if (empty($isAllow)) {
6041
        return false;
6042
    }
6043
6044
    /*
6045
    field show_score in table course :
6046
        0 =>    New documents are visible for all users
6047
        1 =>    New documents are only visible for the teacher(s)
6048
    field visibility in table item_property :
6049
        0 => eye closed, invisible for all students
6050
        1 => eye open
6051
    field accepted in table c_student_publication :
6052
        0 => eye closed, invisible for all students
6053
        1 => eye open
6054
    ( We should have visibility == accepted, otherwise there is an
6055
    inconsistency in the Database)
6056
    field value in table c_course_setting :
6057
        0 => Allow learners to delete their own publications = NO
6058
        1 => Allow learners to delete their own publications = YES
6059
6060
    +------------------+-------------------------+------------------------+
6061
    |Can download work?| doc visible for all = 0 | doc visible for all = 1|
6062
    +------------------+-------------------------+------------------------+
6063
    |  visibility = 0  | editor only             | editor only            |
6064
    |                  |                         |                        |
6065
    +------------------+-------------------------+------------------------+
6066
    |  visibility = 1  | editor                  | editor                 |
6067
    |                  | + owner of the work     | + any student          |
6068
    +------------------+-------------------------+------------------------+
6069
    (editor = teacher + admin + anybody with right api_is_allowed_to_edit)
6070
    */
6071
6072
    $work_is_visible = $studentPublication->isVisible($courseEntity, $sessionEntity) && $studentPublication->getAccepted();
6073
    $doc_visible_for_all = 0 === (int) $courseInfo['show_score'];
6074
6075
    $is_editor = api_is_allowed_to_edit(true, true, true);
6076
    $student_is_owner_of_work = user_is_author($studentPublication->getIid(), api_get_user_id());
6077
6078
    if (($forceAccessForCourseAdmins && $isAllow) ||
6079
        $is_editor ||
6080
        $student_is_owner_of_work ||
6081
        ($doc_visible_for_all && $work_is_visible)
6082
    ) {
6083
        $title = $studentPublication->getTitle();
6084
        $titleCorrection = '';
6085
        if ($correction && $studentPublication->getCorrection()) {
6086
            $title = $titleCorrection = $studentPublication->getCorrection()->getTitle();
6087
        }
6088
        if ($hasFile) {
6089
            $title = $studentPublication->getResourceNode()->getResourceFile()->getName();
6090
        }
6091
6092
        $title = str_replace(' ', '_', $title);
6093
6094
        if (false == $correction) {
6095
            $userInfo = api_get_user_info($studentPublication->getUserId());
6096
            if ($userInfo) {
6097
                $date = api_get_local_time($studentPublication->getSentDate()->format('Y-m-d H:i:s'));
6098
                $date = str_replace([':', '-', ' '], '_', $date);
6099
                $title = $date.'_'.$userInfo['username'].'_'.$title;
6100
            }
6101
        }
6102
6103
        return [
6104
            //'path' => $full_file_name,
6105
            'title' => $title,
6106
            'title_correction' => $titleCorrection,
6107
            'entity' => $studentPublication,
6108
        ];
6109
    }
6110
6111
    return false;
6112
}
6113
6114
/**
6115
 * @param int    $userId
6116
 * @param array  $courseInfo
6117
 * @param string $format
6118
 *
6119
 * @return bool
6120
 */
6121
function exportAllWork($userId, $courseInfo, $format = 'pdf')
6122
{
6123
    $userInfo = api_get_user_info($userId);
6124
    if (empty($userInfo) || empty($courseInfo)) {
6125
        return false;
6126
    }
6127
6128
    $workPerUser = getWorkPerUser($userId);
6129
6130
    switch ($format) {
6131
        case 'pdf':
6132
            if (!empty($workPerUser)) {
6133
                $pdf = new PDF();
6134
6135
                $content = null;
6136
                foreach ($workPerUser as $work) {
6137
                    $work = $work['work'];
6138
                    foreach ($work->user_results as $userResult) {
6139
                        $content .= $userResult['title'];
6140
                        // No need to use api_get_local_time()
6141
                        $content .= $userResult['sent_date'];
6142
                        $content .= $userResult['qualification'];
6143
                        $content .= $userResult['description'];
6144
                    }
6145
                }
6146
6147
                if (!empty($content)) {
6148
                    $pdf->content_to_pdf(
6149
                        $content,
6150
                        null,
6151
                        api_replace_dangerous_char($userInfo['complete_name']),
6152
                        $courseInfo['code']
6153
                    );
6154
                }
6155
            }
6156
6157
            break;
6158
    }
6159
}
6160
6161
/**
6162
 * @param int    $workId
6163
 * @param array  $courseInfo
6164
 * @param int    $sessionId
6165
 * @param string $format
6166
 *
6167
 * @return bool
6168
 */
6169
function exportAllStudentWorkFromPublication(
6170
    $workId,
6171
    $courseInfo,
6172
    $sessionId,
6173
    $format = 'pdf'
6174
) {
6175
    if (empty($courseInfo)) {
6176
        return false;
6177
    }
6178
6179
    $workData = get_work_data_by_id($workId);
6180
    if (empty($workData)) {
6181
        return false;
6182
    }
6183
6184
    $assignment = get_work_assignment_by_id($workId);
6185
    $courseCode = $courseInfo['code'];
6186
    $header = get_lang('Course').': '.$courseInfo['title'];
6187
    $teachers = CourseManager::getTeacherListFromCourseCodeToString($courseCode);
6188
6189
    if (!empty($sessionId)) {
6190
        $sessionInfo = api_get_session_info($sessionId);
6191
        if (!empty($sessionInfo)) {
6192
            $header .= ' - '.$sessionInfo['name'];
6193
            $header .= '<br />'.$sessionInfo['description'];
6194
            $teachers = SessionManager::getCoachesByCourseSessionToString(
6195
                $sessionId,
6196
                $courseInfo['real_id']
6197
            );
6198
        }
6199
    }
6200
6201
    $header .= '<br />'.get_lang('Trainers').': '.$teachers.'<br />';
6202
    $header .= '<br />'.get_lang('Date').': '.api_get_local_time().'<br />';
6203
    $header .= '<br />'.get_lang('Assignment name').': '.$workData['title'].'<br />';
6204
6205
    $content = null;
6206
    $expiresOn = null;
6207
    if (!empty($assignment) && isset($assignment['expires_on'])) {
6208
        $content .= '<br /><strong>'.
6209
            get_lang('Posted deadline for sending the work (Visible to the learner)').'</strong>: '.
6210
            api_get_local_time($assignment['expires_on']);
6211
        $expiresOn = api_get_local_time($assignment['expires_on']);
6212
    }
6213
6214
    if (!empty($workData['description'])) {
6215
        $content .= '<br /><strong>'.get_lang('Description').'</strong>: '.$workData['description'];
6216
    }
6217
6218
    $workList = get_work_user_list(null, null, null, null, $workId);
6219
6220
    switch ($format) {
6221
        case 'pdf':
6222
            if (!empty($workList)) {
6223
                $table = new HTML_Table(['class' => 'data_table']);
6224
                $headers = [
6225
                    get_lang('Name'),
6226
                    get_lang('User'),
6227
                    get_lang('Deadline'),
6228
                    get_lang('Sent date'),
6229
                    get_lang('Filename'),
6230
                    get_lang('Score'),
6231
                    get_lang('Feedback'),
6232
                ];
6233
6234
                $column = 0;
6235
                foreach ($headers as $header) {
6236
                    $table->setHeaderContents(0, $column, $header);
6237
                    $column++;
6238
                }
6239
6240
                $row = 1;
6241
                //$pdf->set_custom_header($header);
6242
                /** @var array $work */
6243
                foreach ($workList as $work) {
6244
                    $content .= '<hr />';
6245
                    // getWorkComments need c_id
6246
                    $work['c_id'] = $courseInfo['real_id'];
6247
                    //$content .= get_lang('Date').': '.api_get_local_time($work['sent_date_from_db']).'<br />';
6248
                    $score = null;
6249
                    if (!empty($work['qualification_only'])) {
6250
                        $score = $work['qualification_only'];
6251
                    }
6252
6253
                    $comments = getWorkComments($work);
6254
                    $feedback = null;
6255
                    if (!empty($comments)) {
6256
                        $content .= '<h4>'.get_lang('Feedback').': </h4>';
6257
                        foreach ($comments as $comment) {
6258
                            $feedback .= get_lang('User').': '.$comment['complete_name'].'<br />';
6259
                            $feedback .= $comment['comment'].'<br />';
6260
                        }
6261
                    }
6262
                    $table->setCellContents($row, 0, strip_tags($workData['title']));
6263
                    $table->setCellContents($row, 1, strip_tags($work['fullname']));
6264
                    $table->setCellContents($row, 2, $expiresOn);
6265
                    $table->setCellContents($row, 3, api_get_local_time($work['sent_date_from_db']));
6266
                    $table->setCellContents($row, 4, strip_tags($work['title']));
6267
                    $table->setCellContents($row, 5, $score);
6268
                    $table->setCellContents($row, 6, $feedback);
6269
                    $row++;
6270
                }
6271
6272
                $content = $table->toHtml();
6273
                if (!empty($content)) {
6274
                    $params = [
6275
                        'filename' => $workData['title'].'_'.api_get_local_time(),
6276
                        'pdf_title' => api_replace_dangerous_char($workData['title']),
6277
                        'course_code' => $courseInfo['code'],
6278
                    ];
6279
                    $pdf = new PDF('A4', null, $params);
6280
                    $pdf->html_to_pdf_with_template($content);
6281
                }
6282
                exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

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

Loading history...
6283
            }
6284
6285
            break;
6286
    }
6287
}
6288
6289
/**
6290
 * Downloads all user files per user.
6291
 *
6292
 * @param int   $userId
6293
 * @param array $courseInfo
6294
 *
6295
 * @return bool
6296
 */
6297
function downloadAllFilesPerUser($userId, $courseInfo)
6298
{
6299
    throw new Exception('downloadAllFilesPerUser');
6300
    /*
6301
    $userInfo = api_get_user_info($userId);
6302
6303
    if (empty($userInfo) || empty($courseInfo)) {
6304
        return false;
6305
    }
6306
6307
    $tempZipFile = api_get_path(SYS_ARCHIVE_PATH).api_get_unique_id().'.zip';
6308
    $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/work/';
6309
    $zip = new PclZip($tempZipFile);
6310
    $workPerUser = getWorkPerUser($userId);
6311
6312
    if (!empty($workPerUser)) {
6313
        $files = [];
6314
        foreach ($workPerUser as $work) {
6315
            $work = $work['work'];
6316
            foreach ($work->user_results as $userResult) {
6317
                if (empty($userResult['url']) || empty($userResult['contains_file'])) {
6318
                    continue;
6319
                }
6320
                $data = getFileContents($userResult['iid'], $courseInfo);
6321
                if (!empty($data) && isset($data['path'])) {
6322
                    $files[basename($data['path'])] = [
6323
                        'title' => $data['title'],
6324
                        'path' => $data['path'],
6325
                    ];
6326
                }
6327
            }
6328
        }
6329
6330
        if (!empty($files)) {
6331
            Session::write('files', $files);
6332
            foreach ($files as $data) {
6333
                $zip->add(
6334
                    $data['path'],
6335
                    PCLZIP_OPT_REMOVE_PATH,
6336
                    $coursePath,
6337
                    PCLZIP_CB_PRE_ADD,
6338
                    'preAddAllWorkStudentCallback'
6339
                );
6340
            }
6341
        }
6342
6343
        // Start download of created file
6344
        $name = basename(api_replace_dangerous_char($userInfo['complete_name'])).'.zip';
6345
        Event::event_download($name.'.zip (folder)');
6346
        if (Security::check_abs_path($tempZipFile, api_get_path(SYS_ARCHIVE_PATH))) {
6347
            DocumentManager::file_send_for_download($tempZipFile, true, $name);
6348
            @unlink($tempZipFile);
6349
            exit;
6350
        }
6351
    }
6352
    exit;*/
6353
}
6354
6355
/**
6356
 * @param $p_event
6357
 * @param array $p_header
6358
 *
6359
 * @return int
6360
 */
6361
function preAddAllWorkStudentCallback($p_event, &$p_header)
6362
{
6363
    $files = Session::read('files');
6364
    if (isset($files[basename($p_header['stored_filename'])])) {
6365
        $p_header['stored_filename'] = $files[basename($p_header['stored_filename'])]['title'];
6366
6367
        return 1;
6368
    }
6369
6370
    return 0;
6371
}
6372
6373
/**
6374
 * Get all work created by a user.
6375
 *
6376
 * @param int $userId
6377
 * @param int $courseId
6378
 * @param int $sessionId
6379
 *
6380
 * @return array
6381
 */
6382
function getWorkCreatedByUser($userId, $courseId, $sessionId)
6383
{
6384
    $repo = Container::getStudentPublicationRepository();
6385
6386
    $courseEntity = api_get_course_entity($courseId);
6387
    $sessionEntity = api_get_session_entity($sessionId);
6388
6389
    $qb = $repo->getResourcesByCourse($courseEntity, $sessionEntity);
6390
6391
    $qb->andWhere('node.creator = :creator');
6392
    $qb->setParameter('creator', $userId);
6393
    $items = $qb->getQuery()->getResult();
6394
6395
    $list = [];
6396
    if (!empty($items)) {
6397
        /** @var CStudentPublication $work */
6398
        foreach ($items as $work) {
6399
            $list[] = [
6400
                $work->getTitle(),
6401
                api_get_local_time($work->getResourceNode()->getCreatedAt()),
6402
                api_get_local_time($work->getResourceNode()->getUpdatedAt()),
6403
            ];
6404
        }
6405
    }
6406
6407
    return $list;
6408
}
6409
6410
/**
6411
 * @param array $courseInfo
6412
 * @param int   $workId
6413
 *
6414
 * @return bool
6415
 */
6416
function protectWork($courseInfo, $workId)
6417
{
6418
    $userId = api_get_user_id();
6419
    $groupId = api_get_group_id();
6420
    $sessionId = api_get_session_id();
6421
    $workData = get_work_data_by_id($workId);
6422
6423
    if (empty($workData) || empty($courseInfo)) {
6424
        api_not_allowed(true);
6425
    }
6426
6427
    if (api_is_platform_admin() || api_is_allowed_to_edit()) {
6428
        return true;
6429
    }
6430
6431
    $workId = $workData['iid'];
6432
6433
    if (1 != $workData['active']) {
6434
        api_not_allowed(true);
6435
    }
6436
6437
    /*$visibility = api_get_item_visibility($courseInfo, 'work', $workId, $sessionId);
6438
    if ($visibility != 1) {
6439
        api_not_allowed(true);
6440
    }*/
6441
6442
    $isAllow = allowOnlySubscribedUser($userId, $workId, $courseInfo['real_id']);
6443
    if (empty($isAllow)) {
6444
        api_not_allowed(true);
6445
    }
6446
6447
    $groupInfo = GroupManager::get_group_properties($groupId);
6448
6449
    if (!empty($groupId)) {
6450
        $showWork = GroupManager::user_has_access(
6451
            $userId,
6452
            $groupInfo['iid'],
6453
            GroupManager::GROUP_TOOL_WORK
6454
        );
6455
        if (!$showWork) {
6456
            api_not_allowed(true);
6457
        }
6458
    }
6459
}
6460
6461
function deleteCorrection(CStudentPublication $work)
6462
{
6463
    $correctionNode = $work->getCorrection();
6464
    if (null !== $correctionNode) {
6465
        $em = Database::getManager();
6466
        $em->remove($correctionNode);
6467
        $em->flush();
6468
    }
6469
}
6470
6471
/**
6472
 * @param int $workId
6473
 *
6474
 * @return string
6475
 */
6476
function workGetExtraFieldData($workId)
6477
{
6478
    $sessionField = new ExtraField('work');
6479
    $extraFieldData = $sessionField->getDataAndFormattedValues($workId);
6480
    $result = '';
6481
    if (!empty($extraFieldData)) {
6482
        $result .= '<div class="well">';
6483
        foreach ($extraFieldData as $data) {
6484
            $result .= $data['text'].': <b>'.$data['value'].'</b>';
6485
        }
6486
        $result .= '</div>';
6487
    }
6488
6489
    return $result;
6490
}
6491