Passed
Push — master ( cc68cc...50453a )
by Julito
09:11
created

public/main/admin/course_list_admin.php (1 issue)

Severity
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
/**
6
 * This script shows a list of courses and allows searching for courses codes
7
 * and names.
8
 */
9
$cidReset = true;
10
require_once __DIR__.'/../inc/global.inc.php';
11
$this_section = SECTION_PLATFORM_ADMIN;
12
api_protect_admin_script();
13
$sessionId = isset($_GET['session_id']) ? $_GET['session_id'] : null;
14
$addTeacherColumn = true;
15
16
/**
17
 * Get the number of courses which will be displayed.
18
 *
19
 * @throws Exception
20
 *
21
 * @return int The number of matching courses
22
 */
23
function get_number_of_courses()
24
{
25
    return get_course_data(0, 0, 0, 0, null, true);
26
}
27
28
/**
29
 * Get course data to display.
30
 *
31
 * @param int    $from
32
 * @param int    $number_of_items
33
 * @param int    $column
34
 * @param string $direction
35
 *
36
 * @throws Exception
37
 *
38
 * @return array
39
 */
40
function get_course_data($from, $number_of_items, $column, $direction, $dataFunctions = [], $getCount = false)
41
{
42
    $addTeacherColumn = true;
43
    $table = Database::get_main_table(TABLE_MAIN_COURSE);
44
45
    $teachers = '';
46
    if ($addTeacherColumn) {
47
        $teachers = " GROUP_CONCAT(cu.user_id SEPARATOR ',') as col4, ";
48
    }
49
    $select = "SELECT
50
                code AS col0,
51
                title AS col1,
52
                creation_date AS col2,
53
                $teachers
54
                visibility,
55
                directory,
56
                visual_code,
57
                course.code,
58
                course.id ";
59
60
    if ($getCount) {
61
        $select = 'SELECT COUNT(DISTINCT(course.id)) as count ';
62
    }
63
64
    $sql = "$select FROM $table course";
65
    if (api_is_multiple_url_enabled()) {
66
        $access_url_rel_course_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
67
        $sql .= " INNER JOIN $access_url_rel_course_table url_rel_course
68
                  ON (course.id = url_rel_course.c_id)";
69
    }
70
71
    $tableCourseRelUser = Database::get_main_table(TABLE_MAIN_COURSE_USER);
72
    $sql .= "
73
            LEFT JOIN $tableCourseRelUser cu
74
            ON (course.id = cu.c_id AND cu.status = ".COURSEMANAGER.")
75
        ";
76
77
    $sql .= ' WHERE 1=1 ';
78
    if (isset($_GET['keyword'])) {
79
        $keyword = Database::escape_string("%".trim($_GET['keyword'])."%");
80
        $sql .= " AND  (
81
            title LIKE '".$keyword."' OR
82
            code LIKE '".$keyword."' OR
83
            visual_code LIKE '".$keyword."'
84
        )
85
        ";
86
    } elseif (isset($_GET['keyword_code'])) {
87
        $keyword_code = Database::escape_string("%".$_GET['keyword_code']."%");
88
        $keyword_title = Database::escape_string("%".$_GET['keyword_title']."%");
89
        $keyword_category = isset($_GET['keyword_category'])
90
            ? Database::escape_string("%".$_GET['keyword_category']."%")
91
            : null;
92
        $keyword_language = Database::escape_string("%".$_GET['keyword_language']."%");
93
        $keyword_visibility = Database::escape_string("%".$_GET['keyword_visibility']."%");
94
        $keyword_subscribe = Database::escape_string($_GET['keyword_subscribe']);
95
        $keyword_unsubscribe = Database::escape_string($_GET['keyword_unsubscribe']);
96
97
        $sql .= " AND
98
                title LIKE '".$keyword_title."' AND
99
                (code LIKE '".$keyword_code."' OR visual_code LIKE '".$keyword_code."') AND
100
                course_language LIKE '".$keyword_language."' AND
101
                visibility LIKE '".$keyword_visibility."' AND
102
                subscribe LIKE '".$keyword_subscribe."' AND
103
                unsubscribe LIKE '".$keyword_unsubscribe."'";
104
105
        if (!empty($keyword_category)) {
106
            $sql .= " AND category_code LIKE '".$keyword_category."' ";
107
        }
108
    }
