Passed
Push — master ( 4c4023...2b0e92 )
by Julito
07:08
created

get_work_id()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 38
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 23
nc 4
nop 1
dl 0
loc 38
rs 9.552
c 0
b 0
f 0
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' ";
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 (null === $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'] = $router->generate(
135
            'chamilo_core_resource_download',
136
            [
137
                'id' => $studentPublication->getResourceNode()->getId(),
138
                'tool' => 'student_publication',
139
                'type' => 'student_publications',
140
            ]
141
        );
142
143
        $work['active'] = $studentPublication->getActive();
144
        $work['allow_text_assignment'] = $studentPublication->getAllowTextAssignment();
145
        //$work['c_id'] = $studentPublication->getCId();
146
        $work['user_id'] = $studentPublication->getUser()->getId();
147
        $work['parent_id'] = 0;
148
        if (null !== $studentPublication->getPublicationParent()) {
149
            $work['parent_id'] = $studentPublication->getPublicationParent()->getIid();
150
        }
151
152
        $work['qualification'] = $studentPublication->getQualification();
153
        $work['contains_file'] = $studentPublication->getContainsFile();
154
        $work['title'] = $studentPublication->getTitle();
155
        $url = $router->generate(
156
            'chamilo_core_resource_download',
157
            [
158
                'id' => $studentPublication->getResourceNode()->getId(),
159
                'tool' => 'student_publication',
160
                'type' => 'student_publications',
161
            ]
162
        );
163
        $work['download_url'] = $url.'?'.api_get_cidreq();
164
        $work['view_url'] = $webCodePath.'work/view.php?id='.$workId.'&'.api_get_cidreq();
165
        $showUrl = $work['show_url'] = $webCodePath.'work/show_file.php?id='.$workId.'&'.api_get_cidreq();
166
        $work['show_content'] = '';
167
        if ($studentPublication->getContainsFile()) {
168
            $fileType = '';
169
            if (in_array($fileType, ['image/jpeg', 'image/jpg', 'image/png', 'image/gif'])) {
170
                $work['show_content'] = Display::img($showUrl, $studentPublication->getTitle(), null, false);
171
            } elseif (false !== strpos($fileType, 'video/')) {
172
                $work['show_content'] = Display::tag(
173
                    'video',
174
                    get_lang('File format not supported'),
175
                    ['src' => $showUrl]
176
                );
177
            }
178
        }
179
180
        $fieldValue = new ExtraFieldValue('work');
181
        $work['extra'] = $fieldValue->getAllValuesForAnItem($id, true);
182
    }
183
184
    return $work;
185
}
186
187
/**
188
 * @param int $user_id
189
 * @param int $work_id
190
 *
191
 * @return int
192
 */
193
function get_work_count_by_student($user_id, $work_id)
194
{
195
    $user_id = (int) $user_id;
196
    $work_id = (int) $work_id;
197
    $course_id = api_get_course_int_id();
198
    $session_id = api_get_session_id();
199
    $sessionCondition = api_get_session_condition($session_id);
200
201
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
202
    $sql = "SELECT COUNT(*) as count
203
            FROM  $table
204
            WHERE
205
                parent_id = $work_id AND
206
                user_id = $user_id AND
207
                active IN (0, 1)
208
                $sessionCondition";
209
    $result = Database::query($sql);
210
    $return = 0;
211
    if (Database::num_rows($result)) {
212
        $return = Database::fetch_row($result, 'ASSOC');
213
        $return = (int) ($return[0]);
214
    }
215
216
    return $return;
217
}
218
219
/**
220
 * @param int $id
221
 * @param int $courseId
222
 *
223
 * @return array
224
 */
