Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
/**
18
 * Course and category management interfaces.
19
 *
20
 * @package    core_course
21
 * @copyright  2013 Sam Hemelryk
22
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
require_once('../config.php');
26
require_once($CFG->dirroot.'/course/lib.php');
27
 
28
$categoryid = optional_param('categoryid', null, PARAM_INT);
29
$selectedcategoryid = optional_param('selectedcategoryid', null, PARAM_INT);
30
$courseid = optional_param('courseid', null, PARAM_INT);
31
$action = optional_param('action', false, PARAM_ALPHA);
32
$page = optional_param('page', 0, PARAM_INT);
33
$perpage = optional_param('perpage', null, PARAM_INT);
34
$viewmode = optional_param('view', 'default', PARAM_ALPHA); // Can be one of default, combined, courses, or categories.
35
 
36
// Search related params.
37
$search = optional_param('search', '', PARAM_RAW); // Search words. Shortname, fullname, idnumber and summary get searched.
38
$blocklist = optional_param('blocklist', 0, PARAM_INT); // Find courses containing this block.
39
$modulelist = optional_param('modulelist', '', PARAM_PLUGIN); // Find courses containing the given modules.
40
 
41
if (!in_array($viewmode, array('default', 'combined', 'courses', 'categories'))) {
42
    $viewmode = 'default';
43
}
44
 
45
$issearching = ($search !== '' || $blocklist !== 0 || $modulelist !== '');
46
if ($issearching) {
47
    $viewmode = 'courses';
48
}
49
 
50
$url = new moodle_url('/course/management.php');
51
$systemcontext = $context = context_system::instance();
52
if ($courseid) {
53
    $record = get_course($courseid);
54
    $course = new core_course_list_element($record);
55
    $category = core_course_category::get($course->category);
56
    $categoryid = $category->id;
57
    $context = context_coursecat::instance($category->id);
58
    $url->param('categoryid', $categoryid);
59
    $url->param('courseid', $course->id);
60
 
61
} else if ($categoryid) {
62
    $courseid = null;
63
    $course = null;
64
    $category = core_course_category::get($categoryid);
65
    $context = context_coursecat::instance($category->id);
66
    $url->param('categoryid', $category->id);
67
 
68
} else {
69
    $course = null;
70
    $courseid = null;
71
    $topchildren = core_course_category::top()->get_children();
72
    if (empty($topchildren)) {
73
        throw new moodle_exception('cannotviewcategory', 'error');
74
    }
75
    $category = reset($topchildren);
76
    $categoryid = $category->id;
77
    $context = context_coursecat::instance($category->id);
78
    $url->param('categoryid', $category->id);
79
}
80
 
81
// Check if there is a selected category param, and if there is apply it.
82
if ($course === null && $selectedcategoryid !== null && $selectedcategoryid !== $categoryid) {
83
    $url->param('categoryid', $selectedcategoryid);
84
}
85
 
86
if ($page !== 0) {
87
    $url->param('page', $page);
88
}
89
if ($viewmode !== 'default') {
90
    $url->param('view', $viewmode);
91
}
92
if ($search !== '') {
93
    $url->param('search', $search);
94
}
95
if ($blocklist !== 0) {
96
    $url->param('blocklist', $search);
97
}
98
if ($modulelist !== '') {
99
    $url->param('modulelist', $search);
100
}
101
 
102
$strmanagement = new lang_string('coursecatmanagement');
103
$pageheading = $category->get_formatted_name();
104
 
105
$PAGE->set_context($context);
106
$PAGE->set_url($url);
107
$PAGE->set_pagelayout('admin');
108
$PAGE->set_title($strmanagement);
109
$PAGE->set_heading($pageheading);
110
$PAGE->requires->js_call_amd('core_course/copy_modal', 'init', array($context->id));
111
$PAGE->set_secondary_active_tab('categorymain');
112
 
113
// This is a system level page that operates on other contexts.
114
require_login();
115
 
116
if (!core_course_category::has_capability_on_any(array('moodle/category:manage', 'moodle/course:create'))) {
117
    // The user isn't able to manage any categories. Lets redirect them to the relevant course/index.php page.
118
    $url = new moodle_url('/course/index.php');
119
    if ($categoryid) {
120
        $url->param('categoryid', $categoryid);
121
    }
122
    redirect($url);
123
}
124
 
125
if (!$issearching && $category !== null) {
126
    $parents = core_course_category::get_many($category->get_parents());
127
    $parents[] = $category;
128
    foreach ($parents as $parent) {
129
        $PAGE->navbar->add(
130
            $parent->get_formatted_name(),
131
            new moodle_url('/course/index.php', array('categoryid' => $parent->id))
132
        );
133
    }
134
    if ($course instanceof core_course_list_element) {
135
        // Use the list name so that it matches whats being displayed below.
136
        $PAGE->navbar->add($course->get_formatted_name());
137
    }
138
}
139
 
140
// If the user poses any of these capabilities then they will be able to see the admin
141
// tree and the management link within it.
142
// This is the most accurate form of navigation.
143
$capabilities = array(
144
    'moodle/site:config',
145
    'moodle/backup:backupcourse',
146
    'moodle/category:manage',
147
    'moodle/course:create',
148
    'moodle/site:approvecourse'
149
);
150
if ($category && !has_any_capability($capabilities, $systemcontext)) {
151
    // If the user doesn't poses any of these system capabilities then we're going to mark the category link in the
152
    // settings block as active, tell the page to ignore the active path and just build what the user would expect.
153
    // This will at least give the page some relevant navigation.
154
    navigation_node::override_active_url(new moodle_url('/course/index.php', array('categoryid' => $category->id)));
155
    $PAGE->set_category_by_id($category->id);
156
    $PAGE->navbar->ignore_active(true);
157
} else {
158
    // If user has system capabilities, make sure the "Category" item in Administration block is active.
159
    navigation_node::require_admin_tree();
160
    navigation_node::override_active_url(new moodle_url('/course/index.php'));
161
}
162
$PAGE->navbar->add(get_string('coursemgmt', 'admin'), $PAGE->url->out_omit_querystring());
163
$PAGE->set_primary_active_tab('home');
164
 
165
$notificationspass = array();
166
$notificationsfail = array();
167
 
168
if ($action !== false && confirm_sesskey()) {
169
    // Actions:
170
    // - resortcategories : Resort the courses in the given category.
171
    // - resortcourses : Resort courses
172
    // - showcourse : make a course visible.
173
    // - hidecourse : make a course hidden.
174
    // - movecourseup : move the selected course up one.
175
    // - movecoursedown : move the selected course down.
176
    // - showcategory : make a category visible.
177
    // - hidecategory : make a category hidden.
178
    // - movecategoryup : move category up.
179
    // - movecategorydown : move category down.
180
    // - deletecategory : delete the category either in full, or moving contents.
181
    // - bulkaction : performs bulk actions:
182
    //    - bulkmovecourses.
183
    //    - bulkmovecategories.
184
    //    - bulkresortcategories.
185
    $redirectback = false;
186
    $redirectmessage = false;
187
    switch ($action) {
188
        case 'resortcategories' :
189
            $sort = required_param('resort', PARAM_ALPHA);
190
            $cattosort = core_course_category::get((int)optional_param('categoryid', 0, PARAM_INT));
191
            $redirectback = \core_course\management\helper::action_category_resort_subcategories($cattosort, $sort);
192
            break;
193
        case 'resortcourses' :
194
            // They must have specified a category.
195
            required_param('categoryid', PARAM_INT);
196
            $sort = required_param('resort', PARAM_ALPHA);
197
            \core_course\management\helper::action_category_resort_courses($category, $sort);
198
            break;
199
        case 'showcourse' :
200
            $redirectback = \core_course\management\helper::action_course_show($course);
201
            break;
202
        case 'hidecourse' :
203
            $redirectback = \core_course\management\helper::action_course_hide($course);
204
            break;
205
        case 'movecourseup' :
206
            // They must have specified a category and a course.
207
            required_param('categoryid', PARAM_INT);
208
            required_param('courseid', PARAM_INT);
209
            $redirectback = \core_course\management\helper::action_course_change_sortorder_up_one($course, $category);
210
            break;
211
        case 'movecoursedown' :
212
            // They must have specified a category and a course.
213
            required_param('categoryid', PARAM_INT);
214
            required_param('courseid', PARAM_INT);
215
            $redirectback = \core_course\management\helper::action_course_change_sortorder_down_one($course, $category);
216
            break;
217
        case 'showcategory' :
218
            // They must have specified a category.
219
            required_param('categoryid', PARAM_INT);
220
            $redirectback = \core_course\management\helper::action_category_show($category);
221
            break;
222
        case 'hidecategory' :
223
            // They must have specified a category.
224
            required_param('categoryid', PARAM_INT);
225
            $redirectback = \core_course\management\helper::action_category_hide($category);
226
            break;
227
        case 'movecategoryup' :
228
            // They must have specified a category.
229
            required_param('categoryid', PARAM_INT);
230
            $redirectback = \core_course\management\helper::action_category_change_sortorder_up_one($category);
231
            break;
232
        case 'movecategorydown' :
233
            // They must have specified a category.
234
            required_param('categoryid', PARAM_INT);
235
            $redirectback = \core_course\management\helper::action_category_change_sortorder_down_one($category);
236
            break;
237
        case 'deletecategory':
238
            // They must have specified a category.
239
            required_param('categoryid', PARAM_INT);
240
            if (!$category->can_delete()) {
241
                throw new moodle_exception('permissiondenied', 'error', '', null, 'core_course_category::can_resort');
242
            }
243
            $mform = new core_course_deletecategory_form(null, $category);
244
            if ($mform->is_cancelled()) {
245
                redirect($PAGE->url);
246
            }
247
            // Start output.
248
            /* @var core_course_management_renderer|core_renderer $renderer */