109
110
    // Adding the filter to see the user's only of the current access_url.
111
    if (api_is_multiple_url_enabled()) {
112
        $sql .= " AND url_rel_course.access_url_id = ".api_get_current_access_url_id();
113
    }
114
115
    if ($addTeacherColumn) {
116
        $teachers = isset($_GET['course_teachers']) ? $_GET['course_teachers'] : [];
117
        if (!empty($teachers)) {
118
            $teachers = array_map('intval', $teachers);
119
            $addNull = '';
120
            foreach ($teachers as $key => $teacherId) {
121
                if (0 === $teacherId) {
122
                    $addNull = 'OR cu.user_id IS NULL ';
123
                    unset($key);
124
                }
125
            }
126
            $sql .= ' AND ( cu.user_id IN ("'.implode('", "', $teachers).'") '.$addNull.' ) ';
127
        }
128
129
        if (false === $getCount) {
130
            $sql .= " GROUP BY course.id ";
131
        }
132
    }
133
134
    if ($getCount) {
135
        $res = Database::query($sql);
136
        $row = Database::fetch_array($res);
137
        if ($row) {
138
            return (int) $row['count'];
139
        }
140
141
        return 0;
142
    }
143
    $sql .= " ORDER BY col$column $direction ";
144
    $sql .= " LIMIT $from, $number_of_items";
145
146
    $res = Database::query($sql);
147
    $courses = [];
148
    $path = api_get_path(WEB_CODE_PATH);
149
    $coursePath = api_get_path(WEB_COURSE_PATH);
150
151
    while ($course = Database::fetch_array($res)) {
152
        $courseId = $course['id'];
153
        $courseCode = $course['code'];
154
155
        // Place colour icons in front of courses.
156
        $showVisualCode = $course['visual_code'] != $courseCode ? Display::label($course['visual_code'], 'info') : null;
157
        $course[1] = get_course_visibility_icon($course['visibility']).PHP_EOL
158
            .Display::url(Security::remove_XSS($course[1]), $coursePath.$course['directory'].'/index.php').PHP_EOL
159
            .$showVisualCode;
160
        $course[5] = SUBSCRIBE_ALLOWED == $course[5] ? get_lang('Yes') : get_lang('No');
161
        $course[6] = UNSUBSCRIBE_ALLOWED == $course[6] ? get_lang('Yes') : get_lang('No');
162
163
        $actions = [];
164
        $actions[] = Display::url(
165
            Display::return_icon('info2.png', get_lang('Info')),
166
            "course_information.php?code=$courseCode"
167
        );
168
        /*$actions[] = Display::url(
169
            Display::return_icon('course_home.png', get_lang('CourseHomepage')),
170
            $coursePath.$course['directory'].'/index.php'
171
        );*/
172
        $actions[] = Display::url(
173
            Display::return_icon('statistics.png', get_lang('Tracking')),
174
            $path.'tracking/courseLog.php?'.api_get_cidreq_params($courseId)
175
        );
176
        $actions[] = Display::url(
177
            Display::return_icon('edit.png', get_lang('Edit')),
178
            $path.'admin/course_edit.php?id='.$courseId
179
        );
180
        $actions[] = Display::url(
181
            Display::return_icon('backup.png', get_lang('CreateBackup')),
182
            $path.'coursecopy/create_backup.php?'.api_get_cidreq_params($courseId)
183
        );
184
        $actions[] = Display::url(
185
            Display::return_icon('delete.png', get_lang('Delete')),
186
            $path.'admin/course_list_admin.php?delete_course='.$courseCode,
187
            [
188
                'onclick' => "javascript: if (!confirm('"
189
                    .addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES))."')) return false;",
190
            ]
191
        );
192
193
        $course['creation_date'] = api_get_local_time($course['col2']);
194
        $lastAccessLocalTime = '';
195
        $lastAccess = Tracking::getLastConnectionDateByCourse($courseId);
196
        if ($lastAccess) {
197
            $lastAccessLocalTime = api_get_local_time($lastAccess);
198
        }
