diff --git a/course/format/topics/format.php b/course/format/topics/format.php index 62ca069..580487a 100644 --- a/course/format/topics/format.php +++ b/course/format/topics/format.php @@ -111,6 +111,14 @@ $section = 0; $thissection = $sections[$section]; + require_once $CFG->dirroot."/course/massaction/lib.php"; + + if (isediting($course->id)) { + echo ""; + massaction_print_form($course->format); + echo ""; + } + if ($thissection->summary or $thissection->sequence or isediting($course->id)) { echo ''; echo ' '; @@ -263,6 +271,12 @@ $section++; } + if (isediting($course->id)) { + echo ""; + massaction_print_form($course->format); + echo ""; + } + echo ''; if (!empty($sectionmenu)) { diff --git a/course/format/weeks/format.php b/course/format/weeks/format.php index 64f3f77..b2fb25c 100644 --- a/course/format/weeks/format.php +++ b/course/format/weeks/format.php @@ -98,6 +98,14 @@ $section = 0; $thissection = $sections[$section]; + require_once $CFG->dirroot."/course/massaction/lib.php"; + + if (isediting($course->id)) { + echo ""; + massaction_print_form($course->format); + echo ""; + } + if ($thissection->summary or $thissection->sequence or isediting($course->id)) { echo ''; echo ' '; @@ -253,7 +261,13 @@ $section++; $weekdate = $nextweekdate; } - echo ''; + + if (isediting($course->id)) { + echo ""; + massaction_print_form($course->format); + echo ""; + } + echo ''; if (!empty($sectionmenu)) { echo '
'; diff --git a/course/lib.php b/course/lib.php index 6c59172..5b7742d 100644 --- a/course/lib.php +++ b/course/lib.php @@ -2805,6 +2805,9 @@ function make_editing_buttons($mod, $absolute=false, $moveselect=true, $indent=- } } + require_once $CFG->dirroot.'/course/massaction/lib.php'; + $checkbox = massaction_checkbox($mod->id); + return ''."\n".$leftright.$move. ''."\n".$hideshow.$groupmode."\n".''; + ' alt="'.$str->delete.'" />'."\n".$hideshow.$groupmode."\n".$checkbox.''; } /** diff --git a/course/massaction/action.php b/course/massaction/action.php new file mode 100644 index 0000000..a0f731d --- /dev/null +++ b/course/massaction/action.php @@ -0,0 +1,117 @@ +libdir .'/dmllib.php'); + +$sesskey = required_param('sesskey'); +$return_to = required_param('return_to'); + +$continue = optional_param('continue', false); +$do = optional_param('do', false); +$modids = array(); +$section = -1; + +foreach ($_POST as $key => $val) { + if (str_replace('massaction_check_', "", $key) == $val) { + $modids[] = $val; + } else if (substr($key, 0, 4) == 'act_') { + $action = substr($key, 4); + } +} + +if ($encoded_modids = optional_param('modids', false)) { + $modids = decode_array($encoded_modids); +} + +// Turn arrays into strings that can easily be passed +$encoded_post = encode_array($_POST); +$encoded_mods = encode_array($modids); + +if (! isset($action) && isset($_POST['action'])) { + $action = $_POST['action']; +} + +if (optional_param('cancel', false)) { + redirect($return_to); +} + +if (! isset($action)) { + redirect($return_to, "No action was specified"); +} else if (empty($modids)) { + redirect($return_to, "No modules were selected"); +} + +$include_file = $CFG->dirroot.'/course/massaction/'.$action.".php"; +$include_file_exists = file_exists($include_file); + +if (! $include_file_exists) { + error("Required file '$include_file' does not exist"); +} +require_once($include_file); + + +$confirm_function = "ma_".$action."_confirm"; +$continue_function = "ma_".$action."_continue"; +$execute_function = "ma_".$action."_execute"; + +$confirm_function_exists = function_exists($confirm_function); +$continue_function_exists = function_exists($continue_function); +$execute_function_exists = function_exists($execute_function); + +$do_page = $do || ! $confirm_function_exists; // action has been confirmed or there is no confirm function +$confirm_page = ($continue || ! $continue_function_exists) && ! $do_page; // past the continue page, or no continue function + +if ($do_page) { // Action has been confirmed OR there is no confirm function + if ($do) { + $modids = decode_array($_POST['modids']); + $post = decode_array($_POST['post']); + } else { + $post = $_POST; + } + if ($modids) { + if (! $execute_function_exists) { + error("Required function '$execute_function' does not exist"); + } + $message = $execute_function($modids, $post); + rebuild_course_cache($post['courseid']); + redirect($return_to, $message); + } +} else { + $modnames = massaction_get_modnames($modids); + + $string = ''; + // Get the custom string for the chosen action; + if ($confirm_page) { + $string .= $confirm_function($modnames, $_POST); + } else { + $string .= $continue_function($modnames, $_POST); + } + + // Print the form + + print_header_simple(get_string($action, 'massaction')." (Mass Action)"); + print_simple_box_start('center', '60%', '#FFAAAA', 20, 'noticebox'); + + echo $string; + + echo "
\n"; + echo "\n"; + if ($confirm_page) { + $name = 'do'; + } else { + $name = 'continue'; + } + + print_hidden_input('modids', $encoded_mods); + print_hidden_input('action', $action); + print_hidden_input('sesskey', $sesskey); + print_hidden_input('return_to', $return_to); + + print_submit_input($name, get_string($action, 'massaction')); + print_submit_input('cancel', get_string('cancel', 'massaction')); + + echo "
\n"; + print_simple_box_end(); + print_footer(); +} +?> diff --git a/course/massaction/delete.php b/course/massaction/delete.php new file mode 100644 index 0000000..2604c2a --- /dev/null +++ b/course/massaction/delete.php @@ -0,0 +1,79 @@ +"; + $string .= "".get_string('delete_confirm', 'massaction').""; + foreach ($modnames as $modname) { + $string .= "$modname"; + } + $string .= ""; + return $string; +} + +/** + * Given a list of module names, prints out a warning message. The first message to be printed before performing the action + */ +function ma_delete_continue($modnames) { + $string = ""; + $string .= ""; + $string .= ""; + foreach ($modnames as $modname) { + $string .= ""; + } + $string .= "
".get_string('delete_continue', 'massaction')."
$modname
"; + return $string; +} + +function ma_delete_execute($modids) { + + global $CFG; + + $in_list = "(".join(", ", $modids).")"; + + $sql = "SELECT cm.id as coursemodule, cm.section, cm.course, mo.name as modulename, instance + FROM {$CFG->prefix}course_modules cm + LEFT JOIN {$CFG->prefix}modules mo on mo.id=cm.module + WHERE cm.id IN $in_list"; + $records = get_records_sql($sql); + $courses = array(); + + $message = ''; + + if ($records) { + foreach ($records as $id => $record) { + $modlib = "$CFG->dirroot/mod/$record->modulename/lib.php"; + $courses[] = $record->course; + if (file_exists($modlib)) { + include_once($modlib); + } else { + $messasge .= "This module is missing important code! ($modlib)  "; + continue; + } + $deleteinstancefunction = $record->modulename."_delete_instance"; + if (! $deleteinstancefunction($record->instance)) { + $message .= "Could not delete the $record->modulename (instance)  "; + continue; + } + if (! delete_course_module($record->coursemodule)) { + $message .= "Could not delete the $record->modulename (coursemodule)  "; + continue; + } + if (! delete_mod_from_section($record->coursemodule, "$record->section")) { + $message .= "Could not delete the $record->modulename from that section  "; + continue; + } + } + + $courses = array_unique($courses); + foreach ($courses as $course) { + rebuild_course_cache($course); + } + } + return $message; +} + +?> diff --git a/course/massaction/hide.php b/course/massaction/hide.php new file mode 100644 index 0000000..8bc3b37 --- /dev/null +++ b/course/massaction/hide.php @@ -0,0 +1,13 @@ + diff --git a/course/massaction/lib.php b/course/massaction/lib.php new file mode 100644 index 0000000..b201361 --- /dev/null +++ b/course/massaction/lib.php @@ -0,0 +1,164 @@ +id == 1) { + return; + } else { + echo ""; + } +} + +/** + * Given an array or an object, converts it into a string value + * + * @param array $array Object to be converted + * @return string string representation of that array or object + */ +function encode_array($array) { + return base64_encode(serialize($array)); +} + +/** + * Given a string value, converts it into an array or an object + * + * @param string $string Value to be converted + * @return array Array or object representation of that string + */ +function decode_array($string) { + return unserialize(base64_decode($string)); +} + +/** + * Given a modid, returns an html string for that checkbox; + * + * @param integer $modid Module Id + * @return string HTML String for that checkbox + */ +function massaction_checkbox($modid) { + global $COURSE; + if (ajaxenabled() || ! $COURSE || $COURSE->id == 1) { + return ''; + } else { + return ''; + } +} + +/** + * Given a name and value, prints out a hidden input + * + * @param string $name Name of hidden input + * @param string $value Value of hidden input + */ +function print_hidden_input($name, $value) { + echo "\n"; +} + +/** + * Given a name and value, prints out a submit button + * + * @param string $name Name of submit + * @param string $value Value of submit + * @param boolean $disabled optional value states if the submit is disabled + */ +function print_submit_input($name, $value, $disabled = false) { + echo "\n"; +} + +/** + * Given a course format, prints out the toolbar that allows for massactions + * + * @param string $course_format optional course format + */ +function massaction_print_form($course_format = 'weeks') { + global $USER, $COURSE; + if (ajaxenabled() || ! $COURSE || $COURSE->id == 1) { + return; + } + print_simple_box_start(); + echo "
\n"; + print_hidden_input('return_to', $_SERVER["REQUEST_URI"]); + print_hidden_input('act_move', 'move'); + print_hidden_input('sesskey', $USER->sesskey); + print_hidden_input('courseid', $COURSE->id); + echo ""; + + echo "\n"; + echo ""; + echo "\n"; + + echo "
".get_string('title', 'massaction')."
"; + helpbutton('massaction', get_string('title', 'massaction')); + echo ""; + print_submit_input('act_delete', get_string('delete', 'massaction'), true); + echo ""; + print_submit_input('act_hide', get_string('hide', 'massaction'), true); + echo ""; + print_submit_input('act_show', get_string('show', 'massaction'), true); + echo "
".get_string('moveto', 'massaction')."
\n"; + echo "
\n"; + echo ""; + print_simple_box_end(); +} + +/** + * Given an array of module ids, returns an array of module names + * + * @param array $modids array of module ids + * @return array array of module names, indexed by id + */ +function massaction_get_modnames($modids) { + global $CFG; + $inlist = "(".join(", ", $modids).")"; + $course_sql = + "SELECT cm.id, mo.name, cm.course FROM {$CFG->prefix}course_modules cm + LEFT JOIN {$CFG->prefix}modules mo on mo.id=cm.module + WHERE cm.id IN $inlist"; + $course_records = get_records_sql($course_sql); + $return_vals = array(); + foreach ($modids as $modid) { + $modinfo = get_coursemodule_from_id($course_records[$modid]->name, $course_records[$modid]->id, $course_records[$modid]->course); + $return_vals[$modid] = $modinfo->name; + } + return $return_vals; +} + +?> diff --git a/course/massaction/massaction.js b/course/massaction/massaction.js new file mode 100644 index 0000000..1e82bd7 --- /dev/null +++ b/course/massaction/massaction.js @@ -0,0 +1,69 @@ +function massaction_check(checkbox) { + var modid = checkbox.getAttribute('modid'); + var name = 'massaction_check_' + modid; + var oldinputs = document.getElementsByName(name); + var js_name = 'js_input'; + + var exists = false; + var count = 0; + for (var i in oldinputs) { + if (typeof(oldinputs[i]) == 'object') { + exists = true; + count++; + } + } + var forms = document.getElementsByName('massactionexecute'); + if (! exists) { + for (var i=0; i < forms.length; i++) { + if (forms[i].appendChild) { + if (! forms[i].js_input) { + var js_elem = document.createElement('input'); + js_elem.setAttribute('type', 'hidden'); + js_elem.setAttribute('name', js_name); + js_elem.setAttribute('value', 'js_enabled'); + forms[i].appendChild(js_elem); + } + var newinput = document.createElement('input'); + newinput.setAttribute('value', modid); + newinput.setAttribute('name', name); + newinput.setAttribute('type', 'hidden'); + forms[i].appendChild(newinput); + } + } + } else { + var done = false; + while (! done) { + done = true; + oldinputs = document.getElementsByName(name); + for (var i in oldinputs) { + if (typeof(oldinputs[i]) == 'object') { + var form = oldinputs[i].parentNode; + form.removeChild(oldinputs[i]); + done = false; + } + } + } + } +} + +function enable_massaction() { + var forms = document.getElementsByName('massactionexecute'); + var form; + + for (var i = 0; i < forms.length; i++) { + if (typeof(forms[i]) == 'object') { + form = forms[i]; + form.act_delete.removeAttribute('disabled'); + form.act_hide.removeAttribute('disabled'); + form.act_show.removeAttribute('disabled'); + form.section.removeAttribute('disabled'); + } + } + + var checkboxes = document.getElementsByName('massaction_check'); + for (var i = 0; i < checkboxes.length; i++) { + if (typeof(checkboxes[i]) == 'object') { + checkboxes[i].removeAttribute('disabled'); + } + } +} diff --git a/course/massaction/move.php b/course/massaction/move.php new file mode 100644 index 0000000..a29d206 --- /dev/null +++ b/course/massaction/move.php @@ -0,0 +1,46 @@ +"; + $str .= "Are you sure you want to move module(s)"; + foreach ($modnames as $modname) { + $str .= "$modname"; + } + $str .= "To Section \"".$section['name']."\"?"; + return $str; +}*/ + +function ma_move_execute($modids, $post) { + $section_id = -1; + foreach ($post as $key => $val) { + if ($key == 'section') { + $section = decode_array($val); + $section_id = $section['id']; + } + } + if ($section_id == -1) { + return; + } + $section = get_record("course_sections", "id", $section_id); + $message = ""; + if ($section) { + foreach ($modids as $modid) { + $cm = get_record("course_modules", "id", $modid); + if (! moveto_module($cm, $section)) { + $message .= "Could not move module $modid, "; + } + } + } else { + $message = "No sections were selected"; + } + return $message; +} + +?> diff --git a/course/massaction/show.php b/course/massaction/show.php new file mode 100644 index 0000000..7abff52 --- /dev/null +++ b/course/massaction/show.php @@ -0,0 +1,13 @@ + diff --git a/course/view.php b/course/view.php index 200e55b..60ff050 100644 --- a/course/view.php +++ b/course/view.php @@ -7,6 +7,7 @@ require_once($CFG->libdir.'/blocklib.php'); require_once($CFG->libdir.'/ajax/ajaxlib.php'); require_once($CFG->dirroot.'/mod/forum/lib.php'); + require_once $CFG->dirroot.'/course/massaction/lib.php'; $id = optional_param('id', 0, PARAM_INT); $name = optional_param('name', '', PARAM_RAW); @@ -196,6 +197,7 @@ $PAGE->print_header(get_string('course').': %fullname%', NULL, '', $bodytags); + massaction_print_js(); // Course wrapper start. echo '
'; diff --git a/lang/en_utf8/help/massaction.html b/lang/en_utf8/help/massaction.html new file mode 100644 index 0000000..47f2b2e --- /dev/null +++ b/lang/en_utf8/help/massaction.html @@ -0,0 +1,22 @@ +

Mass Actions

+ +

+This toolbar allows instructors to perform actions upon +multiple resources or activities in the class view, rather +than having to perform repeated actions on individual items. +

+ +

+To use this toolbar, Javascript must be enabled in your +browser, you must be in editing mode in the course +home page, and Ajax must be disabled. Only the +courses in the Week or Topics formats are supported. +

+ +

+Supported actions include mass deletion, mass hiding, +mass showing, and mass moving. To select items to perform +actions on, simply click the checkbox to the right of it +in the course home page, then at the top or bottom +of the page, click the action you would like to perform. +

diff --git a/lang/en_utf8/massaction.php b/lang/en_utf8/massaction.php new file mode 100644 index 0000000..8c92aab --- /dev/null +++ b/lang/en_utf8/massaction.php @@ -0,0 +1,14 @@ +Mass Actions'; +$string['cancel'] = 'Cancel'; +$string['section'] = 'Section'; +$string['sectionzero'] = 'Section 0'; +?> \ No newline at end of file