249
            $renderer = $PAGE->get_renderer('core_course', 'management');
250
            echo $renderer->header();
251
            echo $renderer->heading(get_string('deletecategory', 'moodle', $category->get_formatted_name()));
252
 
253
            if ($data = $mform->get_data()) {
254
                // The form has been submit handle it.
255
                if ($data->fulldelete == 1 && $category->can_delete_full()) {
256
                    $continueurl = new moodle_url('/course/management.php');
257
                    if ($category->parent != '0') {
258
                        $continueurl->param('categoryid', $category->parent);
259
                    }
260
                    $notification = get_string('coursecategorydeleted', '', $category->get_formatted_name());
261
                    $deletedcourses = $category->delete_full(true);
262
                    foreach ($deletedcourses as $course) {
263
                        echo $renderer->notification(get_string('coursedeleted', '', $course->shortname), 'notifysuccess');
264
                    }
265
                    echo $renderer->notification($notification, 'notifysuccess');
266
                    echo $renderer->continue_button($continueurl);
267
                } else if ($data->fulldelete == 0 && $category->can_move_content_to($data->newparent)) {
268
                    $continueurl = new moodle_url('/course/management.php', array('categoryid' => $data->newparent));
269
                    $category->delete_move($data->newparent, true);
270
                    echo $renderer->continue_button($continueurl);
271
                } else {
272
                    // Some error in parameters (user is cheating?)
273
                    $mform->display();
274
                }
275
            } else {
276
                // Display the form.
277
                $mform->display();
278
            }