225
function get_work_assignment_by_id($id, $courseId = 0)
226
{
227
    $courseId = (int) $courseId;
228
    if (empty($courseId)) {
229
        $courseId = api_get_course_int_id();
230
    }
231
    $id = (int) $id;
232
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
233
    $sql = "SELECT * FROM $table
234
            WHERE publication_id = $id";
235
    $result = Database::query($sql);
236
    $return = [];
237
    if (Database::num_rows($result)) {
238
        $return = Database::fetch_array($result, 'ASSOC');
239
    }
240
241
    return $return;
242
}
243
244
/**
245
 * @param int    $id
246
 * @param array  $my_folder_data
247
 * @param string $add_in_where_query
248
 * @param int    $course_id
249
 * @param int    $session_id
250
 *
251
 * @return CStudentPublication[]
252
 */
253
function getWorkList($id, $my_folder_data, $add_in_where_query = null, $course_id = 0, $session_id = 0)
254
{
255
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
256
257
    $course_id = $course_id ?: api_get_course_int_id();
258
    $session_id = $session_id ?: api_get_session_id();
259
    $condition_session = api_get_session_condition($session_id);
260
    $group_id = api_get_group_id();
261
262
    $groupIid = 0;
263
    if ($group_id) {
264
        $groupInfo = GroupManager::get_group_properties($group_id);
265
        if ($groupInfo) {
266
            $groupIid = $groupInfo['iid'];
267
        }
268
    }
269
270
    $is_allowed_to_edit = api_is_allowed_to_edit(null, true);
271
    $linkInfo = GradebookUtils::isResourceInCourseGradebook(
272
        api_get_course_id(),
273
        3,
274
        $id,
275
        api_get_session_id()
276
    );
277
278
    if ($linkInfo) {
279
        $workInGradeBookLinkId = $linkInfo['id'];
280
        if ($workInGradeBookLinkId && $is_allowed_to_edit) {
281
            if (0 == (int) ($my_folder_data['qualification'])) {
282
                echo Display::return_message(
283
                    get_lang('Max weight need to be provided'),
284
                    'warning'
285
                );
286
            }
287
        }
288
    }
289
290
    $repo = Container::getStudentPublicationRepository();
291
    $course = api_get_course_entity($course_id);
292
    $session = api_get_session_entity($session_id);
293
    $group = api_get_group_entity($group_id);
294
295
    $qb = $repo->getResourcesByCourse($course, $session, $group);
296
297
    $contains_file_query = '';
298
    // Get list from database
299
    if ($is_allowed_to_edit) {
300
        $qb->andWhere($qb->expr()->in('resource.active', [1, 0]));
301
        $qb->andWhere($qb->expr()->isNull('resource.publicationParent'));
302
        /*$active_condition = ' active IN (0, 1)';
303
        $sql = "SELECT * FROM $work_table
304
                WHERE
305
                    c_id = $course_id
306
                    $add_in_where_query
307
                    $condition_session AND
308
                    $active_condition AND
309
                    (parent_id = 0)
310
                    $contains_file_query AND
311
                    post_group_id = $groupIid
312
                ORDER BY sent_date DESC";*/
313
    } else {
314
        if (!empty($group_id)) {
315
            // set to select only messages posted by the user's group
316
            $group_query = " WHERE c_id = $course_id AND post_group_id = $groupIid";
317
            $subdirs_query = ' AND parent_id = 0';
318
        } else {
319
            $group_query = " WHERE c_id = $course_id AND (post_group_id = '0' OR post_group_id is NULL) ";
320
            $subdirs_query = ' AND parent_id = 0';
321
        }
322
        //@todo how we can active or not an assignment?
323
        $active_condition = ' AND active IN (1, 0)';
324
        $sql = "SELECT * FROM  $work_table
325
                $group_query
326
                $subdirs_query
327
                $add_in_where_query
328
                $active_condition
329
                $condition_session
330
                ORDER BY title";
331
    }
332
333
    return $qb->getQuery()->getResult();
334
335
    $work_parents = [];
0 ignored issues
show
Unused Code introduced by
$work_parents = array() is not reachable.

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

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

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

    return false;
}

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

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