199
200
        $courseItem = [
201
            $course[0],
202
            $course[1],
203
            $course['creation_date'],
204
            $lastAccessLocalTime,
205
        ];
206
207
        if ($addTeacherColumn) {
208
            $teacherIdList = array_filter(explode(',', $course['col4']));
209
            $teacherList = [];
210
            if (!empty($teacherIdList)) {
211
                foreach ($teacherIdList as $teacherId) {
212
                    $userInfo = api_get_user_info($teacherId);
213
                    if ($userInfo) {
214
                        $teacherList[] = $userInfo['complete_name'];
215
                    }
216
                }
217
            }
218
            $courseItem[] = implode(', ', $teacherList);
219
        }
220
        $courseItem[] = implode(PHP_EOL, $actions);
221
        $courses[] = $courseItem;
222
    }
223
224
    return $courses;
225
}
226
227
/**
228
 * Return an icon representing the visibility of the course.
229
 *
230
 * @param string $visibility
231
 *
232
 * @return string
233
 */
234
function get_course_visibility_icon($visibility)
235
{
236
    $style = 'margin-bottom:0;margin-right:5px;';
237
    switch ($visibility) {
238
        case 0:
239
            return Display::return_icon(
240
                'bullet_red.png',
241
                get_lang('CourseVisibilityClosed'),
242
                ['style' => $style]
243
            );
244
            break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
245
        case 1:
246
            return Display::return_icon(
247
                'bullet_orange.png',
248
                get_lang('Private'),
249
                ['style' => $style]
250
            );
251
            break;
252
        case 2:
253
            return Display::return_icon(
254
                'bullet_green.png',
255
                get_lang('OpenToThePlatform'),
256
                ['style' => $style]
257
            );
258
            break;
259
        case 3:
260
            return Display::return_icon(
261
                'bullet_blue.png',
262
                get_lang('OpenToTheWorld'),
263
                ['style' => $style]
264
            );
265
            break;
266
        case 4:
267
            return Display::return_icon(
268
                'bullet_grey.png',
269
                get_lang('CourseVisibilityHidden'),
270
                ['style' => $style]
271
            );
272
            break;
273
        default:
274
            return '';
275
    }
276
}
277
278
if (isset($_POST['action'])) {
279
    switch ($_POST['action']) {
280
        // Delete selected courses
281
        case 'delete_courses':
282
            if (!empty($_POST['course'])) {
283
                $course_codes = $_POST['course'];
284
                if (count($course_codes) > 0) {
285
                    foreach ($course_codes as $course_code) {
286
                        CourseManager::delete_course($course_code);
287
                    }
288
                }
289
290
                Display::addFlash(Display::return_message(get_lang('Deleted')));
291
            }
292
            break;
293
    }
294
}
295
$content = '';
296
$message = '';
297
$actions = '';
298
299
if (isset($_GET['search']) && 'advanced' === $_GET['search']) {
300
    // Get all course categories
301
    $interbreadcrumb[] = [
302
        'url' => 'index.php',
303
        'name' => get_lang('PlatformAdmin'),
304
    ];
305
    $interbreadcrumb[] = [
306
        'url' => 'course_list_admin.php',
307
        'name' => get_lang('CourseList'),
308
    ];
309
    $tool_name = get_lang('SearchACourse');
310
    $form = new FormValidator('advanced_course_search', 'get');
311
    $form->addElement('header', $tool_name);
312
    $form->addText('keyword_code', get_lang('CourseCode'), false);
313
    $form->addText('keyword_title', get_lang('Title'), false);
314
315
    // Category code
316
    $url = api_get_path(WEB_AJAX_PATH).'course.ajax.php?a=search_category';
317
318
    $form->addElement(
319
        'select_ajax',
320
        'keyword_category',
321
        get_lang('CourseFaculty'),
322
        null,
323
        [
324
            'url' => $url,
325
        ]
326
    );
327
328
    $el = $form->addSelectLanguage('keyword_language', get_lang('CourseLanguage'));
329
    $el->addOption(get_lang('All'), '%');
330
331
    if ($addTeacherColumn) {
332
        $form->addSelectAjax(
333
            'course_teachers',
334
            get_lang('CourseTeachers'),
335
            [0 => get_lang('None')],
336
            [
337
                'url' => api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=teacher_to_basis_course',
338
                'id' => 'course_teachers',
339
                'multiple' => 'multiple',
340
            ]
341
        );
342
        $form->addLabel('', '<button id="set_none_teacher" class="btn ">'.get_lang('None').'</button>');
343
    }
344
345
    $form->addElement('radio', 'keyword_visibility', get_lang('CourseAccess'), get_lang('OpenToTheWorld'), COURSE_VISIBILITY_OPEN_WORLD);
346
    $form->addElement('radio', 'keyword_visibility', null, get_lang('OpenToThePlatform'), COURSE_VISIBILITY_OPEN_PLATFORM);
347
    $form->addElement('radio', 'keyword_visibility', null, get_lang('Private'), COURSE_VISIBILITY_REGISTERED);
348
    $form->addElement('radio', 'keyword_visibility', null, get_lang('CourseVisibilityClosed'), COURSE_VISIBILITY_CLOSED);
349
    $form->addElement('radio', 'keyword_visibility', null, get_lang('CourseVisibilityHidden'), COURSE_VISIBILITY_HIDDEN);
350
    $form->addElement('radio', 'keyword_visibility', null, get_lang('All'), '%');
351
    $form->addElement('radio', 'keyword_subscribe', get_lang('Subscription'), get_lang('Allowed'), 1);
352
    $form->addElement('radio', 'keyword_subscribe', null, get_lang('Denied'), 0);
353
    $form->addElement('radio', 'keyword_subscribe', null, get_lang('All'), '%');
354
    $form->addElement('radio', 'keyword_unsubscribe', get_lang('Unsubscription'), get_lang('AllowedToUnsubscribe'), 1);
355
    $form->addElement('radio', 'keyword_unsubscribe', null, get_lang('NotAllowedToUnsubscribe'), 0);
356
    $form->addElement('radio', 'keyword_unsubscribe', null, get_lang('All'), '%');
357
    $form->addButtonSearch(get_lang('SearchCourse'));
358
    $defaults['keyword_language'] = '%';
359
    $defaults['keyword_visibility'] = '%';
360
    $defaults['keyword_subscribe'] = '%';
361
    $defaults['keyword_unsubscribe'] = '%';
362
    $form->setDefaults($defaults);
363
    $content .= $form->returnForm();
364
} else {
365
    $interbreadcrumb[] = [
366
        'url' => 'index.php',
367
        'name' => get_lang('PlatformAdmin'),
368
    ];
369
    $tool_name = get_lang('CourseList');
370
    if (isset($_GET['delete_course'])) {
371
        $result = CourseManager::delete_course($_GET['delete_course']);
372
        if ($result) {
373
            Display::addFlash(Display::return_message(get_lang('Deleted')));
374
        }
375
    }
376
    // Create a search-box
377
    $form = new FormValidator(
378
        'search_simple',
379
        'get',
380
        '',
381
        '',
382
        [],
383
        FormValidator::LAYOUT_INLINE
384
    );
385
    $form->addElement(
386
        'text',
387
        'keyword',
388
        null,
389
        ['id' => 'course-search-keyword', 'aria-label' => get_lang('SearchCourse')]
390
    );
391
    $form->addButtonSearch(get_lang('SearchCourse'));
392
    $advanced = '<a class="btn btn-default" href="'.api_get_path(WEB_CODE_PATH).'admin/course_list_admin.php?search=advanced">
393
        <em class="fa fa-search"></em> '.
394
        get_lang('AdvancedSearch').'</a>';
395
396
    // Create a filter by session
397
    $sessionFilter = new FormValidator(
398
        'course_filter',
399
        'get',
400
        '',
401
        '',
402
        [],
403
        FormValidator::LAYOUT_INLINE
404
    );
405
406
    $courseListUrl = api_get_self();
407
    $actions1 = Display::url(
408
        Display::return_icon(
409
            'new_course.png',
410
            get_lang('AddCourse'),
411
            [],
412
            ICON_SIZE_MEDIUM
413
        ),
414
        api_get_path(WEB_CODE_PATH).'admin/course_add.php'
415
    );
416
417
    if ('true' === api_get_setting('course_validation')) {
418
        $actions1 .= Display::url(
419
            Display::return_icon(
420
                'course_request_pending.png',
421
                get_lang('ReviewCourseRequests'),
422
                [],
423
                ICON_SIZE_MEDIUM
424
            ),
425
            api_get_path(WEB_CODE_PATH).'admin/course_request_review.php'
426
        );
427
    }
428
429
    $actions2 = $form->returnForm();
430
    //$actions3 = $sessionFilter->returnForm();
431
    $actions4 = $advanced;
432
433
    $actions = Display::toolbarAction(
434
        'toolbar',
435
        [$actions1, $actions2, $actions4],
436
        [2, 4, 3, 3]
437
    );
438
439
    // Create a sortable table with the course data
440
    $table = new SortableTable(
441
        'course_list_admin',
442
        'get_number_of_courses',
443
        'get_course_data',
444
        1,
445
        20,
446
        'ASC',
447
        'course_list_admin'
448
    );
449
450
    $parameters = [];
451
    if (isset($_GET['keyword'])) {
452
        $parameters = ['keyword' => Security::remove_XSS($_GET['keyword'])];
453
    } elseif (isset($_GET['keyword_code'])) {
454
        $parameters['keyword_code'] = Security::remove_XSS($_GET['keyword_code']);
455
        $parameters['keyword_title'] = Security::remove_XSS($_GET['keyword_title']);
456
        if (isset($_GET['keyword_category'])) {
457
            $parameters['keyword_category'] = Security::remove_XSS($_GET['keyword_category']);
458
        }
459
        $parameters['keyword_language'] = Security::remove_XSS($_GET['keyword_language']);
460
        $parameters['keyword_visibility'] = Security::remove_XSS($_GET['keyword_visibility']);
461
        $parameters['keyword_subscribe'] = Security::remove_XSS($_GET['keyword_subscribe']);
462
        $parameters['keyword_unsubscribe'] = Security::remove_XSS($_GET['keyword_unsubscribe']);
463
    }
464
465
    if (isset($_GET['course_teachers'])) {
466
        $parsed = array_map('intval', $_GET['course_teachers']);
467
        $parameters["course_teachers"] = '';
468
        foreach ($parsed as $key => $teacherId) {
469
            $parameters["course_teachers[$key]"] = $teacherId;
470
        }
471
    }
472
473
    $table->set_additional_parameters($parameters);
474
    $column = 0;
475
    $table->set_header($column++, '', false, 'width="8px"');
476
    $table->set_header($column++, get_lang('Title'), true, null, ['class' => 'title']);
477
    $table->set_header($column++, get_lang('CreationDate'), true, 'width="70px"');
478
    $table->set_header($column++, get_lang('LatestLoginInCourse'), false, 'width="70px"');
479
    //$table->set_header($column++, get_lang('Category'));
480
    //$table->set_header($column++, get_lang('SubscriptionAllowed'), true, 'width="60px"');
481
    //$table->set_header($column++, get_lang('UnsubscriptionAllowed'), false, 'width="50px"');
482
    if ($addTeacherColumn) {
483
        $table->set_header($column++, get_lang('Teachers'), true);
484
    }
485
    $table->set_header(
486
        $column++,
487
        get_lang('Action'),
488
        false,
489
        null,
490
        ['class' => 'td_actions']
491
    );
492
    $table->set_form_actions(
493
        ['delete_courses' => get_lang('DeleteCourse')],
494
        'course'
495
    );
496
    $tab = CourseManager::getCourseListTabs('admin');
497
    $content .= $tab.$table->return_table();
498
}
499
500
$htmlHeadXtra[] = '
501
<script>
502
$(function() {
503
    $("#set_none_teacher").on("click", function () {
504
        $("#course_teachers").val("0").trigger("change");
505
506
        return false;
507
    });
508
});
509
</script>';
510
511
$tpl = new Template($tool_name);
512
$tpl->assign('actions', $actions);
513
$tpl->assign('message', $message);
514
$tpl->assign('content', $content);
515
$tpl->display_one_col_template();
516