279
            // Finish output and exit.
280
            echo $renderer->footer();
281
            exit();
282
            break;
283
        case 'bulkaction':
284
            $bulkmovecourses = optional_param('bulkmovecourses', false, PARAM_BOOL);
285
            $bulkmovecategories = optional_param('bulkmovecategories', false, PARAM_BOOL);
286
            $bulkresortcategories = optional_param('bulksort', false, PARAM_BOOL);
287
 
288
            if ($bulkmovecourses) {
289
                // Move courses out of the current category and into a new category.
290
                // They must have specified a category.
291
                required_param('categoryid', PARAM_INT);
292
                $movetoid = required_param('movecoursesto', PARAM_INT);
293
                $courseids = optional_param_array('bc', false, PARAM_INT);
294
                if ($courseids === false) {
295
                    break;
296
                }
297
                $moveto = core_course_category::get($movetoid);
298
                try {
299
                    // If this fails we want to catch the exception and report it.
300
                    $redirectback = \core_course\management\helper::move_courses_into_category($moveto,
301
                        $courseids);
302
                    if ($redirectback) {
303
                        $a = new stdClass;
304
                        $a->category = $moveto->get_formatted_name();
305
                        $a->courses = count($courseids);
306
                        $redirectmessage = get_string('bulkmovecoursessuccess', 'moodle', $a);
307
                    }
308
                } catch (moodle_exception $ex) {
309
                    $redirectback = false;
310
                    $notificationsfail[] = $ex->getMessage();
311
                }
312
            } else if ($bulkmovecategories) {
313
                $categoryids = optional_param_array('bcat', array(), PARAM_INT);
314
                $movetocatid = required_param('movecategoriesto', PARAM_INT);
315
                $movetocat = core_course_category::get($movetocatid);
316
                $movecount = 0;
317
                foreach ($categoryids as $id) {
318
                    $cattomove = core_course_category::get($id);
319
                    if ($id == $movetocatid) {
320
                        $notificationsfail[] = get_string('movecategoryownparent', 'error', $cattomove->get_formatted_name());
321
                        continue;
322
                    }
323
                    // Don't allow user to move selected category into one of it's own sub-categories.
324
                    if (strpos($movetocat->path, $cattomove->path . '/') === 0) {
325
                        $notificationsfail[] = get_string('movecategoryparentconflict', 'error', $cattomove->get_formatted_name());
326
                        continue;
327
                    }
328
                    if ($cattomove->parent != $movetocatid) {
329
                        if ($cattomove->can_change_parent($movetocatid)) {
330
                            $cattomove->change_parent($movetocatid);
331
                            $movecount++;
332
                        } else {
333
                            $notificationsfail[] = get_string('movecategorynotpossible', 'error', $cattomove->get_formatted_name());
334
                        }
335
                    }
336
                }
337
                if ($movecount > 1) {
338
                    $a = new stdClass;
339
                    $a->count = $movecount;
340
                    $a->to = $movetocat->get_formatted_name();
341
                    $movesuccessstrkey = 'movecategoriessuccess';
342
                    if ($movetocatid == 0) {
343
                        $movesuccessstrkey = 'movecategoriestotopsuccess';
344
                    }
345
                    $notificationspass[] = get_string($movesuccessstrkey, 'moodle', $a);
346
                } else if ($movecount === 1) {
347
                    $a = new stdClass;
348
                    $a->moved = $cattomove->get_formatted_name();
349
                    $a->to = $movetocat->get_formatted_name();
350
                    $movesuccessstrkey = 'movecategorysuccess';
351
                    if ($movetocatid == 0) {
352
                        $movesuccessstrkey = 'movecategorytotopsuccess';
353
                    }
354
                    $notificationspass[] = get_string($movesuccessstrkey, 'moodle', $a);
355
                }
356
            } else if ($bulkresortcategories) {
357
                $for = required_param('selectsortby', PARAM_ALPHA);
358
                $sortcategoriesby = required_param('resortcategoriesby', PARAM_ALPHA);
359
                $sortcoursesby = required_param('resortcoursesby', PARAM_ALPHA);
360
 
361
                if ($sortcategoriesby === 'none' && $sortcoursesby === 'none') {
362
                    // They're not sorting anything.
363
                    break;
364
                }
365
                if (!in_array($sortcategoriesby, array('idnumber', 'idnumberdesc',
366
                                                       'name', 'namedesc'))) {
367
                    $sortcategoriesby = false;
368
                }
369
                if (!in_array($sortcoursesby, array('timecreated', 'timecreateddesc',
370
                                                    'idnumber', 'idnumberdesc',
371
                                                    'fullname', 'fullnamedesc',
372
                                                    'shortname', 'shortnamedesc'))) {
373
                    $sortcoursesby = false;
374
                }
375
 
376
                if ($for === 'thiscategory') {
377
                    $categoryids = array(
378
                        required_param('currentcategoryid', PARAM_INT)
379
                    );
380
                    $categories = core_course_category::get_many($categoryids);
381
                } else if ($for === 'selectedcategories') {
382
                    // Bulk resort selected categories.
383
                    $categoryids = optional_param_array('bcat', false, PARAM_INT);
384
                    $sort = required_param('resortcategoriesby', PARAM_ALPHA);
385
                    if ($categoryids === false) {
386
                        break;
387
                    }
388
                    $categories = core_course_category::get_many($categoryids);
389
                } else if ($for === 'allcategories') {
390
                    if ($sortcategoriesby && core_course_category::top()->can_resort_subcategories()) {
391
                        \core_course\management\helper::action_category_resort_subcategories(
392
                            core_course_category::top(), $sortcategoriesby);
393
                    }
394
                    $categorieslist = core_course_category::make_categories_list('moodle/category:manage');
395
                    $categoryids = array_keys($categorieslist);
396
                    $categories = core_course_category::get_many($categoryids);
397
                    unset($categorieslist);
398
                } else {
399
                    break;
400
                }
401
                foreach ($categories as $cat) {
402
                    if ($sortcategoriesby && $cat->can_resort_subcategories()) {
403
                        // Don't clean up here, we'll do it once we're all done.
404
                        \core_course\management\helper::action_category_resort_subcategories($cat, $sortcategoriesby, false);
405
                    }
406
                    if ($sortcoursesby && $cat->can_resort_courses()) {
407
                        \core_course\management\helper::action_category_resort_courses($cat, $sortcoursesby, false);
408
                    }
409
                }
410
                core_course_category::resort_categories_cleanup($sortcoursesby !== false);
411
                if ($category === null && count($categoryids) === 1) {
412
                    // They're bulk sorting just a single category and they've not selected a category.
413
                    // Lets for convenience sake auto-select the category that has been resorted for them.
414
                    redirect(new moodle_url($PAGE->url, array('categoryid' => reset($categoryids))));
415
                }
416
            }
