Skip to content
Browse files

course categories: Fix many bugs with category editing and permission…

…s. Clean up code.

Bugs: MDL-17479, MDL-16426, MDL-16063, MDL-16013, MDL-15658, MDL-15556, MDL-15161, MDL-14925, MDL-13742, MDL-11557.

* Simplify category editing permissions to just moodle/category:manage and moodle/category:seehiddencategories.
* Enforce those correctly. (Note MDL 17502 is still outstanding.)
* Don't screw up category sort order when you just edit name or description.
* Niceties like where redirects go when you cancel or submit forms.
* Make sure a global course creator can see the site admin block.
* Don't allow a category to be made the child of one of its children!
* General code cleanup to bring key files more in line with best pracitice.

Apologies for the fact it is one big patch, rather than a series of smaller patches. However, categoryedit.php, category.php and index.php where in pretty bad shape and needed significant cleaning up. categoryedit.php, in particular, was almost completely rewritten.
  • Loading branch information...
1 parent 39dc066 commit 79518165b95b367503991c22e2f201b821bd7679 tjhunt committed
View
7 admin/settings/courses.php
@@ -4,10 +4,11 @@
if ($hassiteconfig
or has_capability('moodle/site:backup', $systemcontext)
- or has_capability('moodle/category:update', $systemcontext)) { // speedup for non-admins, add all caps used on this page
+ or has_capability('moodle/category:manage', $systemcontext)
+ or has_capability('moodle/course:create', $systemcontext)) { // speedup for non-admins, add all caps used on this page
-
- $ADMIN->add('courses', new admin_externalpage('coursemgmt', get_string('coursemgmt', 'admin'), $CFG->wwwroot . '/course/index.php?categoryedit=on','moodle/category:update'));
+ $ADMIN->add('courses', new admin_externalpage('coursemgmt', get_string('coursemgmt', 'admin'), $CFG->wwwroot . '/course/index.php?categoryedit=on',
+ array('moodle/category:manage', 'moodle/course:create')));
$ADMIN->add('courses', new admin_enrolment_page());
View
311 course/category.php
@@ -6,25 +6,23 @@
require_once("../config.php");
require_once("lib.php");
- $id = required_param('id', PARAM_INT); // Category id
- $page = optional_param('page', 0, PARAM_INT); // which page to show
- $perpage = optional_param('perpage', $CFG->coursesperpage, PARAM_INT); // how many per page
+ $id = required_param('id', PARAM_INT); // Category id
+ $page = optional_param('page', 0, PARAM_INT); // which page to show
+ $perpage = optional_param('perpage', $CFG->coursesperpage, PARAM_INT); // how many per page
$categoryedit = optional_param('categoryedit', -1, PARAM_BOOL);
- $hide = optional_param('hide', 0, PARAM_INT);
- $show = optional_param('show', 0, PARAM_INT);
- $moveup = optional_param('moveup', 0, PARAM_INT);
- $movedown = optional_param('movedown', 0, PARAM_INT);
- $moveto = optional_param('moveto', 0, PARAM_INT);
- $rename = optional_param('rename', '', PARAM_TEXT);
- $resort = optional_param('resort', 0, PARAM_BOOL);
- $categorytheme= optional_param('categorytheme', false, PARAM_SAFEDIR);
+ $hide = optional_param('hide', 0, PARAM_INT);
+ $show = optional_param('show', 0, PARAM_INT);
+ $moveup = optional_param('moveup', 0, PARAM_INT);
+ $movedown = optional_param('movedown', 0, PARAM_INT);
+ $moveto = optional_param('moveto', 0, PARAM_INT);
+ $resort = optional_param('resort', 0, PARAM_BOOL);
if ($CFG->forcelogin) {
require_login();
}
if (!$site = get_site()) {
- error("Site isn't defined!");
+ error('Site isn\'t defined!');
}
if (empty($id)) {
@@ -38,45 +36,24 @@
if (!$category = get_record("course_categories", "id", $id)) {
error("Category not known!");
}
+ if (!$category->visible) {
+ require_capability('moodle/category:viewhiddencategories', $context);
+ }
- if (has_capability('moodle/course:create', $context)) {
+ if (update_category_button($category->id)) {
if ($categoryedit !== -1) {
$USER->categoryediting = $categoryedit;
}
- $navbaritem = update_category_button($category->id);
- $creatorediting = !empty($USER->categoryediting);
- $adminediting = (has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM)) and $creatorediting);
-
+ $editingon = !empty($USER->categoryediting);
+ $navbaritem = update_category_button($category->id); // Must call this again after updating the state.
} else {
- if (!$category->visible) {
- print_error('notavailable', 'error');
- }
$navbaritem = print_course_search("", true, "navbar");
- $adminediting = false;
- $creatorediting = false;
+ $editingon = false;
}
- if (has_capability('moodle/category:update', $context)) {
- /// Rename the category if requested
- if (!empty($rename) and confirm_sesskey()) {
- if (! set_field("course_categories", "name", $rename, "id", $category->id)) {
- notify("An error occurred while renaming the category");
- }
- $category->name = stripslashes($rename);
- //trigger events
- events_trigger('course_category_updated', $category);
- }
-
- /// Set the category theme if requested
- if (($categorytheme !== false) and confirm_sesskey()) {
- $category->theme = $categorytheme;
- if (! set_field('course_categories', 'theme', $category->theme, 'id', $category->id)) {
- notify('An error occurred while setting the theme');
- }
- }
-
+ // Process any category actions.
+ if (has_capability('moodle/category:manage', $context)) {
/// Resort the category if requested
-
if ($resort and confirm_sesskey()) {
if ($courses = get_courses($category->id, "fullname ASC", 'c.id,c.fullname,c.sortorder')) {
// move it off the range
@@ -94,88 +71,75 @@
}
}
- if(! empty($CFG->allowcategorythemes) ){
- if(isset($category->theme)){
- // specifying theme here saves us some dbqs
- theme_setup($category->theme);
- }
+ if(!empty($CFG->allowcategorythemes) && isset($category->theme)) {
+ // specifying theme here saves us some dbqs
+ theme_setup($category->theme);
}
/// Print headings
+ $numcategories = count_records('course_categories');
- $numcategories = count_records("course_categories");
-
- $stradministration = get_string("administration");
- $strcategories = get_string("categories");
- $strcategory = get_string("category");
- $strcourses = get_string("courses");
+ $stradministration = get_string('administration');
+ $strcategories = get_string('categories');
+ $strcategory = get_string('category');
+ $strcourses = get_string('courses');
$navlinks = array();
$navlinks[] = array('name' => $strcategories, 'link' => 'index.php', 'type' => 'misc');
$navlinks[] = array('name' => format_string($category->name), 'link' => null, 'type' => 'misc');
$navigation = build_navigation($navlinks);
- if ($creatorediting) {
- if ($adminediting) {
- // modify this to treat this as an admin page
-
- require_once($CFG->libdir.'/adminlib.php');
- admin_externalpage_setup('coursemgmt');
- admin_externalpage_print_header();
- } else {
- print_header("$site->shortname: $category->name", "$site->fullname: $strcourses", $navigation, "", "", true, $navbaritem);
- }
+ if ($editingon && update_category_button()) {
+ // Integrate into the admin tree only if the user can edit categories at the top level,
+ // otherwise the admin block does not appear to this user, and you get an error.
+ require_once($CFG->libdir.'/adminlib.php');
+ admin_externalpage_setup('coursemgmt');
+ admin_externalpage_print_header();
} else {
- print_header("$site->shortname: $category->name", "$site->fullname: $strcourses", $navigation, "", "", true, $navbaritem);
+ print_header("$site->shortname: $category->name", "$site->fullname: $strcourses", $navigation, '', '', true, $navbaritem);
}
/// Print button to turn editing off
- if ($adminediting) {
+ if ($editingon) {
echo '<div class="categoryediting button">'.update_category_button($category->id).'</div>';
}
/// Print link to roles
-
if (has_capability('moodle/role:assign', $context)) {
echo '<div class="rolelink"><a href="'.$CFG->wwwroot.'/'.$CFG->admin.'/roles/assign.php?contextid='.
$context->id.'">'.get_string('assignroles','role').'</a></div>';
}
-/// Print the category selector
+/// Print the category selector
$displaylist = array();
- $parentlist = array();
-
- make_categories_list($displaylist, $parentlist, "");
+ $notused = array();
+ make_categories_list($displaylist, $notused);
echo '<div class="categorypicker">';
popup_form('category.php?id=', $displaylist, 'switchcategory', $category->id, '', '', '', false, 'self', $strcategories.':');
echo '</div>';
/// Print current category description
- if (!$creatorediting && $category->description) {
+ if (!$editingon && $category->description) {
print_box_start();
echo format_text($category->description); // for multilang filter
print_box_end();
}
-/// Editing functions
-
- if ($creatorediting) {
+/// Process any course actions.
+ if ($editingon) {
/// Move a specified course to a new category
-
if (!empty($moveto) and $data = data_submitted() and confirm_sesskey()) { // Some courses are being moved
-
// user must have category update in both cats to perform this
- require_capability('moodle/category:update', $context);
- require_capability('moodle/category:update', get_context_instance(CONTEXT_COURSECAT, $moveto));
+ require_capability('moodle/category:manage', $context);
+ require_capability('moodle/category:manage', get_context_instance(CONTEXT_COURSECAT, $moveto));
- if (! $destcategory = get_record("course_categories", "id", $data->moveto)) {
- error("Error finding the category");
+ if (!$destcategory = get_record('course_categories', 'id', $data->moveto)) {
+ error('Error finding the category');
}
-
$courses = array();
- foreach ( $data as $key => $value ) {
+ foreach ($data as $key => $value) {
if (preg_match('/^c\d+$/', $key)) {
array_push($courses, substr($key, 1));
}
@@ -184,90 +148,80 @@
}
/// Hide or show a course
-
if ((!empty($hide) or !empty($show)) and confirm_sesskey()) {
require_capability('moodle/course:visibility', $context);
if (!empty($hide)) {
- $course = get_record("course", "id", $hide);
+ $course = get_record('course', 'id', $hide);
$visible = 0;
} else {
- $course = get_record("course", "id", $show);
+ $course = get_record('course', 'id', $show);
$visible = 1;
}
if ($course) {
- if (! set_field("course", "visible", $visible, "id", $course->id)) {
- notify("Could not update that course!");
+ if (!set_field('course', 'visible', $visible, 'id', $course->id)) {
+ notify('Could not update that course!');
}
}
}
-
/// Move a course up or down
-
if ((!empty($moveup) or !empty($movedown)) and confirm_sesskey()) {
- require_capability('moodle/category:update', $context);
+ require_capability('moodle/category:manage', $context);
$movecourse = NULL;
$swapcourse = NULL;
- // ensure the course order has no gaps
- // and isn't at 0
+ // ensure the course order has no gaps and isn't at 0
fix_course_sortorder($category->id);
// we are going to need to know the range
$max = get_record_sql('SELECT MAX(sortorder) AS max, 1
- FROM ' . $CFG->prefix . 'course WHERE category=' . $category->id);
+ FROM ' . $CFG->prefix . 'course WHERE category=' . $category->id);
$max = $max->max + 100;
if (!empty($moveup)) {
$movecourse = get_record('course', 'id', $moveup);
- $swapcourse = get_record('course',
- 'category', $category->id,
- 'sortorder', $movecourse->sortorder - 1);
+ $swapcourse = get_record('course', 'category', $category->id,
+ 'sortorder', $movecourse->sortorder - 1);
} else {
$movecourse = get_record('course', 'id', $movedown);
- $swapcourse = get_record('course',
- 'category', $category->id,
- 'sortorder', $movecourse->sortorder + 1);
+ $swapcourse = get_record('course', 'category', $category->id,
+ 'sortorder', $movecourse->sortorder + 1);
}
- if ($swapcourse and $movecourse) { // Renumber everything for robustness
+ if ($swapcourse and $movecourse) {
+ // Renumber everything for robustness
begin_sql();
- if (!( set_field("course", "sortorder", $max, "id", $swapcourse->id)
- && set_field("course", "sortorder", $swapcourse->sortorder, "id", $movecourse->id)
- && set_field("course", "sortorder", $movecourse->sortorder, "id", $swapcourse->id)
+ if (!( set_field('course', 'sortorder', $max, 'id', $swapcourse->id)
+ && set_field('course', 'sortorder', $swapcourse->sortorder, 'id', $movecourse->id)
+ && set_field('course', 'sortorder', $movecourse->sortorder, 'id', $swapcourse->id)
)) {
- notify("Could not update that course!");
+ notify('Could not update that course!');
}
commit_sql();
}
}
-
} // End of editing stuff
+ if ($editingon && has_capability('moodle/category:manage', $context)) {
+ echo '<div class="buttons">';
- if ($creatorediting) {
- echo '<div class="buttons">';
- if (has_capability('moodle/category:update', $context)) { // Print button to update this category
- unset($options);
- $options['id'] = $category->id;
- print_single_button('editcategory.php', $options, get_string('editcategorythis'), 'get');
- }
+ // Print button to update this category
+ $options = array('id' => $category->id);
+ print_single_button($CFG->wwwroot.'/course/editcategory.php', $options, get_string('editcategorythis'), 'get');
+
+ // Print button for creating new categories
+ $options = array('parent' => $category->id);
+ print_single_button($CFG->wwwroot.'/course/editcategory.php', $options, get_string('addsubcategory'), 'get');
- if (has_capability('moodle/category:create', $context)) { // Print button for creating new categories
- unset($options);
- $options['categoryadd'] = 1;
- $options['id'] = $id;
- print_single_button('editcategory.php', $options, get_string('addsubcategory'), 'get');
- }
echo '</div>';
}
/// Print out all the sub-categories
- if ($subcategories = get_records("course_categories", "parent", $category->id, "sortorder ASC")) {
+ if ($subcategories = get_records('course_categories', 'parent', $category->id, 'sortorder ASC')) {
$firstentry = true;
foreach ($subcategories as $subcategory) {
- if ($subcategory->visible or has_capability('moodle/course:create', $context)) {
+ if ($subcategory->visible || has_capability('moodle/category:viewhiddencategories', $context)) {
$subcategorieswereshown = true;
if ($firstentry) {
echo '<table border="0" cellspacing="2" cellpadding="4" class="generalbox boxaligncenter">';
@@ -275,24 +229,22 @@
echo '<tr><td style="white-space: nowrap">';
$firstentry = false;
}
- $catlinkcss = $subcategory->visible ? "" : " class=\"dimmed\" ";
+ $catlinkcss = $subcategory->visible ? '' : 'class="dimmed" ';
echo '<a '.$catlinkcss.' href="category.php?id='.$subcategory->id.'">'.
format_string($subcategory->name).'</a><br />';
}
}
if (!$firstentry) {
- echo "</td></tr></table>";
- echo "<br />";
+ echo '</td></tr></table>';
+ echo '<br />';
}
}
/// Print out all the courses
- unset($course); // To avoid unwanted language effects later
-
$courses = get_courses_page($category->id, 'c.sortorder ASC',
- 'c.id,c.sortorder,c.shortname,c.fullname,c.summary,c.visible,c.teacher,c.guest,c.password',
- $totalcount, $page*$perpage, $perpage);
+ 'c.id,c.sortorder,c.shortname,c.fullname,c.summary,c.visible,c.teacher,c.guest,c.password',
+ $totalcount, $page*$perpage, $perpage);
$numcourses = count($courses);
if (!$courses) {
@@ -300,7 +252,7 @@
print_heading(get_string("nocoursesyet"));
}
- } else if ($numcourses <= COURSE_MAX_SUMMARIES_PER_PAGE and !$page and !$creatorediting) {
+ } else if ($numcourses <= COURSE_MAX_SUMMARIES_PER_PAGE and !$page and !$editingon) {
print_box_start('courseboxes');
print_courses($category);
print_box_end();
@@ -308,33 +260,31 @@
} else {
print_paging_bar($totalcount, $page, $perpage, "category.php?id=$category->id&amp;perpage=$perpage&amp;");
- $strcourses = get_string("courses");
- $strselect = get_string("select");
- $stredit = get_string("edit");
- $strdelete = get_string("delete");
- $strbackup = get_string("backup");
- $strrestore = get_string("restore");
- $strmoveup = get_string("moveup");
- $strmovedown = get_string("movedown");
- $strupdate = get_string("update");
- $strhide = get_string("hide");
- $strshow = get_string("show");
- $strsummary = get_string("summary");
- $strsettings = get_string("settings");
- $strassignteachers = get_string("assignteachers");
- $strallowguests = get_string("allowguests");
- $strrequireskey = get_string("requireskey");
+ $strcourses = get_string('courses');
+ $strselect = get_string('select');
+ $stredit = get_string('edit');
+ $strdelete = get_string('delete');
+ $strbackup = get_string('backup');
+ $strrestore = get_string('restore');
+ $strmoveup = get_string('moveup');
+ $strmovedown = get_string('movedown');
+ $strupdate = get_string('update');
+ $strhide = get_string('hide');
+ $strshow = get_string('show');
+ $strsummary = get_string('summary');
+ $strsettings = get_string('settings');
+ $strassignteachers = get_string('assignteachers');
+ $strallowguests = get_string('allowguests');
+ $strrequireskey = get_string('requireskey');
echo '<form id="movecourses" action="category.php" method="post"><div>';
echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
echo '<table border="0" cellspacing="2" cellpadding="4" class="generalbox boxaligncenter"><tr>';
echo '<th class="header" scope="col">'.$strcourses.'</th>';
- if ($creatorediting) {
+ if ($editingon) {
echo '<th class="header" scope="col">'.$stredit.'</th>';
- if ($adminediting) {
- echo '<th class="header" scope="col">'.$strselect.'</th>';
- }
+ echo '<th class="header" scope="col">'.$strselect.'</th>';
} else {
echo '<th class="header" scope="col">&nbsp;</th>';
}
@@ -358,6 +308,7 @@
$atlastpage = true;
}
+ $spacer = '<img src="'.$CFG->wwwroot.'/pix/spacer.gif" class="iconsmall" alt="" /> ';
foreach ($courses as $acourse) {
if (isset($acourse->context)) {
$coursecontext = $acourse->context;
@@ -369,24 +320,31 @@
$up = ($count > 1 || !$atfirstpage);
$down = ($count < $numcourses || !$atlastpage);
- $linkcss = $acourse->visible ? "" : ' class="dimmed" ';
+ $linkcss = $acourse->visible ? '' : ' class="dimmed" ';
echo '<tr>';
echo '<td><a '.$linkcss.' href="view.php?id='.$acourse->id.'">'. format_string($acourse->fullname) .'</a></td>';
- if ($creatorediting) {
- echo "<td>";
+ if ($editingon) {
+ echo '<td>';
if (has_capability('moodle/course:update', $coursecontext)) {
- echo '<a title="'.$strsettings.'" href="'.$CFG->wwwroot.'/course/edit.php?id='.
- $acourse->id.'">'.
- '<img src="'.$CFG->pixpath.'/t/edit.gif" class="iconsmall" alt="'.$stredit.'" /></a> '; }
+ echo '<a title="'.$strsettings.'" href="'.$CFG->wwwroot.'/course/edit.php?id='.$acourse->id.'">'.
+ '<img src="'.$CFG->pixpath.'/t/edit.gif" class="iconsmall" alt="'.$stredit.'" /></a> ';
+ } else {
+ echo $spacer;
+ }
// role assignment link
if (has_capability('moodle/role:assign', $coursecontext)) {
- echo'<a title="'.get_string('assignroles', 'role').'" href="'.$CFG->wwwroot.'/'.$CFG->admin.'/roles/assign.php?contextid='.$coursecontext->id.'"><img src="'.$CFG->pixpath.'/i/roles.gif" class="iconsmall" alt="'.get_string('assignroles', 'role').'" /></a>';
+ echo '<a title="'.get_string('assignroles', 'role').'" href="'.$CFG->wwwroot.'/'.$CFG->admin.'/roles/assign.php?contextid='.$coursecontext->id.'">'.
+ '<img src="'.$CFG->pixpath.'/i/roles.gif" class="iconsmall" alt="'.get_string('assignroles', 'role').'" /></a> ';
+ } else {
+ echo $spacer;
}
if (can_delete_course($acourse->id)) {
echo '<a title="'.$strdelete.'" href="delete.php?id='.$acourse->id.'">'.
'<img src="'.$CFG->pixpath.'/t/delete.gif" class="iconsmall" alt="'.$strdelete.'" /></a> ';
+ } else {
+ echo $spacer;
}
// MDL-8885, users with no capability to view hidden courses, should not be able to lock themselves out
@@ -400,26 +358,32 @@
'&amp;perpage='.$perpage.'&amp;show='.$acourse->id.'&amp;sesskey='.$USER->sesskey.'">'.
'<img src="'.$CFG->pixpath.'/t/show.gif" class="iconsmall" alt="'.$strshow.'" /></a> ';
}
+ } else {
+ echo $spacer;
}
if (has_capability('moodle/site:backup', $coursecontext)) {
echo '<a title="'.$strbackup.'" href="../backup/backup.php?id='.$acourse->id.'">'.
'<img src="'.$CFG->pixpath.'/t/backup.gif" class="iconsmall" alt="'.$strbackup.'" /></a> ';
+ } else {
+ echo $spacer;
}
if (has_capability('moodle/site:restore', $coursecontext)) {
echo '<a title="'.$strrestore.'" href="../files/index.php?id='.$acourse->id.
'&amp;wdir=/backupdata">'.
'<img src="'.$CFG->pixpath.'/t/restore.gif" class="iconsmall" alt="'.$strrestore.'" /></a> ';
+ } else {
+ echo $spacer;
}
- if (has_capability('moodle/category:update', $context)) {
+ if (has_capability('moodle/category:manage', $context)) {
if ($up) {
echo '<a title="'.$strmoveup.'" href="category.php?id='.$category->id.'&amp;page='.$page.
'&amp;perpage='.$perpage.'&amp;moveup='.$acourse->id.'&amp;sesskey='.$USER->sesskey.'">'.
'<img src="'.$CFG->pixpath.'/t/up.gif" class="iconsmall" alt="'.$strmoveup.'" /></a> ';
} else {
- echo '<img src="'.$CFG->wwwroot.'/pix/spacer.gif" class="iconsmall" alt="" /> ';
+ echo $spacer;
}
if ($down) {
@@ -427,9 +391,11 @@
'&amp;perpage='.$perpage.'&amp;movedown='.$acourse->id.'&amp;sesskey='.$USER->sesskey.'">'.
'<img src="'.$CFG->pixpath.'/t/down.gif" class="iconsmall" alt="'.$strmovedown.'" /></a> ';
} else {
- echo '<img src="'.$CFG->wwwroot.'/pix/spacer.gif" class="iconsmall" alt="" /> ';
+ echo $spacer;
}
$abletomovecourses = true;
+ } else {
+ echo $spacer, $spacer;
}
echo '</td>';
@@ -459,19 +425,12 @@
}
if ($abletomovecourses) {
+ $movetocategories = array();
+ $notused = array();
+ make_categories_list($movetocategories, $notused, 'moodle/category:manage');
+ $movetocategories[$category->id] = get_string('moveselectedcoursesto');
echo '<tr><td colspan="3" align="right">';
- echo '<br />';
- unset($displaylist[$category->id]);
-
- // loop and unset categories the user can't move into
-
- foreach ($displaylist as $did=>$dlist) {
- if (!has_capability('moodle/category:update', get_context_instance(CONTEXT_COURSECAT, $did))) {
- unset($displaylist[$did]);
- }
- }
-
- choose_from_menu ($displaylist, "moveto", "", get_string("moveselectedcoursesto"), "javascript: submitFormById('movecourses')");
+ choose_from_menu($movetocategories, 'moveto', $category->id, '', "javascript:submitFormById('movecourses')");
echo '<input type="hidden" name="id" value="'.$category->id.'" />';
echo '</td></tr>';
}
@@ -481,8 +440,9 @@
echo '<br />';
}
- echo '<div class="buttons">';
- if (has_capability('moodle/category:update', get_context_instance(CONTEXT_SYSTEM)) and $numcourses > 1) { /// Print button to re-sort courses by name
+ echo '<div class="buttons">';
+ if (has_capability('moodle/category:manage', $context) and $numcourses > 1) {
+ /// Print button to re-sort courses by name
unset($options);
$options['id'] = $category->id;
$options['resort'] = 'name';
@@ -490,14 +450,13 @@
print_single_button('category.php', $options, get_string('resortcoursesbyname'), 'get');
}
- if (has_capability('moodle/course:create', $context)) { /// Print button to create a new course
+ if (has_capability('moodle/course:create', $context)) {
+ /// Print button to create a new course
unset($options);
$options['category'] = $category->id;
print_single_button('edit.php', $options, get_string('addnewcourse'), 'get');
}
- echo '</div>';
-
-
+ echo '</div>';
print_course_search();
View
32 course/delete_category_form.php
@@ -11,36 +11,30 @@ function definition() {
$mform =& $this->_form;
$category = $this->_customdata;
+ ensure_context_subobj_present($category, CONTEXT_COURSECAT);
$this->_category = $category;
$mform->addElement('header','general', get_string('categorycurrentcontents', '', format_string($category->name)));
$displaylist = array();
- $parentlist = array();
- $children = array();
- make_categories_list($displaylist, $parentlist);
- unset($displaylist[$category->id]);
- foreach ($displaylist as $catid=>$unused) {
- // remove all children of $category
- if (isset($parentlist[$catid]) and in_array($category->id, $parentlist[$catid])) {
- $children[] = $catid;
- unset($displaylist[$catid]);
- continue;
- }
- if (!has_capability('moodle/course:create', get_context_instance(CONTEXT_COURSECAT, $catid))) {
- unset($displaylist[$catid]);
- }
- }
+ $notused = array();
+ make_categories_list($displaylist, $notused, 'moodle/course:create', $category->id);
+ // Check permissions, to see if it OK to give the option to delete
+ // the contents, rather than move elsewhere.
$candeletecontent = true;
- foreach ($children as $catid) {
- $context = get_context_instance(CONTEXT_COURSECAT, $catid);
- if (!has_capability('moodle/category:delete', $context)) {
+ $tocheck = array($category);
+ while (!empty($tocheck)) {
+ $checkcat = array_pop($tocheck);
+ $tocheck = $tocheck + get_child_categories($checkcat->id);
+ if (!has_capability('moodle/category:manage', $checkcat->context)) {
$candeletecontent = false;
break;
}
}
+ // TODO check that the user is allowed to delete all the courses MDL-17502!
+
$options = array();
if ($displaylist) {
@@ -48,7 +42,7 @@ function definition() {
}
if ($candeletecontent) {
- $options[1] =get_string('delete');
+ $options[1] = get_string('delete');
}
if (empty($options)) {
View
9 course/edit_form.php
@@ -56,16 +56,11 @@ function definition() {
//--------------------------------------------------------------------------------
$mform->addElement('header','general', get_string('general', 'form'));
- //must have create course capability in both categories in order to move course
+ // Must have create course capability in both categories in order to move course
if (has_capability('moodle/course:create', $categorycontext)) {
$displaylist = array();
$parentlist = array();
- make_categories_list($displaylist, $parentlist);
- foreach ($displaylist as $key=>$val) {
- if (!has_capability('moodle/course:create', get_context_instance(CONTEXT_COURSECAT, $key))) {
- unset($displaylist[$key]);
- }
- }
+ make_categories_list($displaylist, $parentlist, 'moodle/course:create');
$mform->addElement('select', 'category', get_string('category'), $displaylist);
} else {
$mform->addElement('hidden', 'category', null);
View
340 course/editcategory.php
@@ -1,323 +1,93 @@
<?php // $Id$
/**
- * Displays a category and all its sub-categories.
- * In editing mode, allows admins to move/delete/hide categories
+ * Page for creating or editing course category name/parent/description.
+ * When called with an id parameter, edits the category with that id.
+ * Otherwise it creates a new category with default parent from the parent
+ * parameter, which may be 0.
*/
-require_once("../config.php");
-require_once("lib.php");
+require_once('../config.php');
+require_once('lib.php');
require_once('editcategory_form.php');
-$id = optional_param('id', 0, PARAM_INT); // Category id: if not given, show Add a Category form. If given and 'categoryupdate': show edit form
-$page = optional_param('page', 0, PARAM_INT); // which page to show
-$perpage = optional_param('perpage', $CFG->coursesperpage, PARAM_INT); // how many per page
-$hide = optional_param('hide', 0, PARAM_INT);
-$show = optional_param('show', 0, PARAM_INT);
-$moveup = optional_param('moveup', 0, PARAM_INT);
-$movedown = optional_param('movedown', 0, PARAM_INT);
-$moveto = optional_param('moveto', 0, PARAM_INT);
-$categoryedit = optional_param('categoryedit', -1, PARAM_BOOL); // Enables Move/Delete/Hide icons near each category in the list
-$categoryadd = optional_param('categoryadd', 0, PARAM_BOOL); // Enables the Add Category form
-$categoryupdate = optional_param('categoryupdate', 0, PARAM_BOOL); // Enables the Edit Category form
-$resort = optional_param('resort', 0, PARAM_BOOL);
-$parent = optional_param('parent', 0, PARAM_INT );
+require_login();
-if (!$site = get_site()) {
- error("Site isn't defined!");
-}
-
-if ($categoryadd and !$parent) { // Show Add category form: if $id is given, it is used as the parent category
- $strtitle = get_string("addnewcategory");
- $context = get_context_instance(CONTEXT_SYSTEM);
- $category = null;
-} elseif ($categoryadd and $parent) {
- $strtitle = get_string("addnewcategory");
- $context = get_context_instance(CONTEXT_COURSECAT,$parent);
- $category = null;
-} elseif (!is_null($id) && !$categoryadd) { // Show Edit category form: $id is given as the identifier of the category being edited
- $strtitle = get_string("editcategorysettings");
- $context = get_context_instance(CONTEXT_COURSECAT, $id);
- if (!$category = get_record("course_categories", "id", $id)) {
+$id = optional_param('id', 0, PARAM_INT);
+if ($id) {
+ if (!$category = get_record('course_categories', 'id', $id)) {
error("Category not known!");
}
+ require_capability('moodle/category:manage', get_context_instance(CONTEXT_COURSECAT, $id));
+ $strtitle = get_string('editcategorysettings');
+} else {
+ $parent = required_param('parent', PARAM_INT);
+ if ($parent) {
+ if (!record_exists('course_categories', 'id', $parent)) {
+ error('Unknown parent category ' . $parent);
+ }
+ $context = get_context_instance(CONTEXT_COURSECAT, $parent);
+ } else {
+ $context = get_system_context();
+ }
+ $category = new stdClass();
+ $category->id = 0;
+ $category->parent = $parent;
+ require_capability('moodle/category:manage', $context);
+ $strtitle = get_string("addnewcategory");
}
-$mform = new editcategory_form('editcategory.php', compact(array('category', 'id')));
+$mform = new editcategory_form('editcategory.php', $category);
+$mform->set_data($category);
-if (!empty($category)) {
- $mform->set_data($category);
-} elseif (!is_null($id)) {
- $data = new stdClass();
- $data->parent = $id;
- $data->categoryadd = 1;
- $mform->set_data($data);
-}
-
-if ($mform->is_cancelled()){
- if (empty($category)) {
- redirect($CFG->wwwroot .'/course/index.php?categoryedit=on');
+if ($mform->is_cancelled()) {
+ if ($id) {
+ redirect($CFG->wwwroot . '/course/category.php?id=' . $id . '&categoryedit=on');
+ } else if ($parent) {
+ redirect($CFG->wwwroot .'/course/category.php?id=' . $parent . '&categoryedit=on');
} else {
- redirect($CFG->wwwroot.'/course/category.php?categoryedit=on&id='.$category->id);
- }
-} else if (($data = $mform->get_data())) {
+ redirect($CFG->wwwroot .'/course/index.php?categoryedit=on');
+ }
+} else if ($data = $mform->get_data()) {
$newcategory = new stdClass();
$newcategory->name = $data->name;
$newcategory->description = $data->description;
- $newcategory->sortorder = 999;
- $newcategory->parent = $data->parent; // if $id = 0, the new category will be a top-level category
+ $newcategory->parent = $data->parent; // if $data->parent = 0, the new category will be a top-level category
if (isset($data->theme) && !empty($CFG->allowcategorythemes)) {
$newcategory->theme = $data->theme;
- theme_setup(); /// TODO: Do we really want the theme to be changed here? Doesn't look ok IMO. Eloy - 20080828
}
- if (empty($category) && has_capability('moodle/category:create', $context)) { // Create a new category
- if (!$newcategory->id = insert_record('course_categories', $newcategory)) {
- notify( "Could not insert the new category '$newcategory->name' ");
- } else {
- $newcategory->context = get_context_instance(CONTEXT_COURSECAT, $newcategory->id);
- mark_context_dirty($newcategory->context->path);
- redirect('index.php?categoryedit=on');
- }
- } elseif (has_capability('moodle/category:update', $context)) {
+ if ($id) {
+ // Update an existing category.
$newcategory->id = $category->id;
-
if ($newcategory->parent != $category->parent) {
$parent_cat = get_record('course_categories', 'id', $newcategory->parent);
move_category($newcategory, $parent_cat);
}
-
if (!update_record('course_categories', $newcategory)) {
error( "Could not update the category '$newcategory->name' ");
- } else {
- if ($newcategory->parent == 0) {
- $redirect_link = 'index.php?categoryedit=on';
- } else {
- $redirect_link = 'category.php?id='.$newcategory->id.'&categoryedit=on';
- }
- fix_course_sortorder();
- redirect($redirect_link);
- }
- }
-}
-
-
-
-// If id is given, but not categoryadd or categoryupdate, we show the category with its list of subcategories
-if ($id && !$categoryadd && !$categoryupdate && false) {
- /* TODO implement
-
- if ($CFG->forcelogin) {
- require_login();
- }
-
- // Determine whether to allow user to see this category
- if (has_capability('moodle/course:create', $context)) {
- if ($categoryedit !== -1) {
- $USER->categoryediting = $categoryedit;
}
- $navbaritem = update_category_button($category->id);
- $creatorediting = !empty($USER->categoryediting);
- $adminediting = (has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM)) and $creatorediting);
-
- } else {
- if (!$category->visible) {
- print_error('notavailable', 'error');
- }
- $navbaritem = print_course_search("", true, "navbar");
- $adminediting = false;
- $creatorediting = false;
- }
-
- // Resort the category if requested
- if ($resort and confirm_sesskey()) {
- if ($courses = get_courses($id, "fullname ASC", 'c.id,c.fullname,c.sortorder')) {
- // move it off the range
- $count = get_record_sql('SELECT MAX(sortorder) AS max, 1
- FROM ' . $CFG->prefix . 'course WHERE category=' . $category->id);
- $count = $count->max + 100;
- begin_sql();
- foreach ($courses as $course) {
- set_field('course', 'sortorder', $count, 'id', $course->id);
- $count++;
- }
- commit_sql();
- fix_course_sortorder($category->id);
- }
- }
-
- // Print headings
- $numcategories = count_records("course_categories");
-
- $stradministration = get_string("administration");
- $strcategories = get_string("categories");
- $strcategory = get_string("category");
- $strcourses = get_string("courses");
-
- $navlinks = array();
- $navlinks[] = array('name' => $strcategories, 'link' => 'index.php', 'type' => 'misc');
- $navlinks[] = array('name' => $category->name, 'link' => null, 'type' => 'misc');
- $navigation = build_navigation($navlinks);
-
- if ($creatorediting) {
- if ($adminediting) {
- // modify this to treat this as an admin page
+ fix_course_sortorder();
- require_once($CFG->libdir.'/adminlib.php');
- admin_externalpage_setup('categorymgmt');
- admin_externalpage_print_header();
- } else {
- print_header("$site->shortname: $category->name", "$site->fullname: $strcategories", $navigation, "", "", true, $navbaritem);
- }
} else {
- print_header("$site->shortname: $category->name", "$site->fullname: $strcategories", $navigation, "", "", true, $navbaritem);
- }
-
- // Print button to turn editing off
- if ($adminediting) {
- echo '<div class="categoryediting button" align="right">'.update_category_button($category->id).'</div>';
- }
-
- // Print link to roles
-
- if (has_capability('moodle/role:assign', $context)) {
- echo '<div class="rolelink"><a href="'.$CFG->wwwroot.'/'.$CFG->admin.'/roles/assign.php?contextid='.
- $context->id.'">'.get_string('assignroles','role').'</a></div>';
- }
-
- // Print the category selector
-
- $displaylist = array();
- $parentlist = array();
-
- make_categories_list($displaylist, $parentlist, "");
-
- echo '<div class="categorypicker">';
- popup_form('category.php?id=', $displaylist, 'switchcategory', $category->id, '', '', '', false, 'self', $strcategories.':');
- echo '</div>';
-
- // Print current category description
- if ($category->description) {
- print_box_start();
- print_heading(get_string('description'));
- echo $category->description;
- print_box_end();
- }
-
- // Editing functions
- if ($creatorediting) {
- // Move a specified category to a new category
-
- if (!empty($moveto) and $data = data_submitted() and confirm_sesskey()) { // Some courses are being moved
-
- // user must have category update in both cats to perform this
- require_capability('moodle/category:update', $context);
- require_capability('moodle/category:update', get_context_instance(CONTEXT_COURSECAT, $moveto));
-
- if (!$destcategory = get_record("course_categories", "id", $data->moveto)) {
- error("Error finding the destination category");
- }
- // TODO function to move the category
- }
-
- // Hide or show a category
- if ((!empty($hide) or !empty($show)) and confirm_sesskey()) {
- require_capability('moodle/category:visibility', $context);
- if (!empty($hide)) {
- $category = get_record("course_categories", "id", $hide);
- $visible = 0;
- } else {
- $category = get_record("course_categories", "id", $show);
- $visible = 1;
- }
- if ($category) {
- if (! set_field("course_categories", "visible", $visible, "id", $category->id)) {
- notify("Could not update that category!");
- }
- }
- }
-
-
- // Move a category up or down
- if ((!empty($moveup) or !empty($movedown)) and confirm_sesskey()) {
- require_capability('moodle/category:update', $context);
- $movecategory = NULL;
- $swapcategory = NULL;
-
- // TODO something like fix_course_sortorder() ?
-
- // we are going to need to know the range
- $max = get_record_sql('SELECT MAX(sortorder) AS max, 1 FROM ' . $CFG->prefix . 'course_categories WHERE id=' . $category->id);
- $max = $max->max + 100;
-
- if (!empty($moveup)) {
- $movecategory = get_record('course_categories', 'id', $moveup);
- $swapcategory = get_record('course_categories',
- 'category', $category->id,
- 'sortorder', $movecategory->sortorder - 1);
- } else {
- $movecategory = get_record('course_categories', 'id', $movedown);
- $swapcategory = get_record('course_categories',
- 'category', $category->id,
- 'sortorder', $movecategory->sortorder + 1);
- }
-
- if ($swapcourse and $movecourse) { // Renumber everything for robustness
- begin_sql();
- if (!( set_field("course", "sortorder", $max, "id", $swapcourse->id)
- && set_field("course", "sortorder", $swapcourse->sortorder, "id", $movecourse->id)
- && set_field("course", "sortorder", $movecourse->sortorder, "id", $swapcourse->id)
- )) {
- notify("Could not update that course!");
- }
- commit_sql();
- }
-
- }
-
- } // End of editing stuff
-
- // Print out all the sub-categories
- if ($subcategories = get_records("course_categories", "parent", $category->id, "sortorder ASC")) {
- $firstentry = true;
- foreach ($subcategories as $subcategory) {
- if ($subcategory->visible or has_capability('moodle/course:create', $context)) {
- $subcategorieswereshown = true;
- if ($firstentry) {
- echo '<table border="0" cellspacing="2" cellpadding="4" class="generalbox boxaligncenter">';
- echo '<tr><th scope="col">'.get_string('subcategories').'</th></tr>';
- echo '<tr><td style="white-space: nowrap">';
- $firstentry = false;
- }
- $catlinkcss = $subcategory->visible ? "" : " class=\"dimmed\" ";
- echo '<a '.$catlinkcss.' href="category.php?id='.$subcategory->id.'">'.
- format_string($subcategory->name).'</a><br />';
- }
- }
- if (!$firstentry) {
- echo "</td></tr></table>";
- echo "<br />";
+ // Create a new category.
+ $newcategory->sortorder = 999;
+ if (!$newcategory->id = insert_record('course_categories', $newcategory)) {
+ error("Could not insert the new category '$newcategory->name' ");
}
+ $newcategory->context = get_context_instance(CONTEXT_COURSECAT, $newcategory->id);
+ mark_context_dirty($newcategory->context->path);
}
+ redirect('category.php?id='.$newcategory->id.'&categoryedit=on');
+}
- // print option to add a subcategory
- if (has_capability('moodle/category:create', $context) && $creatorediting) {
- $cat->id = $id;
- $mform->set_data($cat);
- $mform->display();
- }
- */
-}
// Print the form
-
-$site = get_site();
-
-$straddnewcategory = get_string("addnewcategory");
-$stradministration = get_string("administration");
-$strcategories = get_string("categories");
+$straddnewcategory = get_string('addnewcategory');
+$stradministration = get_string('administration');
+$strcategories = get_string('categories');
$navlinks = array();
-if (!empty($category->name)) {
+if ($id) {
$navlinks[] = array('name' => $strtitle,
'link' => null,
'type' => 'misc');
@@ -333,8 +103,8 @@
$navlinks[] = array('name' => $straddnewcategory,
'link' => null,
'type' => 'misc');
- $title = "$site->shortname: $straddnewcategory";
- $fullname = $site->fullname;
+ $title = "$SITE->shortname: $straddnewcategory";
+ $fullname = $SITE->fullname;
}
$navigation = build_navigation($navlinks);
View
28 course/editcategory_form.php
@@ -6,15 +6,24 @@ class editcategory_form extends moodleform {
function definition() {
global $CFG;
$mform =& $this->_form;
-
+ $category = $this->_customdata;
+
// get list of categories to use as parents, with site as the first one
$options = array(get_string('top'));
$parents = array();
- make_categories_list($options, $parents);
-
+ if ($category->id) {
+ // Editing an existing category.
+ make_categories_list($options, $parents, 'moodle/category:manage', $category->id);
+ $strsubmit = get_string('savechanges');
+ } else {
+ // Making a new category
+ make_categories_list($options, $parents, 'moodle/category:manage');
+ $strsubmit = get_string('createcategory');
+ }
+
$mform->addElement('select', 'parent', get_string('parentcategory'), $options);
- $mform->addElement('text', 'name', get_string('categoryname'), array('size'=>'30'));
- $mform->addRule('name', get_string('required'), 'required', null);
+ $mform->addElement('text', 'name', get_string('categoryname'), array('size'=>'30'));
+ $mform->addRule('name', get_string('required'), 'required', null);
$mform->addElement('htmleditor', 'description', get_string('description'));
$mform->setType('description', PARAM_RAW);
if (!empty($CFG->allowcategorythemes)) {
@@ -24,11 +33,12 @@ function definition() {
$mform->addElement('select', 'theme', get_string('forcetheme'), $themes);
}
$mform->setHelpButton('description', array('writing', 'richtext'), false, 'editorhelpbutton');
-
- $mform->addElement('hidden', 'id', null);
- $mform->addElement('hidden', 'categoryadd', 0);
+
+ $mform->addElement('hidden', 'id', 0);
$mform->setType('id', PARAM_INT);
- $this->add_action_buttons(true, get_string('savechanges'));
+ $mform->setDefault('id', $category->id);
+
+ $this->add_action_buttons(true, $strsubmit);
}
}
?>
View
179 course/index.php
@@ -14,18 +14,17 @@
$moveup = optional_param('moveup',0,PARAM_INT);
$movedown = optional_param('movedown',0,PARAM_INT);
- $sysctx = get_context_instance(CONTEXT_SYSTEM);
- $context = $sysctx;
+ if ($CFG->forcelogin) {
+ require_login();
+ }
if (!$site = get_site()) {
error('Site isn\'t defined!');
}
- if ($CFG->forcelogin) {
- require_login();
- }
+ $systemcontext = get_context_instance(CONTEXT_SYSTEM);
- if (has_capability('moodle/category:update', $sysctx)) {
+ if (update_category_button()) {
if ($categoryedit !== -1) {
$USER->categoryediting = $categoryedit;
}
@@ -44,11 +43,9 @@
/// Unless it's an editing admin, just print the regular listing of courses/categories
-
if (!$adminediting) {
- /// Print form for creating new categories
-
+ /// Print form for creating new categories
$countcategories = count_records('course_categories');
if ($countcategories > 1 || ($countcategories == 1 && count_records('course') > 200)) {
@@ -58,7 +55,7 @@
$navlinks = array();
$navlinks[] = array('name'=>$strcategories,'link'=>'','type'=>'misc');
$navigation = build_navigation($navlinks);
- print_header("$site->shortname: $strcategories", $strcourses, $navigation, '', '', true, update_categories_button());
+ print_header("$site->shortname: $strcategories", $strcourses, $navigation, '', '', true, update_category_button());
print_heading($strcategories);
echo skip_main_destination();
print_box_start('categorybox');
@@ -69,45 +66,44 @@
$strfulllistofcourses = get_string('fulllistofcourses');
print_header("$site->shortname: $strfulllistofcourses", $strfulllistofcourses,
build_navigation(array(array('name'=>$strfulllistofcourses, 'link'=>'','type'=>'misc'))),
- '', '', true, update_categories_button());
+ '', '', true, update_category_button());
echo skip_main_destination();
print_box_start('courseboxes');
print_courses(0);
print_box_end();
}
- /// I am not sure this context in the next has_capability call is correct.
- if (isloggedin() and !isguest() and !has_capability('moodle/course:create', $sysctx) and $CFG->enablecourserequests) { // Print link to request a new course
+ echo '<div class="buttons">';
+ if ($CFG->enablecourserequests and isloggedin() and !isguest() and !has_capability('moodle/course:create', $systemcontext)) {
+ /// Print link to request a new course
print_single_button('request.php', NULL, get_string('courserequest'), 'get');
}
- if (has_capability('moodle/course:create', $sysctx)) { // Print link to create a new course
+ if (has_capability('moodle/course:create', $systemcontext)) {
+ /// Print link to create a new course
/// Get the 1st available category
- $options = array('category' => get_field('course_categories', 'id', 'parent', '0'));
+ $options = array('category' => $CFG->defaultrequestcategory);
print_single_button('edit.php', $options, get_string('addnewcourse'), 'get');
}
- if (has_capability('moodle/site:approvecourse', $sysctx) and !empty($CFG->enablecourserequests)) {
+ if (has_capability('moodle/site:approvecourse', $systemcontext) and !empty($CFG->enablecourserequests)) {
print_single_button('pending.php',NULL, get_string('coursespending'),'get');
}
+ echo '</div>';
print_footer();
exit;
}
+/// Everything else is editing on mode.
-/// From now on is all the admin/course creator functions
-
-/// Delete a category if necessary
-
+/// Delete a category.
if (!empty($delete) and confirm_sesskey()) {
- require_once('delete_category_form.php');
-
if (!$deletecat = get_record('course_categories', 'id', $delete)) {
error('Incorrect category id', 'index.php');
}
-
- $heading = get_string('deletecategory', '', format_string($deletecat->name));
-
$context = get_context_instance(CONTEXT_COURSECAT, $delete);
- require_capability('moodle/category:delete', $context);
+ require_capability('moodle/category:manage', $context);
+ require_capability('moodle/category:manage', get_category_or_system_context($deletecat->parent));
+ $heading = get_string('deletecategory', '', format_string($deletecat->name));
+ require_once('delete_category_form.php');
$mform = new delete_category_form(null, $deletecat);
$mform->set_data(array('delete'=>$delete));
@@ -124,7 +120,7 @@
'generalbox boxwidthnormal boxaligncenter');
}
$mform->display();
- print_footer();
+ admin_externalpage_print_footer();
exit();
}
@@ -137,9 +133,14 @@
category_delete_move($deletecat, $data->newparent, true);
}
+ // If we deleted $CFG->defaultrequestcategory, make it point somewhere else.
+ if ($delete == $CFG->defaultrequestcategory) {
+ set_config('defaultrequestcategory', get_field('course_categories', 'MIN(id)', 'parent', 0));
+ }
+
print_continue('index.php');
- print_footer();
+ admin_externalpage_print_footer();
die;
}
@@ -147,7 +148,6 @@
print_category_edit_header();
print_heading($strcategories);
-
/// Create a default category if necessary
if (!$categories = get_categories()) { /// No category yet!
// Try and make one
@@ -160,21 +160,20 @@
mark_context_dirty('/'.SYSCONTEXTID);
}
-
/// Move a category to a new parent if required
-
- if (!empty($move) and ($moveto>=0) and confirm_sesskey()) {
- if ($tempcat = get_record('course_categories', 'id', $move)) {
- if ($tempcat->parent != $moveto) {
- $newp = get_record('course_categories', 'id', $moveto);
- if (! move_category($tempcat, $newp)) {
+ if (!empty($move) and ($moveto >= 0) and confirm_sesskey()) {
+ if ($cattomove = get_record('course_categories', 'id', $move)) {
+ require_capability('moodle/category:manage', get_category_or_system_context($cattomove->parent));
+ if ($cattomove->parent != $moveto) {
+ $newparent = get_record('course_categories', 'id', $moveto);
+ require_capability('moodle/category:manage', get_category_or_system_context($moveto));
+ if (!move_category($cattomove, $newparent)) {
notify('Could not update that category!');
}
}
}
}
-
/// Hide or show a category
if ((!empty($hide) or !empty($show)) and confirm_sesskey()) {
if (!empty($hide)) {
@@ -184,6 +183,7 @@
$tempcat = get_record('course_categories', 'id', $show);
$visible = 1;
}
+ require_capability('moodle/category:manage', get_category_or_system_context($tempcat->parent));
if ($tempcat) {
if (! set_field('course_categories', 'visible', $visible, 'id', $tempcat->id)) {
notify('Could not update that category!');
@@ -194,15 +194,13 @@
}
}
-
/// Move a category up or down
-
if ((!empty($moveup) or !empty($movedown)) and confirm_sesskey()) {
-
$swapcategory = NULL;
$movecategory = NULL;
if (!empty($moveup)) {
+ require_capability('moodle/category:manage', get_context_instance(CONTEXT_COURSECAT, $moveup));
if ($movecategory = get_record('course_categories', 'id', $moveup)) {
$categories = get_categories($movecategory->parent);
@@ -216,6 +214,7 @@
}
}
if (!empty($movedown)) {
+ require_capability('moodle/category:manage', get_context_instance(CONTEXT_COURSECAT, $movedown));
if ($movecategory = get_record('course_categories', 'id', $movedown)) {
$categories = get_categories($movecategory->parent);
@@ -256,7 +255,6 @@
fix_course_sortorder();
/// Print out the categories with all the knobs
-
$strcategories = get_string('categories');
$strcourses = get_string('courses');
$strmovecategoryto = get_string('movecategoryto');
@@ -266,7 +264,7 @@
$parentlist = array();
$displaylist[0] = get_string('top');
- make_categories_list($displaylist, $parentlist, '');
+ make_categories_list($displaylist, $parentlist);
echo '<table class="generalbox editcourse boxaligncenter"><tr class="header">';
echo '<th class="header" scope="col">'.$strcategories.'</th>';
@@ -281,52 +279,39 @@
echo '<div class="buttons">';
- if (!empty($category->id)) {
- // Print link to create a new course in current category
- if (has_capability('moodle/course:create', $context)) {
- $options = array();
- $options['category'] = $category->id;
- print_single_button('edit.php', $options, get_string('addnewcourse'), 'get');
- }
- }else{
- if (has_capability('moodle/course:create', $sysctx)) {
- // print create course link to first category
- $options = array();
- $options = array('category' => get_field('course_categories', 'id', 'parent', '0'));
- print_single_button('edit.php', $options, get_string('addnewcourse'), 'get');
- }
+ if (has_capability('moodle/course:create', $systemcontext)) {
+ // print create course link to first category
+ $options = array();
+ $options = array('category' => $CFG->defaultrequestcategory);
+ print_single_button('edit.php', $options, get_string('addnewcourse'), 'get');
}
// Print button for creating new categories
- if (has_capability('moodle/category:create', $context)) {
- unset($options);
- if (!empty($category->id)) {
- $options['id'] = $category->id;
- } else {
- $options['id'] = 0;
- }
- $options['categoryadd'] = 1;
+ if (has_capability('moodle/category:manage', $systemcontext)) {
+ $options = array();
+ $options['parent'] = 0;
print_single_button('editcategory.php', $options, get_string('addnewcategory'), 'get');
}
- if (has_capability('moodle/site:approvecourse', $sysctx) and !empty($CFG->enablecourserequests)) {
+ if (has_capability('moodle/site:approvecourse', $systemcontext) and !empty($CFG->enablecourserequests)) {
print_single_button('pending.php',NULL, get_string('coursespending'), 'get');
}
// admin page does not allow custom buttons in the navigation bar
echo '<div class="singlebutton">';
- echo update_categories_button();
+ echo update_category_button();
echo '</div></div>';
- print_footer();
+ admin_externalpage_print_footer();
function print_category_edit($category, $displaylist, $parentslist, $depth=-1, $up=false, $down=false) {
/// Recursive function to print all the categories ready for editing
global $CFG, $USER;
- static $str = '';
+ static $str = NULL;
- if (empty($str)) {
+ if (is_null($str)) {
+ $str = new stdClass;
$str->edit = get_string('edit');
$str->delete = get_string('delete');
$str->moveup = get_string('moveup');
@@ -334,9 +319,10 @@ function print_category_edit($category, $displaylist, $parentslist, $depth=-1, $
$str->edit = get_string('editthiscategory');
$str->hide = get_string('hide');
$str->show = get_string('show');
+ $str->spacer = '<img src="'.$CFG->wwwroot.'/pix/spacer.gif" class="iconsmall" alt="" /> ';
}
- if ($category) {
+ if (!empty($category)) {
if (!isset($category->context)) {
$category->context = get_context_instance(CONTEXT_COURSECAT, $category->id);
@@ -356,17 +342,13 @@ function print_category_edit($category, $displaylist, $parentslist, $depth=-1, $
echo '<td class="icons">'; /// Print little icons
- if (has_capability('moodle/category:update', $category->context)) {
- echo '<a title="'.$str->edit.'" href="editcategory.php?id='.$category->id.'&amp;sesskey='.sesskey().'"><img'.
+ if (has_capability('moodle/category:manage', $category->context)) {
+ echo '<a title="'.$str->edit.'" href="editcategory.php?id='.$category->id.'"><img'.
' src="'.$CFG->pixpath.'/t/edit.gif" class="iconsmall" alt="'.$str->edit.'" /></a> ';
- }
- if (has_capability('moodle/category:delete', $category->context)) {
echo '<a title="'.$str->delete.'" href="index.php?delete='.$category->id.'&amp;sesskey='.sesskey().'"><img'.
' src="'.$CFG->pixpath.'/t/delete.gif" class="iconsmall" alt="'.$str->delete.'" /></a> ';
- }
- if (has_capability('moodle/category:visibility', $category->context)) {
if (!empty($category->visible)) {
echo '<a title="'.$str->hide.'" href="index.php?hide='.$category->id.'&amp;sesskey='.sesskey().'"><img'.
' src="'.$CFG->pixpath.'/t/hide.gif" class="iconsmall" alt="'.$str->hide.'" /></a> ';
@@ -374,27 +356,33 @@ function print_category_edit($category, $displaylist, $parentslist, $depth=-1, $
echo '<a title="'.$str->show.'" href="index.php?show='.$category->id.'&amp;sesskey='.sesskey().'"><img'.
' src="'.$CFG->pixpath.'/t/show.gif" class="iconsmall" alt="'.$str->show.'" /></a> ';
}
- }
- if ($up) {
- echo '<a title="'.$str->moveup.'" href="index.php?moveup='.$category->id.'&amp;sesskey='.sesskey().'"><img'.
- ' src="'.$CFG->pixpath.'/t/up.gif" class="iconsmall" alt="'.$str->moveup.'" /></a> ';
- }
- if ($down) {
- echo '<a title="'.$str->movedown.'" href="index.php?movedown='.$category->id.'&amp;sesskey='.sesskey().'"><img'.
- ' src="'.$CFG->pixpath.'/t/down.gif" class="iconsmall" alt="'.$str->movedown.'" /></a> ';
+ if ($up) {
+ echo '<a title="'.$str->moveup.'" href="index.php?moveup='.$category->id.'&amp;sesskey='.sesskey().'"><img'.
+ ' src="'.$CFG->pixpath.'/t/up.gif" class="iconsmall" alt="'.$str->moveup.'" /></a> ';
+ } else {
+ echo $str->spacer;
+ }
+ if ($down) {
+ echo '<a title="'.$str->movedown.'" href="index.php?movedown='.$category->id.'&amp;sesskey='.sesskey().'"><img'.
+ ' src="'.$CFG->pixpath.'/t/down.gif" class="iconsmall" alt="'.$str->movedown.'" /></a> ';
+ } else {
+ echo $str->spacer;
+ }
}
echo '</td>';
echo '<td align="left">';
- $tempdisplaylist = $displaylist;
- unset($tempdisplaylist[$category->id]);
- foreach ($parentslist as $key => $parents) {
- if (in_array($category->id, $parents)) {
- unset($tempdisplaylist[$key]);
+ if (has_capability('moodle/category:manage', $category->context)) {
+ $tempdisplaylist = $displaylist;
+ unset($tempdisplaylist[$category->id]);
+ foreach ($parentslist as $key => $parents) {
+ if (in_array($category->id, $parents)) {
+ unset($tempdisplaylist[$key]);
+ }
}
+ popup_form ("index.php?move=$category->id&amp;sesskey=$USER->sesskey&amp;moveto=", $tempdisplaylist, "moveform$category->id", $category->parent, '', '', '', false);
}
- popup_form ("index.php?move=$category->id&amp;sesskey=$USER->sesskey&amp;moveto=", $tempdisplaylist, "moveform$category->id", $category->parent, '', '', '', false);
echo '</td>';
echo '</tr>';
} else {
@@ -424,13 +412,8 @@ function print_category_edit_header() {
global $CFG;
global $SITE;
- if (has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM))) {
- require_once($CFG->libdir.'/adminlib.php');
- admin_externalpage_setup('coursemgmt');
- admin_externalpage_print_header();
- } else {
- print_header("$SITE->shortname:". get_string('categories'), get_string('courses'),
- build_navigation(array(array('name'=>get_string('categories'),'link'=>'','type'=>'misc'))), '', '', true, update_categories_button());
- }
+ require_once($CFG->libdir.'/adminlib.php');
+ admin_externalpage_setup('coursemgmt');
+ admin_externalpage_print_header();
}
?>
View
151 course/lib.php
@@ -1533,6 +1533,21 @@ function print_section_add_menus($course, $section, $modnames, $vertical=false,
}
/**
+ * Return the course category context for the category with id $categoryid, except
+ * that if $categoryid is 0, return the system context.
+ *
+ * @param integer $categoryid a category id or 0.
+ * @return object the corresponding context
+ */
+function get_category_or_system_context($categoryid) {
+ if ($categoryid) {
+ return get_context_instance(CONTEXT_COURSECAT, $categoryid);
+ } else {
+ return get_context_instance(CONTEXT_SYSTEM);
+ }
+}
+
+/**
* Rebuilds the cached list of course activities stored in the database
* @param int $courseid - id of course to rebuil, empty means all
* @param boolean $clearonly - only clear the modinfo fields, gets rebuild automatically on the fly
@@ -1578,10 +1593,14 @@ function rebuild_course_cache($courseid=0, $clearonly=false) {
get_fast_modinfo($reset);
}
-function get_child_categories($parent) {
-/// Returns an array of the children categories for the given category
-/// ID by caching all of the categories in a static hash
-
+/**
+ * Gets the child categories of a given coures category. Uses a static cache
+ * to make repeat calls efficient.
+ *
+ * @param unknown_type $parentid the id of a course category.
+ * @return array all the child course categories.
+ */
+function get_child_categories($parentid) {
static $allcategories = null;
// only fill in this variable the first time
@@ -1597,18 +1616,50 @@ function get_child_categories($parent) {
}
}
- if (empty($allcategories[$parent])) {
+ if (empty($allcategories[$parentid])) {
return array();
} else {
- return $allcategories[$parent];
+ return $allcategories[$parentid];
}
}
-
-function make_categories_list(&$list, &$parents, $category=NULL, $path="") {
-/// Given an empty array, this function recursively travels the
-/// categories, building up a nice list for display. It also makes
-/// an array that list all the parents for each category.
+/**
+ * This function recursively travels the categories, building up a nice list
+ * for display. It also makes an array that list all the parents for each
+ * category.
+ *
+ * For example, if you have a tree of categories like:
+ * Miscellaneous (id = 1)
+ * Subcategory (id = 2)
+ * Sub-subcategory (id = 4)
+ * Other category (id = 3)
+ * Then after calling this function you will have
+ * $list = array(1 => 'Miscellaneous', 2 => 'Miscellaneous / Subcategory',
+ * 4 => 'Miscellaneous / Subcategory / Sub-subcategory',
+ * 3 => 'Other category');
+ * $parents = array(2 => array(1), 4 => array(1, 2));
+ *
+ * If you specify $requiredcapability, then only categories where the current
+ * user has that capability will be added to $list, although all categories
+ * will still be added to $parents, and if you only have $requiredcapability
+ * in a child category, not the parent, then the child catgegory will still be
+ * included.
+ *
+ * If you specify the option $excluded, then that category, and all its children,
+ * are omitted from the tree. This is useful when you are doing something like
+ * moving categories, where you do not want to allow people to move a category
+ * to be the child of itself.
+ *
+ * @param array $list For output, accumulates an array categoryid => full category path name
+ * @param array $parents For output, accumulates an array categoryid => list of parent category ids.
+ * @param string $requiredcapability if given, only categories where the current
+ * user has this capability will be added to $list.
+ * @param integer $excludeid Omit this category and its children from the lists built.
+ * @param object $category Build the tree starting at this category - otherwise starts at the top level.
+ * @param string $path For internal use, as part of recursive calls.
+ */
+function make_categories_list(&$list, &$parents, $requiredcapability = '',
+ $excludeid = 0, $category = NULL, $path = "") {
// initialize the arrays if needed
if (!is_array($list)) {
@@ -1618,18 +1669,34 @@ function make_categories_list(&$list, &$parents, $category=NULL, $path="") {
$parents = array();
}
- if ($category) {
+ if (empty($category)) {
+ // Start at the top level.
+ $category = new stdClass;
+ $category->id = 0;
+ } else {
+ // This is the excluded category, don't include it.
+ if ($excludeid > 0 && $excludeid == $category->id) {
+ return;
+ }
+
+ // Update $path.
if ($path) {
$path = $path.' / '.format_string($category->name);
} else {
$path = format_string($category->name);
}
- $list[$category->id] = $path;
- } else {
- $category->id = 0;
+
+ // Add this category to $list, if the permissions check out.
+ if ($requiredcapability) {
+ ensure_context_subobj_present($category, CONTEXT_COURSECAT);
+ }
+ if (!$requiredcapability || has_capability($requiredcapability, $category->context)) {
+ $list[$category->id] = $path;
+ }
}
- if ($categories = get_child_categories($category->id)) { // Print all the children recursively
+ // Add all the children recursively, while updating the parents array.
+ if ($categories = get_child_categories($category->id)) {
foreach ($categories as $cat) {
if (!empty($category->id)) {
if (isset($parents[$category->id])) {
@@ -1637,13 +1704,12 @@ function make_categories_list(&$list, &$parents, $category=NULL, $path="") {
}
$parents[$cat->id][] = $category->id;
}
- make_categories_list($list, $parents, $cat, $path);
+ make_categories_list($list, $parents, $requiredcapability, $excludeid, $cat, $path);
}
}
}
-
-function print_whole_category_list($category=NULL, $displaylist=NULL, $parentslist=NULL, $depth=-1, $files = true) {
+function print_whole_category_list($category=NULL, $displaylist=NULL, $parentslist=NULL, $depth=-1, $showcourses = true) {
/// Recursive function to print out all the categories in a nice format
/// with or without courses included
global $CFG;
@@ -1657,8 +1723,8 @@ function print_whole_category_list($category=NULL, $displaylist=NULL, $parentsli
}
if ($category) {
- if ($category->visible or has_capability('moodle/course:update', get_context_instance(CONTEXT_SYSTEM))) {
- print_category_info($category, $depth, $files);
+ if ($category->visible or has_capability('moodle/category:viewhiddencategories', get_context_instance(CONTEXT_SYSTEM))) {
+ print_category_info($category, $depth, $showcourses);
} else {
return; // Don't bother printing children of invisible categories
}
@@ -1681,7 +1747,7 @@ function print_whole_category_list($category=NULL, $displaylist=NULL, $parentsli
$down = $last ? false : true;
$first = false;
- print_whole_category_list($cat, $displaylist, $parentslist, $depth + 1, $files);
+ print_whole_category_list($cat, $displaylist, $parentslist, $depth + 1, $showcourses);
}
}
}
@@ -1702,7 +1768,7 @@ function make_categories_options() {
return $cats;
}
-function print_category_info($category, $depth, $files = false) {
+function print_category_info($category, $depth, $showcourses = false) {
/// Prints the category info in indented fashion
/// This function is only used by print_whole_category_list() above
@@ -1718,7 +1784,7 @@ function print_category_info($category, $depth, $files = false) {
$catlinkcss = $category->visible ? '' : ' class="dimmed" ';
$coursecount = count_records('course') <= FRONTPAGECOURSELIMIT;
- if ($files and $coursecount) {
+ if ($showcourses and $coursecount) {
$catimage = '<img src="'.$CFG->pixpath.'/i/course.gif" alt="" />';
} else {
$catimage = "&nbsp;";
@@ -1727,7 +1793,7 @@ function print_category_info($category, $depth, $files = false) {
echo "\n\n".'<table class="categorylist">';
$courses = get_courses($category->id, 'c.sortorder ASC', 'c.id,c.sortorder,c.visible,c.fullname,c.shortname,c.password,c.summary,c.guest,c.cost,c.currency');
- if ($files and $coursecount) {
+ if ($showcourses and $coursecount) {
echo '<tr>';
@@ -1798,7 +1864,42 @@ function print_category_info($category, $depth, $files = false) {
echo '</table>';
}
+/**
+ * Prints the turn editing on/off button on course/index.php or course/category.php.
+ *
+ * @param integer $categoryid The id of the category we are showing, or 0 for system context.
+ * @return string HTML of the editing button, or empty string, if this user is not allowed
+ * to see it.
+ */
+function update_category_button($categoryid = 0) {
+ global $CFG, $USER;
+
+ // Check permissions.
+ $context = get_category_or_system_context($categoryid);
+ if (!has_any_capability(array('moodle/category:manage', 'moodle/course:create'), $context)) {
+ return '';
+ }
+
+ // Work out the appropriate action.
+ if (!empty($USER->categoryediting)) {
+ $label = get_string('turneditingoff');
+ $edit = 'off';
+ } else {
+ $label = get_string('turneditingon');
+ $edit = 'on';
+ }
+ // Generate the button HTML.
+ $options = array('categoryedit' => $edit, 'sesskey' => sesskey());
+ if ($categoryid) {
+ $options['id'] = $categoryid;
+ $page = 'category.php';
+ } else {
+ $page = 'index.php';
+ }
+ return print_single_button($CFG->wwwroot . '/course/' . $page, $options,
+ $label, 'get', '', true);
+}
function print_courses($category) {
/// Category is 0 (for all courses) or an object
View
4 course/search.php
@@ -72,7 +72,7 @@
$displaylist = array();
$parentlist = array();
- make_categories_list($displaylist, $parentlist, "");
+ make_categories_list($displaylist, $parentlist);
$strcourses = get_string("courses");
$strsearch = get_string("search");
@@ -260,7 +260,7 @@
// this is ok since this will get inherited from course category context
// if it is set
- if (has_capability('moodle/category:update', $coursecontext)) {
+ if (has_capability('moodle/category:manage', $coursecontext)) {
echo "<input type=\"checkbox\" name=\"c$course->id\" />\n";
} else {
echo "<input type=\"checkbox\" name=\"c$course->id\" disabled=\"disabled\" />\n";
View
1 lang/en_utf8/moodle.php
@@ -306,6 +306,7 @@
$string['courseuploadlimit'] = 'Course upload limit';
$string['create'] = 'Create';
$string['createaccount'] = 'Create my new account';
+$string['createcategory'] = 'Create category';