417
    }
418
    if ($redirectback) {
419
        if ($redirectmessage) {
420
            redirect($PAGE->url, $redirectmessage, 5);
421
        } else {
422
            redirect($PAGE->url);
423
        }
424
    }
425
}
426
 
427
if (!is_null($perpage)) {
428
    set_user_preference('coursecat_management_perpage', $perpage);
429
} else {
430
    $perpage = get_user_preferences('coursecat_management_perpage', $CFG->coursesperpage);
431
}
432
if ((int)$perpage != $perpage || $perpage < 2) {
433
    $perpage = $CFG->coursesperpage;
434
}
435
 
436
$categorysize = 4;
437
$coursesize = 4;
438
$detailssize = 4;
439
if ($viewmode === 'default' || $viewmode === 'combined') {
440
    if (isset($courseid)) {
441
        $class = 'columns-3';
442
    } else {
443
        $categorysize = 5;
444
        $coursesize = 7;
445
        $class = 'columns-2';
446
    }
447
} else if ($viewmode === 'categories') {
448
    $categorysize = 12;
449
    $class = 'columns-1';
450
} else if ($viewmode === 'courses') {
451
    if (isset($courseid)) {
452
        $coursesize = 6;
453
        $detailssize = 6;
454
        $class = 'columns-2';
455
    } else {
456
        $coursesize = 12;
457
        $class = 'columns-1';
458
    }
459
}
460
if ($viewmode === 'default' || $viewmode === 'combined') {
461
    $class .= ' viewmode-combined';
462
} else {
463
    $class .= ' viewmode-'.$viewmode;
464
}
465
if (($viewmode === 'default' || $viewmode === 'combined' || $viewmode === 'courses') && !empty($courseid)) {
466
    $class .= ' course-selected';
467
}
468
 
469
/* @var core_course_management_renderer|core_renderer $renderer */
470
$renderer = $PAGE->get_renderer('core_course', 'management');
471
$renderer->enhance_management_interface();
472
 
473
$displaycategorylisting = ($viewmode === 'default' || $viewmode === 'combined' || $viewmode === 'categories');
474
$displaycourselisting = ($viewmode === 'default' || $viewmode === 'combined' || $viewmode === 'courses');
475
$displaycoursedetail = (isset($courseid));
476
 
477
echo $renderer->header();
478
$actionbar = new \core_course\output\manage_categories_action_bar($PAGE, $viewmode, $course, $search);
479
echo $renderer->render_action_bar($actionbar);
480
 
481
if (count($notificationspass) > 0) {
482
    echo $renderer->notification(join('<br />', $notificationspass), 'notifysuccess');
483
}
484
if (count($notificationsfail) > 0) {
485
    echo $renderer->notification(join('<br />', $notificationsfail));
486
}
487
 
488
// Start the management form.
489
 
490
echo $renderer->management_form_start();
491
 
492
echo $renderer->accessible_skipto_links($displaycategorylisting, $displaycourselisting, $displaycoursedetail);
493
 
494
echo $renderer->grid_start('course-category-listings', $class);
495
 
496
if ($displaycategorylisting) {
497
    echo $renderer->grid_column_start($categorysize, 'category-listing');
498
    echo $renderer->category_listing($category);
499
    echo $renderer->grid_column_end();
500
}
501
if ($displaycourselisting) {
502
    echo $renderer->grid_column_start($coursesize, 'course-listing');
503
    if (!$issearching) {
504
        echo $renderer->course_listing($category, $course, $page, $perpage, $viewmode);
505
    } else {
506
        list($courses, $coursescount, $coursestotal) =
507
            \core_course\management\helper::search_courses($search, $blocklist, $modulelist, $page, $perpage);
508
        echo $renderer->search_listing($courses, $coursestotal, $course, $page, $perpage, $search);
509
    }
510
    echo $renderer->grid_column_end();
511
    if ($displaycoursedetail) {
512
        echo $renderer->grid_column_start($detailssize, 'course-detail');
513
        echo $renderer->course_detail($course);
514
        echo $renderer->grid_column_end();
515
    }
516
}
517
echo $renderer->grid_end();
518
 
519
// End of the management form.
520
echo $renderer->management_form_end();
521
 
522
echo $renderer->footer();