From 4a1ade3d64850e36b2d2a8ccba05e80b1ebcfc0e Mon Sep 17 00:00:00 2001 From: Marcus Green Date: Thu, 24 Oct 2024 12:17:35 +0100 Subject: [PATCH] Refactor lib.php to use classes Triggerd by review for plugins database here https://github.com/marcusgreen/moodle-tool_driprelease/issues/2 Move functions into a new driprelease class to conform to more modern php and avoid potential name clashes --- classes/driprelease.php | 391 +++++++++ classes/event/driprelease_updated.php | 4 +- classes/event/driprelease_viewed.php | 4 +- driprelease_form.php | 5 +- lang/en/tool_driprelease.php | 1 + lib.php | 364 +-------- phpunit.xml | 2 + tests/coverage-html/classes/dashboard.html | 32 +- .../classes/driprelease.php.html | 756 ++++++++++++++++++ .../classes/event/dashboard.html | 2 +- .../event/driprelease_updated.php.html | 2 +- .../classes/event/driprelease_viewed.php.html | 2 +- tests/coverage-html/classes/event/index.html | 2 +- tests/coverage-html/classes/index.html | 36 +- tests/coverage-html/classes/lib.php.html | 131 +++ .../classes/privacy/dashboard.html | 2 +- .../coverage-html/classes/privacy/index.html | 2 +- .../classes/privacy/provider.php.html | 2 +- tests/coverage-html/dashboard.html | 32 +- tests/coverage-html/driprelease_form.php.html | 6 +- tests/coverage-html/index.html | 48 +- tests/coverage-html/lib.php.html | 610 +------------- tests/coverage-html/view.php.html | 229 +++--- tests/driprelease_test.php | 117 ++- view.php | 42 +- 25 files changed, 1635 insertions(+), 1189 deletions(-) create mode 100644 classes/driprelease.php create mode 100644 tests/coverage-html/classes/driprelease.php.html create mode 100644 tests/coverage-html/classes/lib.php.html diff --git a/classes/driprelease.php b/classes/driprelease.php new file mode 100644 index 0000000..54caa80 --- /dev/null +++ b/classes/driprelease.php @@ -0,0 +1,391 @@ +. + +namespace tool_driprelease; +use core_availability\tree; +/** + * Class driprelease + * + * @package tool_driprelease + * @copyright 2024 YOUR NAME + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class driprelease { + /** + * Adds/updates an instance of driprelease and its related + * + * @param \stdClass $fromform + * @param int $courseid + * @return array + */ + public function update(\stdClass $fromform , int $courseid): array { + global $DB; + $dripreleaseid = $DB->get_field('tool_driprelease', 'id', ['courseid' => $courseid]); + + if ($dripreleaseid) { + $driprelease = (object) [ + 'id' => $dripreleaseid, + 'modtype' => $fromform->modtype, + 'courseid' => $courseid, + 'activitiespersession' => $fromform->activitiespersession, + 'sessionlength' => $fromform->sessiongroup['sessionlength'] ?? $fromform->sessionlength, + 'schedulestart' => $fromform->schedulestart, + 'schedulefinish' => $fromform->schedulefinish, + 'coursegroup' => $fromform->coursegroup, + 'stayavailable' => $fromform->stayavailable, + 'hideunselected' => $fromform->hideunselected, + 'resetunselected' => $fromform->resetunselected, + 'displaydisabled' => $fromform->displaydisabled, + ]; + $DB->update_record('tool_driprelease', $driprelease); + $this->manage_selections($fromform, $dripreleaseid); + } else { + $driprelease = (object) [ + 'courseid' => $courseid, + 'modtype' => $fromform->modtype, + 'activitiespersession' => $fromform->activitiespersession, + 'sessionlength' => $fromform->sessionlength, + 'schedulestart' => $fromform->schedulestart, + 'schedulefinish' => $fromform->schedulefinish, + 'coursegroup' => $fromform->coursegroup, + 'stayavailable' => $fromform->stayavailable, + 'hideunselected' => $fromform->hideunselected, + 'resetunselected' => $fromform->resetunselected, + 'displaydisabled' => $fromform->displaydisabled, + ]; + $dripreleaseid = $DB->insert_record('tool_driprelease', $driprelease); + $driprelease->id = $dripreleaseid; + } + $this->manage_selections($fromform, $dripreleaseid); + $selections = $DB->get_records_menu('tool_driprelease_cmids', ['driprelease' => $dripreleaseid], null, 'id,coursemoduleid'); + return [$selections, $driprelease]; + } + /** + * Get the rows to be displayed in the schedule of dripped out modules + * + * @param \stdClass $dripdata + * @return array + */ + public function get_table_data(\stdClass $dripdata): array { + global $DB; + $modules = $this->get_modules($dripdata); + $contentcounter = 0; + $sessioncounter = 0; + $selections = []; + if (isset($dripdata->id)) { + $selections = $DB->get_records_menu('tool_driprelease_cmids', ['driprelease' => $dripdata->id], + null, 'id,coursemoduleid'); + } + foreach ($modules as $cm) { + $row['selected'] = in_array($cm->id, $selections) ? 'checked' : ""; + + if ($contentcounter % ($dripdata->activitiespersession) == 0) { + if ($row['selected'] > "") { + $row['calculatedavailability'] = $this->calculate_availability($dripdata, $sessioncounter); + $sessioncounter++; + } + $data[] = $this->add_header($row); + } + $contentcounter++; + $row['modtype'] = $dripdata->modtype; + $data[] = $this->row_fill($row, $cm); + } + return $data ?? []; + } + /** + * Write the availability back to the course_modules table + * See https://moodledev.io/docs/apis/subsystems/availability/ + * @param array $tabledata + * @param \stdClass $dripdata + * @return void + */ + public function update_availability(array $tabledata, \stdClass $dripdata) { + global $DB, $COURSE; + $updatecount = 0; + foreach ($tabledata as $module) { + if (!$module['isheader']) { + if (!$module['selected'] == "checked") { + $this->process_unselected($module, $dripdata); + continue; + } + if (!array_key_exists('calculatedavailability', $module)) { + continue; + } + // Don't write any availability restrictions after the end of the schedule. + if ($module['calculatedavailability']['start'] > $dripdata->schedulefinish) { + continue; + } + $cm = $module['cm']; + set_coursemodule_visible($cm->id, true, true); + \core\event\course_module_updated::create_from_cm($cm)->trigger(); + + $availability = $module['calculatedavailability']; + $restrictions = []; + if ($dripdata->coursegroup) { + $restrictions[] = \availability_group\condition::get_json($dripdata->coursegroup); + } + $restrictions[] = \availability_date\condition::get_json(">=", $availability['start']); + if (!$dripdata->stayavailable) { + $restrictions[] = \availability_date\condition::get_json("<", $availability['end']); + } + $showvalue = false; + if ($dripdata->displaydisabled) { + $showvalue = true; + } + + $showc = array_fill(0, count($restrictions), $showvalue); + $restrictionsclass = tree::get_root_json($restrictions, tree::OP_AND, $showc); + + $DB->set_field( + 'course_modules', + 'availability', + json_encode($restrictionsclass), + ['id' => $module['cm']->id] + ); + $updatecount++; + } + } + $modulenameplural = get_string('modulenameplural', $dripdata->modtype); + $msg = get_string('updated', 'moodle', $updatecount). " ".$modulenameplural; + $refresh = optional_param('refresh', 0, PARAM_RAW); + if (! $refresh) { + \core\notification::add($msg, \core\notification::SUCCESS); + rebuild_course_cache($COURSE->id); + } + } + /** + * Where thee checkbox is not selected + * @param array $module + * @param \stdClass $dripdata + * @return void + */ + public function process_unselected(array $module, \stdClass $dripdata): void { + global $DB; + $cm = $module['cm']; + if ($dripdata->hideunselected) { + set_coursemodule_visible($cm->id, false, false); + \core\event\course_module_updated::create_from_cm($cm)->trigger(); + } else { + set_coursemodule_visible($cm->id, true, true); + } + + if ($dripdata->resetunselected) { + $DB->set_field( + 'course_modules', + 'availability', + '', + ['id' => $module['cm']->id] + ); + } + } + /** + * Simplify get_table_data + * + * @param array $row + * @param \cm_info $cm + * @return array + */ + private function row_fill(array $row, \cm_info $cm): array { + global $DB; + + $details = $DB->get_record($row['modtype'], ['id' => $cm->instance]); + $row['cm'] = $cm; + $row['intro'] = strip_tags($details->intro); + if ($cm->modname == 'quiz') { + $questions = $DB->get_records('quiz_slots', ['quizid' => $cm->instance]); + $row['questioncount'] = count($questions); + } + $row['isheader'] = false; + $row['id'] = $cm->id; + $row['name'] = $cm->name; + $row['moduleavailability'] = $this->get_availability($cm->availability); + return $row; + } + /** + * Get names of modules on course for showing + * in the select element on the form. + * + * @param int $courseid + * @return array + */ + public static function get_course_module_types(int $courseid): array { + $modinfo = get_fast_modinfo($courseid); + $modtypes = []; + foreach ($modinfo->cms as $cm) { + $modtypes[$cm->modname] = get_string('pluginname', $cm->modname); + } + return $modtypes; + } + /** + * Add another session header row in the display/preview of scheduled modules + * + * @param array $row + * @return array + */ + public function add_header(array $row): array { + $header = $row; + $header['isheader'] = true; + $header['cm'] = (object) ['id' => -1]; + $header['name'] = 'Session'; + return $header; + } + /** + * Take an optional JSON string as input and return an array containing + * the date-related availability information. + * * + * If the input JSON is empty, the function returns an empty array. + * + * Loop through each restriction in the JSON object and checks + * if the restriction type is "date". If true, it extracts the operator and + * timestamp from the restriction object. + * + * Based on the operator, the function updates the availability array with + * the formatted date string using userdate() function. + * + * The function returns the availability array containing the 'from' and 'to' + * dates in a human-readable format. + * @param string $json The optional JSON input string containing the availability restrictions + * @return array The availability array containing the 'from' and 'to' dates + */ + public function get_availability(?string $json): array { + $availability = []; + if (empty($json)) { + return $availability; + } + $decoded = json_decode($json); + foreach ($decoded->c as $restriction) { + if (property_exists($restriction, 'type') && $restriction->type == "date") { + $operator = $restriction->d; + if ($operator == ">=") { + $datetime = $restriction->t; + $availability['from'] = userdate($datetime, '%a %d %b %Y %H:%M'); + } else { + $datetime = $restriction->t; + $availability['to'] = userdate($datetime, '%a %d %b %Y %H:%M'); + } + } + } + return $availability; + } + + /** + * Calculate the dripping out of availability and format the dates for the session labels + * + * @param \stdClass $driprelease + * @param int $sessioncounter + * @return array + */ + public function calculate_availability(\stdClass $driprelease, int $sessioncounter): array { + $row = []; + $daysrepeat = $sessioncounter * $driprelease->sessionlength; + $daysoffset = " + $daysrepeat day"; + $start = strtotime(' + ' . $daysrepeat . ' day', $driprelease->schedulestart); + $daysoffset = " + " . (($daysrepeat - 1) + $driprelease->sessionlength) . " day "; + $end = strtotime($daysoffset, $driprelease->schedulestart); + + $midnight = strtotime('today midnight', $driprelease->schedulefinish); + $endminutes = $driprelease->schedulefinish - $midnight; + $end = strtotime('today midnight', $end ); + $end += $endminutes; + + $row['sessioncounter'] = $sessioncounter + 1; + $row['start'] = $start; + $row['end'] = $end; + return $row; + } + /** + * This is designed to return the coursemods in the order they are displayed on the course + * It is currently not used and may be deleted at some point, or the need for it may be obscured + * by the way test data means course activities are always in the order they were created. + * + * @param \stdClass $data + * @return array + */ + public function get_sequence(\stdClass $data): array { + global $DB; + $sql = 'SELECT sequence FROM {course_sections} WHERE course = :course AND sequence > "" ORDER BY section'; + $coursesequence = $DB->get_records_sql($sql, ['course' => $data->course]); + $activitiesordered = []; + $i = 0; + foreach ($coursesequence as $item) { + $temp = explode(',', $item->sequence); + foreach ($temp as $t) { + if (array_key_exists($t, $data->activities)) { + $activitiesordered[$i] = $t; + $i++; + } + } + } + return $activitiesordered; + } + /** + * Process the checkbox selections and upsert the database records + * + * @param \stdClass $fromform + * @param int $dripreleaseid + * @return int $insertedcount // For future testing purposes. + */ + public function manage_selections(\stdClass $fromform, int $dripreleaseid): int { + global $DB; + if (!isset($fromform->activitygroup)) { + return 0; + } + $moduleids = []; + foreach ($fromform->activitygroup as $key => $value) { + if ($value == 1) { + $moduleids[] = explode('_', $key)[1]; + } + } + $selections = $DB->get_records_menu('tool_driprelease_cmids', ['driprelease' => $dripreleaseid], null, 'id,coursemoduleid'); + + $todelete = array_diff($selections, $moduleids); + if ($todelete) { + list($insql, $inparams) = $DB->get_in_or_equal($todelete); + $DB->delete_records_select("tool_driprelease_cmids", "coursemoduleid $insql", $inparams); + } + $toinsert = array_diff($moduleids, $selections); + $insertedcount = 0; + foreach ($toinsert as $moduleid) { + $dataobject = (object) [ + 'driprelease' => $dripreleaseid, + 'coursemoduleid' => $moduleid, + ]; + $DB->insert_record('tool_driprelease_cmids', $dataobject); + $insertedcount ++; + } + return $insertedcount; + } + /** + * Get course modules given an instance of driprelease + * + * @param \stdClass $dripdata + * @return array + */ + public static function get_modules(\stdClass $dripdata): array { + global $DB; + $course = $DB->get_record('course', ['id' => $dripdata->courseid]); + $modinfo = get_fast_modinfo($course); + if (!$modinfo->instances || (!array_key_exists($dripdata->modtype, $modinfo->instances))) { + return []; + }; + $modules = []; + foreach ($modinfo->instances[$dripdata->modtype] as $cm) { + $modules[$cm->id] = $cm; + } + return $modules; + } + +} diff --git a/classes/event/driprelease_updated.php b/classes/event/driprelease_updated.php index ced6b94..12589e9 100644 --- a/classes/event/driprelease_updated.php +++ b/classes/event/driprelease_updated.php @@ -28,7 +28,7 @@ * The ool_driprelease viewed event class. * * @package tool_driprelease - * @copyright 2022 Marcus Green + * @copyright 2024 Marcus Green * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class driprelease_updated extends \core\event\base { @@ -46,7 +46,7 @@ protected function init() { * @return string */ public function get_description() { - return 'User '.$this->data['other']['username']. ' updated driprelease for course '.$this->data['other']['course']; + return get_string('user').' '.$this->data['other']['username']. get_string('updatedforcourse', 'tool_driprelease').$this->data['other']['course']; } } diff --git a/classes/event/driprelease_viewed.php b/classes/event/driprelease_viewed.php index 2fe6145..8c7e824 100644 --- a/classes/event/driprelease_viewed.php +++ b/classes/event/driprelease_viewed.php @@ -18,7 +18,7 @@ * The tool_driprelease viewed. * * @package tool_driprelease - * @copyright 2022 Marcus Green + * @copyright 2024 Marcus Green * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -46,7 +46,7 @@ protected function init() { * @return string */ public function get_description() { - return 'User '.$this->data['other']['username']. ' viewed driprelease for course '.$this->data['other']['course']; + return get_string('user'). ' '.$this->data['other']['username']. get_string('viewedforcourse', 'tool_driprelease').$this->data['other']['course']; } } diff --git a/driprelease_form.php b/driprelease_form.php index 6280683..b811842 100644 --- a/driprelease_form.php +++ b/driprelease_form.php @@ -23,7 +23,7 @@ */ defined('MOODLE_INTERNAL') || die(); - +use tool_driprelease\driprelease; require_once($CFG->libdir . '/formslib.php'); /** @@ -61,8 +61,7 @@ public function definition() { $mform->setExpanded('driprelease'); $mform->setType('courseid', PARAM_INT); - - $moduletypes = get_course_module_types($courseid); + $moduletypes = driprelease::get_course_module_types($courseid); $group[] = $mform->createElement('select', 'modtype', get_string('activitytype', 'tool_driprelease'), $moduletypes); $group[] = $mform->createElement('submit', 'refresh', get_string('refresh', 'tool_driprelease')); $string = get_string('activity', 'tool_driprelease'); diff --git a/lang/en/tool_driprelease.php b/lang/en/tool_driprelease.php index 03ca9e2..77da8e0 100755 --- a/lang/en/tool_driprelease.php +++ b/lang/en/tool_driprelease.php @@ -75,3 +75,4 @@ $string['stayavailable_help'] = 'Items will stay available at the session end. The equivalent of not setting the Until field in the restrictions setting'; $string['stayavailable_text'] = 'Stay available after session finish, set no end date'; $string['to'] = 'To'; +$string['updatedforcourse'] = 'updated driprelease for course'; diff --git a/lib.php b/lib.php index 4ee3b81..03313bf 100644 --- a/lib.php +++ b/lib.php @@ -22,7 +22,7 @@ * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ use core_availability\tree; - +use tool_driprelease\lib; /** * A core callback to make ther plugin appear in the "more" dropdown of courses * @@ -39,365 +39,3 @@ function tool_driprelease_extend_navigation_course(navigation_node $navigation, 'tool_driprelease')); } } - -/** - * Adds/updates an instance of driprelease and its related - * - * @param \stdClass $fromform - * @param int $courseid - * @return array - */ -function driprelease_update(\stdClass $fromform , int $courseid): array { - global $DB; - $dripreleaseid = $DB->get_field('tool_driprelease', 'id', ['courseid' => $courseid]); - - if ($dripreleaseid) { - $driprelease = (object) [ - 'id' => $dripreleaseid, - 'modtype' => $fromform->modtype, - 'courseid' => $courseid, - 'activitiespersession' => $fromform->activitiespersession, - 'sessionlength' => $fromform->sessiongroup['sessionlength'] ?? $fromform->sessionlength, - 'schedulestart' => $fromform->schedulestart, - 'schedulefinish' => $fromform->schedulefinish, - 'coursegroup' => $fromform->coursegroup, - 'stayavailable' => $fromform->stayavailable, - 'hideunselected' => $fromform->hideunselected, - 'resetunselected' => $fromform->resetunselected, - 'displaydisabled' => $fromform->displaydisabled, - ]; - $DB->update_record('tool_driprelease', $driprelease); - manage_selections($fromform, $dripreleaseid); - } else { - $driprelease = (object) [ - 'courseid' => $courseid, - 'modtype' => $fromform->modtype, - 'activitiespersession' => $fromform->activitiespersession, - 'sessionlength' => $fromform->sessionlength, - 'schedulestart' => $fromform->schedulestart, - 'schedulefinish' => $fromform->schedulefinish, - 'coursegroup' => $fromform->coursegroup, - 'stayavailable' => $fromform->stayavailable, - 'hideunselected' => $fromform->hideunselected, - 'resetunselected' => $fromform->resetunselected, - 'displaydisabled' => $fromform->displaydisabled, - ]; - $dripreleaseid = $DB->insert_record('tool_driprelease', $driprelease); - $driprelease->id = $dripreleaseid; - } - manage_selections($fromform, $dripreleaseid); - $selections = $DB->get_records_menu('tool_driprelease_cmids', ['driprelease' => $dripreleaseid], null, 'id,coursemoduleid'); - return [$selections, $driprelease]; -} - -/** - * Process the checkbox selections and upsert the database records - * - * @param \stdClass $fromform - * @param int $dripreleaseid - * @return int $insertedcount // For future testing purposes. - */ -function manage_selections(\stdClass $fromform, int $dripreleaseid): int { - global $DB; - if (!isset($fromform->activitygroup)) { - return 0; - } - $moduleids = []; - foreach ($fromform->activitygroup as $key => $value) { - if ($value == 1) { - $moduleids[] = explode('_', $key)[1]; - } - } - $selections = $DB->get_records_menu('tool_driprelease_cmids', ['driprelease' => $dripreleaseid], null, 'id,coursemoduleid'); - - $todelete = array_diff($selections, $moduleids); - if ($todelete) { - list($insql, $inparams) = $DB->get_in_or_equal($todelete); - $DB->delete_records_select("tool_driprelease_cmids", "coursemoduleid $insql", $inparams); - } - $toinsert = array_diff($moduleids, $selections); - $insertedcount = 0; - foreach ($toinsert as $moduleid) { - $dataobject = (object) [ - 'driprelease' => $dripreleaseid, - 'coursemoduleid' => $moduleid, - ]; - $DB->insert_record('tool_driprelease_cmids', $dataobject); - $insertedcount ++; - } - return $insertedcount; -} -/** - * Get names of modules on course for showing - * in the select element on the form. - * - * @param int $courseid - * @return array - */ -function get_course_module_types(int $courseid): array { - $modinfo = get_fast_modinfo($courseid); - $modtypes = []; - foreach ($modinfo->cms as $cm) { - $modtypes[$cm->modname] = get_string('pluginname', $cm->modname); - } - return $modtypes; -} - -/** - * Get course modules given an instance of driprelease - * - * @param \stdClass $driprelease - * @return array - */ -function get_modules(\stdClass $driprelease): array { - global $DB; - $course = $DB->get_record('course', ['id' => $driprelease->courseid]); - $modinfo = get_fast_modinfo($course); - if (!$modinfo->instances || (!array_key_exists($driprelease->modtype, $modinfo->instances))) { - return []; - }; - $modules = []; - foreach ($modinfo->instances[$driprelease->modtype] as $cm) { - $modules[$cm->id] = $cm; - } - return $modules; -} -/** - * Add another session header row in the display/preview of scheduled modules - * - * @param array $row - * @return array - */ -function add_header(array $row): array { - $header = $row; - $header['isheader'] = true; - $header['cm'] = (object) ['id' => -1]; - $header['name'] = 'Session'; - return $header; -} -/** - * Get the rows to be displayed in the schedule of dripped out modules - * - * @param \stdClass $driprelease - * @return array - */ -function get_table_data(\stdClass $driprelease): array { - global $DB; - $modules = get_modules($driprelease); - $contentcounter = 0; - $sessioncounter = 0; - $selections = []; - if (isset($driprelease->id)) { - $selections = $DB->get_records_menu('tool_driprelease_cmids', ['driprelease' => $driprelease->id], - null, 'id,coursemoduleid'); - } - foreach ($modules as $cm) { - $row['selected'] = in_array($cm->id, $selections) ? 'checked' : ""; - - if ($contentcounter % ($driprelease->activitiespersession) == 0) { - if ($row['selected'] > "") { - $row['calculatedavailability'] = driprelease_calculate_availability($driprelease, $sessioncounter); - $sessioncounter++; - } - $data[] = add_header($row); - } - $contentcounter++; - $row['modtype'] = $driprelease->modtype; - $data[] = row_fill($row, $cm); - } - return $data ?? []; -} - -/** - * Simplify get_table_data - * - * @param array $row - * @param cm_info $cm - * @return array - */ -function row_fill(array $row, cm_info $cm): array { - global $DB; - - $details = $DB->get_record($row['modtype'], ['id' => $cm->instance]); - $row['cm'] = $cm; - $row['intro'] = strip_tags($details->intro); - if ($cm->modname == 'quiz') { - $questions = $DB->get_records('quiz_slots', ['quizid' => $cm->instance]); - $row['questioncount'] = count($questions); - } - $row['isheader'] = false; - $row['id'] = $cm->id; - $row['name'] = $cm->name; - $row['moduleavailability'] = get_availability($cm->availability); - return $row; -} - -/** - * Write the availability back to the course_modules table - * See https://moodledev.io/docs/apis/subsystems/availability/ - * @param array $tabledata - * @param \stdClass $driprelease - * @return void - */ -function update_availability(array $tabledata, \stdClass $driprelease) { - global $DB, $COURSE; - $updatecount = 0; - - foreach ($tabledata as $module) { - if (!$module['isheader']) { - if (!$module['selected'] == "checked") { - $cm = $module['cm']; - if ($driprelease->hideunselected) { - set_coursemodule_visible($cm->id, false, false); - \core\event\course_module_updated::create_from_cm($cm)->trigger(); - } else { - set_coursemodule_visible($cm->id, true, true); - } - if ($driprelease->resetunselected) { - $DB->set_field( - 'course_modules', - 'availability', - '', - ['id' => $module['cm']->id] - ); - } - continue; - } - if (!array_key_exists('calculatedavailability', $module)) { - continue; - } - // Don't write any availability restrictions after the end of the schedule. - if ($module['calculatedavailability']['start'] > $driprelease->schedulefinish) { - continue; - } - $cm = $module['cm']; - set_coursemodule_visible($cm->id, true, true); - \core\event\course_module_updated::create_from_cm($cm)->trigger(); - - $availability = $module['calculatedavailability']; - $restrictions = []; - if ($driprelease->coursegroup) { - $restrictions[] = \availability_group\condition::get_json($driprelease->coursegroup); - } - $restrictions[] = \availability_date\condition::get_json(">=", $availability['start']); - if (!$driprelease->stayavailable) { - $restrictions[] = \availability_date\condition::get_json("<", $availability['end']); - } - $showvalue = false; - if ($driprelease->displaydisabled) { - $showvalue = true; - } - - $showc = array_fill(0, count($restrictions), $showvalue); - $restrictionsclass = tree::get_root_json($restrictions, tree::OP_AND, $showc); - - $DB->set_field( - 'course_modules', - 'availability', - json_encode($restrictionsclass), - ['id' => $module['cm']->id] - ); - $updatecount++; - } - } - $modulenameplural = get_string('modulenameplural', $driprelease->modtype); - $msg = get_string('updated', 'moodle', $updatecount). " ".$modulenameplural; - $refresh = optional_param('refresh', 0, PARAM_RAW); - if (! $refresh) { - \core\notification::add($msg, \core\notification::SUCCESS); - rebuild_course_cache($COURSE->id); - } -} - - -/** - * Take an optional JSON string as input and return an array containing - * the date-related availability information. - * * - * If the input JSON is empty, the function returns an empty array. - * - * Loop through each restriction in the JSON object and checks - * if the restriction type is "date". If true, it extracts the operator and - * timestamp from the restriction object. - * - * Based on the operator, the function updates the availability array with - * the formatted date string using userdate() function. - * - * The function returns the availability array containing the 'from' and 'to' - * dates in a human-readable format. - * @param string $json The optional JSON input string containing the availability restrictions - * @return array The availability array containing the 'from' and 'to' dates - */ -function get_availability(?string $json): array { - $availability = []; - if (empty($json)) { - return $availability; - } - $decoded = json_decode($json); - foreach ($decoded->c as $restriction) { - if (property_exists($restriction, 'type') && $restriction->type == "date") { - $operator = $restriction->d; - if ($operator == ">=") { - $datetime = $restriction->t; - $availability['from'] = userdate($datetime, '%a %d %b %Y %H:%M'); - } else { - $datetime = $restriction->t; - $availability['to'] = userdate($datetime, '%a %d %b %Y %H:%M'); - } - } - } - return $availability; -} - - - /** - * Calculate the dripping out of availability and format the dates for the session labels - * - * @param \stdClass $driprelease - * @param int $sessioncounter - * @return array - */ -function driprelease_calculate_availability(\stdClass $driprelease, int $sessioncounter): array { - $row = []; - $daysrepeat = $sessioncounter * $driprelease->sessionlength; - $daysoffset = " + $daysrepeat day"; - $start = strtotime(' + ' . $daysrepeat . ' day', $driprelease->schedulestart); - $daysoffset = " + " . (($daysrepeat - 1) + $driprelease->sessionlength) . " day "; - $end = strtotime($daysoffset, $driprelease->schedulestart); - - $midnight = strtotime('today midnight', $driprelease->schedulefinish); - $endminutes = $driprelease->schedulefinish - $midnight; - $end = strtotime('today midnight', $end ); - $end += $endminutes; - - $row['sessioncounter'] = $sessioncounter + 1; - $row['start'] = $start; - $row['end'] = $end; - return $row; -} - -/** - * This is designed to return the coursemods in the order they are displayed on the course - * It is currently not used and may be deleted at some point, or the need for it may be obscured - * by the way test data means course activities are always in the order they were created. - * - * @param \stdClass $data - * @return array - */ -function get_sequence(\stdClass $data): array { - global $DB; - $sql = 'SELECT sequence FROM {course_sections} WHERE course = :course AND sequence > "" ORDER BY section'; - $coursesequence = $DB->get_records_sql($sql, ['course' => $data->course]); - $activitiesordered = []; - $i = 0; - foreach ($coursesequence as $item) { - $temp = explode(',', $item->sequence); - foreach ($temp as $t) { - if (array_key_exists($t, $data->activities)) { - $activitiesordered[$i] = $t; - $i++; - } - } - } - return $activitiesordered; -} diff --git a/phpunit.xml b/phpunit.xml index a0eb0fa..6cd4cf8 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -8,6 +8,8 @@ tests lang db + classes/event + classes/privacy settings.php version.php index.php diff --git a/tests/coverage-html/classes/dashboard.html b/tests/coverage-html/classes/dashboard.html index 2c94cad..8ff72d1 100644 --- a/tests/coverage-html/classes/dashboard.html +++ b/tests/coverage-html/classes/dashboard.html @@ -58,6 +58,7 @@

Insufficient Coverage

+ tool_driprelease\driprelease0% tool_driprelease\event\driprelease_updated0% tool_driprelease\event\driprelease_viewed0% tool_driprelease\privacy\provider0% @@ -77,6 +78,7 @@

Project Risks

+ tool_driprelease\driprelease2162 @@ -114,6 +116,17 @@

Insufficient Coverage

+ update0% + get_table_data0% + update_availability0% + row_fill0% + get_course_module_types0% + add_header0% + get_availability0% + calculate_availability0% + get_sequence0% + manage_selections0% + get_modules0% init0% get_description0% init0% @@ -135,6 +148,15 @@

Project Risks

+ update_availability156 + get_table_data42 + get_availability42 + manage_selections42 + get_sequence20 + get_modules20 + update6 + row_fill6 + get_course_module_types6 @@ -144,7 +166,7 @@

Project Risks

@@ -163,7 +185,7 @@

Project Risks

.yAxis.tickFormat(d3.format('d')); d3.select('#classCoverageDistribution svg') - .datum(getCoverageDistributionData([3,0,0,0,0,0,0,0,0,0,0,0], "Class Coverage")) + .datum(getCoverageDistributionData([4,0,0,0,0,0,0,0,0,0,0,0], "Class Coverage")) .transition().duration(500).call(chart); nv.utils.windowResize(chart.update); @@ -181,7 +203,7 @@

Project Risks

.yAxis.tickFormat(d3.format('d')); d3.select('#methodCoverageDistribution svg') - .datum(getCoverageDistributionData([5,0,0,0,0,0,0,0,0,0,0,0], "Method Coverage")) + .datum(getCoverageDistributionData([16,0,0,0,0,0,0,0,0,0,0,0], "Method Coverage")) .transition().duration(500).call(chart); nv.utils.windowResize(chart.update); @@ -231,7 +253,7 @@

Project Risks

chart.yAxis.axisLabel('Cyclomatic Complexity'); d3.select('#classComplexity svg') - .datum(getComplexityData([[0,2,"tool_driprelease\\event\\driprelease_updated<\/a>"],[0,2,"tool_driprelease\\event\\driprelease_viewed<\/a>"],[0,1,"tool_driprelease\\privacy\\provider<\/a>"]], 'Class Complexity')) + .datum(getComplexityData([[0,46,"tool_driprelease\\driprelease<\/a>"],[0,2,"tool_driprelease\\event\\driprelease_updated<\/a>"],[0,2,"tool_driprelease\\event\\driprelease_viewed<\/a>"],[0,1,"tool_driprelease\\privacy\\provider<\/a>"]], 'Class Complexity')) .transition() .duration(500) .call(chart); @@ -255,7 +277,7 @@

Project Risks

chart.yAxis.axisLabel('Method Complexity'); d3.select('#methodComplexity svg') - .datum(getComplexityData([[0,1,"
tool_driprelease\\event\\driprelease_updated::init<\/a>"],[0,1,"tool_driprelease\\event\\driprelease_updated::get_description<\/a>"],[0,1,"tool_driprelease\\event\\driprelease_viewed::init<\/a>"],[0,1,"tool_driprelease\\event\\driprelease_viewed::get_description<\/a>"],[0,1,"tool_driprelease\\privacy\\provider::get_reason<\/a>"]], 'Method Complexity')) + .datum(getComplexityData([[0,2,"tool_driprelease\\driprelease::update<\/a>"],[0,6,"tool_driprelease\\driprelease::get_table_data<\/a>"],[0,12,"tool_driprelease\\driprelease::update_availability<\/a>"],[0,2,"tool_driprelease\\driprelease::row_fill<\/a>"],[0,2,"tool_driprelease\\driprelease::get_course_module_types<\/a>"],[0,1,"tool_driprelease\\driprelease::add_header<\/a>"],[0,6,"tool_driprelease\\driprelease::get_availability<\/a>"],[0,1,"tool_driprelease\\driprelease::calculate_availability<\/a>"],[0,4,"tool_driprelease\\driprelease::get_sequence<\/a>"],[0,6,"tool_driprelease\\driprelease::manage_selections<\/a>"],[0,4,"tool_driprelease\\driprelease::get_modules<\/a>"],[0,1,"tool_driprelease\\event\\driprelease_updated::init<\/a>"],[0,1,"tool_driprelease\\event\\driprelease_updated::get_description<\/a>"],[0,1,"tool_driprelease\\event\\driprelease_viewed::init<\/a>"],[0,1,"tool_driprelease\\event\\driprelease_viewed::get_description<\/a>"],[0,1,"tool_driprelease\\privacy\\provider::get_reason<\/a>"]], 'Method Complexity')) .transition() .duration(500) .call(chart); diff --git a/tests/coverage-html/classes/driprelease.php.html b/tests/coverage-html/classes/driprelease.php.html new file mode 100644 index 0000000..b0c52a9 --- /dev/null +++ b/tests/coverage-html/classes/driprelease.php.html @@ -0,0 +1,756 @@ + + + + + Code Coverage for /var/www/html/mdl44/admin/tool/driprelease/classes/driprelease.php + + + + + + + +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 200
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 11
CRAP
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 1
driprelease
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 200
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 11
2162
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 1
 update
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 38
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 1
6
 get_table_data
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 19
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 1
42
 update_availability
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 51
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 1
156
 row_fill
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 12
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 1
6
 get_course_module_types
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 5
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 1
6
 add_header
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 5
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 1
2
 get_availability
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 13
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 1
42
 calculate_availability
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 14
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 1
2
 get_sequence
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 12
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 1
20
 manage_selections
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 22
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 1
42
 get_modules
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 9
+
+ 0.00% covered (danger) +
+
+
0.00%
0 / 1
20
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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
17namespace tool_driprelease;
18use core_availability\tree;
19/**
20 * Class driprelease
21 *
22 * @package    tool_driprelease
23 * @copyright  2024 YOUR NAME <your@email.com>
24 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 */
26class driprelease {
27    /**
28     * Adds/updates an instance of driprelease and its related
29     *
30     * @param \stdClass $fromform
31     * @param int $courseid
32     * @return array
33     */
34    public function update(\stdClass $fromform , int $courseid): array {
35        global $DB;
36        $lib = new lib();
37        $dripreleaseid = $DB->get_field('tool_driprelease', 'id', ['courseid' => $courseid]);
38
39        if ($dripreleaseid) {
40            $driprelease = (object) [
41            'id' => $dripreleaseid,
42            'modtype' => $fromform->modtype,
43            'courseid' => $courseid,
44            'activitiespersession' => $fromform->activitiespersession,
45            'sessionlength' => $fromform->sessiongroup['sessionlength'] ?? $fromform->sessionlength,
46            'schedulestart' => $fromform->schedulestart,
47            'schedulefinish' => $fromform->schedulefinish,
48            'coursegroup' => $fromform->coursegroup,
49            'stayavailable' => $fromform->stayavailable,
50            'hideunselected' => $fromform->hideunselected,
51            'resetunselected' => $fromform->resetunselected,
52            'displaydisabled' => $fromform->displaydisabled,
53            ];
54            $DB->update_record('tool_driprelease', $driprelease);
55            $lib->manage_selections($fromform, $dripreleaseid);
56        } else {
57            $driprelease = (object) [
58            'courseid' => $courseid,
59            'modtype' => $fromform->modtype,
60            'activitiespersession' => $fromform->activitiespersession,
61            'sessionlength' => $fromform->sessionlength,
62            'schedulestart' => $fromform->schedulestart,
63            'schedulefinish' => $fromform->schedulefinish,
64            'coursegroup' => $fromform->coursegroup,
65            'stayavailable' => $fromform->stayavailable,
66            'hideunselected' => $fromform->hideunselected,
67            'resetunselected' => $fromform->resetunselected,
68            'displaydisabled' => $fromform->displaydisabled,
69            ];
70            $dripreleaseid = $DB->insert_record('tool_driprelease', $driprelease);
71            $driprelease->id = $dripreleaseid;
72        }
73        $this->manage_selections($fromform, $dripreleaseid);
74        $selections = $DB->get_records_menu('tool_driprelease_cmids', ['driprelease' => $dripreleaseid], null, 'id,coursemoduleid');
75        return [$selections, $driprelease];
76    }
77    /**
78     * Get the rows to be displayed in the schedule of dripped out modules
79     *
80     * @param \stdClass $driprelease
81     * @return array
82     */
83    public function get_table_data(\stdClass $dripdata): array {
84        global $DB;
85        $modules = $this->get_modules($dripdata);
86        $contentcounter = 0;
87        $sessioncounter = 0;
88        $selections = [];
89        if (isset($driprelease->id)) {
90            $selections = $DB->get_records_menu('tool_driprelease_cmids', ['driprelease' => $driprelease->id],
91            null, 'id,coursemoduleid');
92        }
93        foreach ($modules as $cm) {
94            $row['selected'] = in_array($cm->id, $selections) ? 'checked' : "";
95
96            if ($contentcounter % ($dripdata->activitiespersession) == 0) {
97                if ($row['selected'] > "") {
98                    $row['calculatedavailability'] = $this->calculate_availability($dripdata, $sessioncounter);
99                    $sessioncounter++;
100                }
101                $data[] = $this->add_header($row);
102            }
103            $contentcounter++;
104            $row['modtype'] = $dripdata->modtype;
105            $data[] = $this->row_fill($row, $cm);
106        }
107        return $data ?? [];
108    }
109    /**
110     * Write the availability back to the course_modules table
111     * See https://moodledev.io/docs/apis/subsystems/availability/
112     * @param array $tabledata
113     * @param \stdClass $driprelease
114     * @return void
115     */
116    public function update_availability(array $tabledata, \stdClass $dripdata) {
117        global $DB, $COURSE;
118        $updatecount = 0;
119        foreach ($tabledata as $module) {
120            if (!$module['isheader']) {
121                if (!$module['selected'] == "checked") {
122                    $cm = $module['cm'];
123                    if ($dripdata->hideunselected) {
124                        set_coursemodule_visible($cm->id, false, false);
125                        \core\event\course_module_updated::create_from_cm($cm)->trigger();
126                    } else {
127                        set_coursemodule_visible($cm->id, true, true);
128                    }
129                    xdebug_break();
130
131                    if ($dripdata->resetunselected) {
132                        $DB->set_field(
133                        'course_modules',
134                        'availability',
135                        '',
136                        ['id' => $module['cm']->id]
137                        );
138                    }
139                    continue;
140                }
141                if (!array_key_exists('calculatedavailability', $module)) {
142                    continue;
143                }
144                // Don't write any availability restrictions after the end of the schedule.
145                if ($module['calculatedavailability']['start'] > $dripdata->schedulefinish) {
146                    continue;
147                }
148                $cm = $module['cm'];
149                set_coursemodule_visible($cm->id, true, true);
150                \core\event\course_module_updated::create_from_cm($cm)->trigger();
151
152                $availability = $module['calculatedavailability'];
153                $restrictions = [];
154                if ($dripdata->coursegroup) {
155                    $restrictions[] = \availability_group\condition::get_json($driprelease->coursegroup);
156                }
157                $restrictions[] = \availability_date\condition::get_json(">=", $availability['start']);
158                if (!$dripdata->stayavailable) {
159                    $restrictions[] = \availability_date\condition::get_json("<", $availability['end']);
160                }
161                $showvalue = false;
162                if ($dripdata->displaydisabled) {
163                    $showvalue = true;
164                }
165
166                $showc = array_fill(0, count($restrictions), $showvalue);
167                $restrictionsclass = tree::get_root_json($restrictions, tree::OP_AND, $showc);
168
169                $DB->set_field(
170                'course_modules',
171                'availability',
172                json_encode($restrictionsclass),
173                ['id' => $module['cm']->id]
174                );
175                $updatecount++;
176            }
177        }
178        $modulenameplural = get_string('modulenameplural', $dripdata->modtype);
179        $msg = get_string('updated', 'moodle', $updatecount). " ".$modulenameplural;
180        $refresh = optional_param('refresh', 0, PARAM_RAW);
181        if (! $refresh) {
182            \core\notification::add($msg, \core\notification::SUCCESS);
183            rebuild_course_cache($COURSE->id);
184        }
185    }
186    /**
187     * Simplify get_table_data
188     *
189     * @param array $row
190     * @param \cm_info $cm
191     * @return array
192     */
193    private function row_fill(array $row, \cm_info $cm): array {
194        global $DB;
195
196        $details = $DB->get_record($row['modtype'], ['id' => $cm->instance]);
197        $row['cm'] = $cm;
198        $row['intro'] = strip_tags($details->intro);
199        if ($cm->modname == 'quiz') {
200            $questions = $DB->get_records('quiz_slots', ['quizid' => $cm->instance]);
201            $row['questioncount'] = count($questions);
202        }
203        $row['isheader'] = false;
204        $row['id'] = $cm->id;
205        $row['name'] = $cm->name;
206        $row['moduleavailability'] = $this->get_availability($cm->availability);
207        return $row;
208    }
209    /**
210     * Get names of modules on course for showing
211     * in the select element on the form.
212     *
213     * @param int $courseid
214     * @return array
215     */
216    public static function get_course_module_types(int $courseid): array {
217        $modinfo = get_fast_modinfo($courseid);
218        $modtypes = [];
219        foreach ($modinfo->cms as $cm) {
220            $modtypes[$cm->modname] = get_string('pluginname', $cm->modname);
221        }
222        return $modtypes;
223    }
224    /**
225     * Add another session header row in the display/preview of scheduled modules
226     *
227     * @param array $row
228     * @return array
229     */
230    private function add_header(array $row): array {
231        $header = $row;
232        $header['isheader'] = true;
233        $header['cm'] = (object) ['id' => -1];
234        $header['name'] = 'Session';
235        return $header;
236    }
237    /**
238     * Take an optional JSON string as input and return an array containing
239     * the date-related availability information.
240     * *
241     * If the input JSON is empty, the function returns an empty array.
242     *
243     * Loop through each restriction in the JSON object and checks
244     * if the restriction type is "date". If true, it extracts the operator and
245     * timestamp from the restriction object.
246     *
247     * Based on the operator, the function updates the availability array with
248     * the formatted date string using userdate() function.
249     *
250     * The function returns the availability array containing the 'from' and 'to'
251     * dates in a human-readable format.
252     * @param string $json The optional JSON input string containing the availability restrictions
253     * @return array The availability array containing the 'from' and 'to' dates
254     */
255    public function get_availability(?string $json): array {
256        $availability = [];
257        if (empty($json)) {
258            return $availability;
259        }
260        $decoded = json_decode($json);
261        foreach ($decoded->c as $restriction) {
262            if (property_exists($restriction, 'type') && $restriction->type == "date") {
263                $operator = $restriction->d;
264                if ($operator == ">=") {
265                    $datetime = $restriction->t;
266                    $availability['from'] = userdate($datetime, '%a %d %b %Y %H:%M');
267                } else {
268                    $datetime = $restriction->t;
269                    $availability['to'] = userdate($datetime, '%a %d %b %Y %H:%M');
270                }
271            }
272        }
273        return $availability;
274    }
275
276    /**
277     * Calculate the dripping out of availability and format the dates for the session labels
278     *
279     * @param \stdClass $driprelease
280     * @param int $sessioncounter
281     * @return array
282     */
283    public function calculate_availability(\stdClass $driprelease, int $sessioncounter): array {
284        $row = [];
285        $daysrepeat = $sessioncounter * $driprelease->sessionlength;
286        $daysoffset = " + $daysrepeat day";
287        $start = strtotime(' + ' . $daysrepeat . ' day', $driprelease->schedulestart);
288        $daysoffset = " + " . (($daysrepeat - 1) + $driprelease->sessionlength) . " day ";
289        $end = strtotime($daysoffset, $driprelease->schedulestart);
290
291        $midnight = strtotime('today midnight', $driprelease->schedulefinish);
292        $endminutes = $driprelease->schedulefinish - $midnight;
293        $end = strtotime('today midnight', $end );
294        $end += $endminutes;
295
296        $row['sessioncounter'] = $sessioncounter + 1;
297        $row['start'] = $start;
298        $row['end'] = $end;
299        return $row;
300    }
301    /**
302     * This is designed to return the coursemods in the order they are displayed on the course
303     * It is currently not used and may be deleted at some point, or the need for it may be obscured
304     * by the way test data means course activities are always in the order they were created.
305     *
306     * @param \stdClass $data
307     * @return array
308     */
309    public function get_sequence(\stdClass $data): array {
310        global $DB;
311        $sql = 'SELECT sequence FROM {course_sections} WHERE course = :course AND sequence > "" ORDER BY section';
312        $coursesequence = $DB->get_records_sql($sql, ['course' => $data->course]);
313        $activitiesordered = [];
314        $i = 0;
315        foreach ($coursesequence as $item) {
316            $temp = explode(',', $item->sequence);
317            foreach ($temp as $t) {
318                if (array_key_exists($t, $data->activities)) {
319                    $activitiesordered[$i] = $t;
320                    $i++;
321                }
322            }
323        }
324        return $activitiesordered;
325    }
326        /**
327     * Process the checkbox selections and upsert the database records
328     *
329     * @param \stdClass $fromform
330     * @param int $dripreleaseid
331     * @return int $insertedcount // For future testing purposes.
332     */
333    public function manage_selections(\stdClass $fromform, int $dripreleaseid): int {
334        global $DB;
335        if (!isset($fromform->activitygroup)) {
336            return 0;
337        }
338        $moduleids = [];
339        foreach ($fromform->activitygroup as $key => $value) {
340            if ($value == 1) {
341                $moduleids[] = explode('_', $key)[1];
342            }
343        }
344        $selections = $DB->get_records_menu('tool_driprelease_cmids', ['driprelease' => $dripreleaseid], null, 'id,coursemoduleid');
345
346        $todelete = array_diff($selections, $moduleids);
347        if ($todelete) {
348            list($insql, $inparams) = $DB->get_in_or_equal($todelete);
349            $DB->delete_records_select("tool_driprelease_cmids", "coursemoduleid $insql", $inparams);
350        }
351        $toinsert = array_diff($moduleids, $selections);
352        $insertedcount = 0;
353        foreach ($toinsert as $moduleid) {
354            $dataobject = (object) [
355            'driprelease' => $dripreleaseid,
356            'coursemoduleid' => $moduleid,
357            ];
358            $DB->insert_record('tool_driprelease_cmids', $dataobject);
359            $insertedcount ++;
360        }
361        return $insertedcount;
362    }
363    /**
364     * Get course modules given an instance of driprelease
365     *
366     * @param \stdClass $driprelease
367     * @return array
368     */
369    public static function get_modules(\stdClass $dripdata): array {
370        global $DB;
371        $course = $DB->get_record('course', ['id' => $dripdata->courseid]);
372        $modinfo = get_fast_modinfo($course);
373        if (!$modinfo->instances || (!array_key_exists($dripdata->modtype, $modinfo->instances))) {
374            return [];
375        };
376        $modules = [];
377        foreach ($modinfo->instances[$dripdata->modtype] as $cm) {
378            $modules[$cm->id] = $cm;
379        }
380        return $modules;
381    }
382
383}
+ + +
+
+

Legend

+

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

+

+ Generated by php-code-coverage 9.2.31 using PHP 8.2.19 and PHPUnit 9.6.18 at Thu Oct 24 19:13:44 AWST 2024. +

+ + + +
+
+ + + + + + diff --git a/tests/coverage-html/classes/event/dashboard.html b/tests/coverage-html/classes/event/dashboard.html index 64eb749..028a147 100644 --- a/tests/coverage-html/classes/event/dashboard.html +++ b/tests/coverage-html/classes/event/dashboard.html @@ -143,7 +143,7 @@

Project Risks

diff --git a/tests/coverage-html/classes/event/driprelease_updated.php.html b/tests/coverage-html/classes/event/driprelease_updated.php.html index 487f468..7a156f7 100644 --- a/tests/coverage-html/classes/event/driprelease_updated.php.html +++ b/tests/coverage-html/classes/event/driprelease_updated.php.html @@ -214,7 +214,7 @@

Legend

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

- Generated by php-code-coverage 9.2.31 using PHP 8.2.19 and PHPUnit 9.6.18 at Sun Aug 11 8:46:25 AWST 2024. + Generated by php-code-coverage 9.2.31 using PHP 8.2.19 and PHPUnit 9.6.18 at Thu Oct 24 19:13:44 AWST 2024.

diff --git a/tests/coverage-html/classes/event/driprelease_viewed.php.html b/tests/coverage-html/classes/event/driprelease_viewed.php.html index 97cf049..9766881 100644 --- a/tests/coverage-html/classes/event/driprelease_viewed.php.html +++ b/tests/coverage-html/classes/event/driprelease_viewed.php.html @@ -214,7 +214,7 @@

Legend

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

- Generated by php-code-coverage 9.2.31 using PHP 8.2.19 and PHPUnit 9.6.18 at Sun Aug 11 8:46:25 AWST 2024. + Generated by php-code-coverage 9.2.31 using PHP 8.2.19 and PHPUnit 9.6.18 at Thu Oct 24 19:13:44 AWST 2024.

diff --git a/tests/coverage-html/classes/event/index.html b/tests/coverage-html/classes/event/index.html index 304c94d..dcf56af 100644 --- a/tests/coverage-html/classes/event/index.html +++ b/tests/coverage-html/classes/event/index.html @@ -140,7 +140,7 @@

Legend

High: 90% to 100%

- Generated by php-code-coverage 9.2.31 using PHP 8.2.19 and PHPUnit 9.6.18 at Sun Aug 11 8:46:25 AWST 2024. + Generated by php-code-coverage 9.2.31 using PHP 8.2.19 and PHPUnit 9.6.18 at Thu Oct 24 19:13:44 AWST 2024.

diff --git a/tests/coverage-html/classes/index.html b/tests/coverage-html/classes/index.html index 7b5a9e2..8c78ef7 100644 --- a/tests/coverage-html/classes/index.html +++ b/tests/coverage-html/classes/index.html @@ -51,7 +51,7 @@
0.00%
-
0 / 7
+
0 / 207
0.00% covered (danger) @@ -59,7 +59,7 @@
0.00%
-
0 / 5
+
0 / 16
0.00% covered (danger) @@ -67,7 +67,7 @@
0.00%
-
0 / 3
+
0 / 4
@@ -126,6 +126,34 @@
0 / 1
+ + driprelease.php +
+
+ 0.00% covered (danger) +
+
+ +
0.00%
+
0 / 200
+
+
+ 0.00% covered (danger) +
+
+ +
0.00%
+
0 / 11
+
+
+ 0.00% covered (danger) +
+
+ +
0.00%
+
0 / 1
+ + @@ -139,7 +167,7 @@

Legend

High: 90% to 100%

- Generated by php-code-coverage 9.2.31 using PHP 8.2.19 and PHPUnit 9.6.18 at Sun Aug 11 8:46:25 AWST 2024. + Generated by php-code-coverage 9.2.31 using PHP 8.2.19 and PHPUnit 9.6.18 at Thu Oct 24 19:13:44 AWST 2024.

diff --git a/tests/coverage-html/classes/lib.php.html b/tests/coverage-html/classes/lib.php.html new file mode 100644 index 0000000..f6461ea --- /dev/null +++ b/tests/coverage-html/classes/lib.php.html @@ -0,0 +1,131 @@ + + + + + Code Coverage for /var/www/html/mdl44/admin/tool/driprelease/classes/lib.php + + + + + + + +
+
+
+ +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
lib
n/a
0 / 0
n/a
0 / 0
0
n/a
0 / 0
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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
17namespace tool_driprelease;
18
19/**
20 * Class lib
21 *
22 * @package    tool_driprelease
23 * @copyright  2024 YOUR NAME <your@email.com>
24 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 */
26class lib {
27
28
29
30}
+ + +
+
+

Legend

+

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

+

+ Generated by php-code-coverage 9.2.31 using PHP 8.2.19 and PHPUnit 9.6.18 at Thu Oct 24 19:02:25 AWST 2024. +

+ + + +
+
+ + + + + + diff --git a/tests/coverage-html/classes/privacy/dashboard.html b/tests/coverage-html/classes/privacy/dashboard.html index efe9caa..7aedd92 100644 --- a/tests/coverage-html/classes/privacy/dashboard.html +++ b/tests/coverage-html/classes/privacy/dashboard.html @@ -139,7 +139,7 @@

Project Risks

diff --git a/tests/coverage-html/classes/privacy/index.html b/tests/coverage-html/classes/privacy/index.html index b513582..ba5cc90 100644 --- a/tests/coverage-html/classes/privacy/index.html +++ b/tests/coverage-html/classes/privacy/index.html @@ -112,7 +112,7 @@

Legend

High: 90% to 100%

- Generated by php-code-coverage 9.2.31 using PHP 8.2.19 and PHPUnit 9.6.18 at Sun Aug 11 8:46:25 AWST 2024. + Generated by php-code-coverage 9.2.31 using PHP 8.2.19 and PHPUnit 9.6.18 at Thu Oct 24 19:13:44 AWST 2024.

diff --git a/tests/coverage-html/classes/privacy/provider.php.html b/tests/coverage-html/classes/privacy/provider.php.html index 7d4cffe..364b65b 100644 --- a/tests/coverage-html/classes/privacy/provider.php.html +++ b/tests/coverage-html/classes/privacy/provider.php.html @@ -182,7 +182,7 @@

Legend

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

- Generated by php-code-coverage 9.2.31 using PHP 8.2.19 and PHPUnit 9.6.18 at Sun Aug 11 8:46:25 AWST 2024. + Generated by php-code-coverage 9.2.31 using PHP 8.2.19 and PHPUnit 9.6.18 at Thu Oct 24 19:13:44 AWST 2024.

diff --git a/tests/coverage-html/dashboard.html b/tests/coverage-html/dashboard.html index d2f013c..cfadfb0 100644 --- a/tests/coverage-html/dashboard.html +++ b/tests/coverage-html/dashboard.html @@ -57,6 +57,7 @@

Insufficient Coverage

+
tool_driprelease\driprelease0% tool_driprelease\event\driprelease_updated0% tool_driprelease\event\driprelease_viewed0% tool_driprelease\privacy\provider0% @@ -77,6 +78,7 @@

Project Risks

+ tool_driprelease\driprelease2162 tool_driprelease_form702 @@ -115,6 +117,17 @@

Insufficient Coverage

+ update0% + get_table_data0% + update_availability0% + row_fill0% + get_course_module_types0% + add_header0% + get_availability0% + calculate_availability0% + get_sequence0% + manage_selections0% + get_modules0% init0% get_description0% init0% @@ -141,11 +154,20 @@

Project Risks

+ update_availability156 validation56 + get_table_data42 + get_availability42 + manage_selections42 definition42 set_data30 add_action_buttons30 + get_sequence20 + get_modules20 get_modules12 + update6 + row_fill6 + get_course_module_types6 @@ -155,7 +177,7 @@

Project Risks

@@ -174,7 +196,7 @@

Project Risks

.yAxis.tickFormat(d3.format('d')); d3.select('#classCoverageDistribution svg') - .datum(getCoverageDistributionData([4,0,0,0,0,0,0,0,0,0,0,0], "Class Coverage")) + .datum(getCoverageDistributionData([5,0,0,0,0,0,0,0,0,0,0,0], "Class Coverage")) .transition().duration(500).call(chart); nv.utils.windowResize(chart.update); @@ -192,7 +214,7 @@

Project Risks

.yAxis.tickFormat(d3.format('d')); d3.select('#methodCoverageDistribution svg') - .datum(getCoverageDistributionData([10,0,0,0,0,0,0,0,0,0,0,0], "Method Coverage")) + .datum(getCoverageDistributionData([21,0,0,0,0,0,0,0,0,0,0,0], "Method Coverage")) .transition().duration(500).call(chart); nv.utils.windowResize(chart.update); @@ -242,7 +264,7 @@

Project Risks

chart.yAxis.axisLabel('Cyclomatic Complexity'); d3.select('#classComplexity svg') - .datum(getComplexityData([[0,2,"tool_driprelease\\event\\driprelease_updated<\/a>"],[0,2,"tool_driprelease\\event\\driprelease_viewed<\/a>"],[0,1,"tool_driprelease\\privacy\\provider<\/a>"],[0,26,"tool_driprelease_form<\/a>"]], 'Class Complexity')) + .datum(getComplexityData([[0,46,"tool_driprelease\\driprelease<\/a>"],[0,2,"tool_driprelease\\event\\driprelease_updated<\/a>"],[0,2,"tool_driprelease\\event\\driprelease_viewed<\/a>"],[0,1,"tool_driprelease\\privacy\\provider<\/a>"],[0,26,"tool_driprelease_form<\/a>"]], 'Class Complexity')) .transition() .duration(500) .call(chart); @@ -266,7 +288,7 @@

Project Risks

chart.yAxis.axisLabel('Method Complexity'); d3.select('#methodComplexity svg') - .datum(getComplexityData([[0,1,"
tool_driprelease\\event\\driprelease_updated::init<\/a>"],[0,1,"tool_driprelease\\event\\driprelease_updated::get_description<\/a>"],[0,1,"tool_driprelease\\event\\driprelease_viewed::init<\/a>"],[0,1,"tool_driprelease\\event\\driprelease_viewed::get_description<\/a>"],[0,1,"tool_driprelease\\privacy\\provider::get_reason<\/a>"],[0,6,"tool_driprelease_form::definition<\/a>"],[0,7,"tool_driprelease_form::validation<\/a>"],[0,3,"tool_driprelease_form::get_modules<\/a>"],[0,5,"tool_driprelease_form::set_data<\/a>"],[0,5,"tool_driprelease_form::add_action_buttons<\/a>"]], 'Method Complexity')) + .datum(getComplexityData([[0,2,"tool_driprelease\\driprelease::update<\/a>"],[0,6,"tool_driprelease\\driprelease::get_table_data<\/a>"],[0,12,"tool_driprelease\\driprelease::update_availability<\/a>"],[0,2,"tool_driprelease\\driprelease::row_fill<\/a>"],[0,2,"tool_driprelease\\driprelease::get_course_module_types<\/a>"],[0,1,"tool_driprelease\\driprelease::add_header<\/a>"],[0,6,"tool_driprelease\\driprelease::get_availability<\/a>"],[0,1,"tool_driprelease\\driprelease::calculate_availability<\/a>"],[0,4,"tool_driprelease\\driprelease::get_sequence<\/a>"],[0,6,"tool_driprelease\\driprelease::manage_selections<\/a>"],[0,4,"tool_driprelease\\driprelease::get_modules<\/a>"],[0,1,"tool_driprelease\\event\\driprelease_updated::init<\/a>"],[0,1,"tool_driprelease\\event\\driprelease_updated::get_description<\/a>"],[0,1,"tool_driprelease\\event\\driprelease_viewed::init<\/a>"],[0,1,"tool_driprelease\\event\\driprelease_viewed::get_description<\/a>"],[0,1,"tool_driprelease\\privacy\\provider::get_reason<\/a>"],[0,6,"tool_driprelease_form::definition<\/a>"],[0,7,"tool_driprelease_form::validation<\/a>"],[0,3,"tool_driprelease_form::get_modules<\/a>"],[0,5,"tool_driprelease_form::set_data<\/a>"],[0,5,"tool_driprelease_form::add_action_buttons<\/a>"]], 'Method Complexity')) .transition() .duration(500) .call(chart); diff --git a/tests/coverage-html/driprelease_form.php.html b/tests/coverage-html/driprelease_form.php.html index 76119d8..97664ff 100644 --- a/tests/coverage-html/driprelease_form.php.html +++ b/tests/coverage-html/driprelease_form.php.html @@ -240,7 +240,7 @@ 23 */ 24 25defined('MOODLE_INTERNAL') || die(); - 26 + 26use tool_driprelease\driprelease; 27require_once($CFG->libdir . '/formslib.php'); 28 29/** @@ -279,7 +279,7 @@ 62 63        $mform->setType('courseid', PARAM_INT); 64 - 65        $moduletypes = get_course_module_types($courseid); + 65        $moduletypes = driprelease::get_course_module_types($courseid); 66        $group[] = $mform->createElement('select', 'modtype', get_string('activitytype', 'tool_driprelease'), $moduletypes); 67        $group[] = $mform->createElement('submit', 'refresh', get_string('refresh', 'tool_driprelease')); 68        $string = get_string('activity', 'tool_driprelease'); @@ -504,7 +504,7 @@

Legend

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

- Generated by php-code-coverage 9.2.31 using PHP 8.2.19 and PHPUnit 9.6.18 at Sun Aug 11 8:46:25 AWST 2024. + Generated by php-code-coverage 9.2.31 using PHP 8.2.19 and PHPUnit 9.6.18 at Thu Oct 24 19:13:44 AWST 2024.

diff --git a/tests/coverage-html/index.html b/tests/coverage-html/index.html index a20daef..279e978 100644 --- a/tests/coverage-html/index.html +++ b/tests/coverage-html/index.html @@ -44,21 +44,21 @@ Total
-
- 32.40% covered (danger) +
+ 0.00% covered (danger)
-
32.40%
-
139 / 429
+
0.00%
+
0 / 435
-
- 22.73% covered (danger) +
+ 0.00% covered (danger)
-
22.73%
-
5 / 22
+
0.00%
+
0 / 22
0.00% covered (danger) @@ -66,7 +66,7 @@
0.00%
-
0 / 4
+
0 / 5
@@ -78,7 +78,7 @@
0.00%
-
0 / 7
+
0 / 207
0.00% covered (danger) @@ -86,7 +86,7 @@
0.00%
-
0 / 5
+
0 / 16
0.00% covered (danger) @@ -94,7 +94,7 @@
0.00%
-
0 / 3
+
0 / 4
@@ -126,23 +126,23 @@ -
lib.php -
-
- 68.47% covered (warning) + lib.php +
+
+ 0.00% covered (danger)
-
68.47%
-
139 / 203
+
0.00%
+
0 / 5
-
- 41.67% covered (danger) +
+ 0.00% covered (danger)
-
41.67%
-
5 / 12
+
0.00%
+
0 / 1
n/a
0 / 0
@@ -157,7 +157,7 @@
0.00%
-
0 / 81
+
0 / 85
n/a
0 / 0
@@ -179,7 +179,7 @@

Legend

High: 90% to 100%

- Generated by php-code-coverage 9.2.31 using PHP 8.2.19 and PHPUnit 9.6.18 at Sun Aug 11 8:46:25 AWST 2024. + Generated by php-code-coverage 9.2.31 using PHP 8.2.19 and PHPUnit 9.6.18 at Thu Oct 24 19:13:44 AWST 2024.

diff --git a/tests/coverage-html/lib.php.html b/tests/coverage-html/lib.php.html index 2d18e43..a203534 100644 --- a/tests/coverage-html/lib.php.html +++ b/tests/coverage-html/lib.php.html @@ -42,31 +42,7 @@ - Total -
-
- 68.47% covered (warning) -
-
- -
68.47%
-
139 / 203
-
-
- 41.67% covered (danger) -
-
- -
41.67%
-
5 / 12
- CRAP - -
n/a
-
0 / 0
- - - - tool_driprelease_extend_navigation_course + Total
0.00% covered (danger) @@ -83,144 +59,14 @@
0.00%
0 / 1
- 6 - - - - - driprelease_update -
-
- 100.00% covered (success) -
-
- -
100.00%
-
37 / 37
-
-
- 100.00% covered (success) -
-
- -
100.00%
-
1 / 1
- 2 - - - - - manage_selections -
-
- 86.36% covered (warning) -
-
- -
86.36%
-
19 / 22
-
-
- 0.00% covered (danger) -
-
- -
0.00%
-
0 / 1
- 6.09 - - - - - get_course_module_types -
-
- 100.00% covered (success) -
-
- -
100.00%
-
5 / 5
-
-
- 100.00% covered (success) -
-
- -
100.00%
-
1 / 1
- 2 - - - - - get_modules -
-
- 88.89% covered (warning) -
-
- -
88.89%
-
8 / 9
-
-
- 0.00% covered (danger) -
-
- -
0.00%
-
0 / 1
- 4.02 - - - - - add_header -
-
- 100.00% covered (success) -
-
- -
100.00%
-
5 / 5
-
-
- 100.00% covered (success) -
-
- -
100.00%
-
1 / 1
- 1 - - - - - get_table_data -
-
- 100.00% covered (success) -
-
- -
100.00%
-
19 / 19
-
-
- 100.00% covered (success) -
-
- -
100.00%
-
1 / 1
- 6 - + CRAP + +
n/a
+
0 / 0
- row_fill + tool_driprelease_extend_navigation_course
0.00% covered (danger) @@ -228,7 +74,7 @@
0.00%
-
0 / 12
+
0 / 5
0.00% covered (danger) @@ -241,94 +87,6 @@ - - update_availability -
-
- 66.00% covered (warning) -
-
- -
66.00%
-
33 / 50
-
-
- 0.00% covered (danger) -
-
- -
0.00%
-
0 / 1
- 17.66 - - - - - get_availability -
-
- 100.00% covered (success) -
-
- -
100.00%
-
13 / 13
-
-
- 100.00% covered (success) -
-
- -
100.00%
-
1 / 1
- 7 - - - - - driprelease_calculate_availability -
-
- 0.00% covered (danger) -
-
- -
0.00%
-
0 / 14
-
-
- 0.00% covered (danger) -
-
- -
0.00%
-
0 / 1
- 2 - - - - - get_sequence -
-
- 0.00% covered (danger) -
-
- -
0.00%
-
0 / 12
-
-
- 0.00% covered (danger) -
-
- -
0.00%
-
0 / 1
- 20 - - - @@ -359,7 +117,7 @@ 22 * @license     https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24use core_availability\tree; - 25 + 25use tool_driprelease\lib; 26/** 27 * A core callback to make ther plugin appear in the "more" dropdown of courses 28 * @@ -376,356 +134,6 @@ 39                     'tool_driprelease')); 40    } 41} - 42 - 43/** - 44 * Adds/updates an instance of driprelease and its related - 45 * - 46 * @param \stdClass $fromform - 47 * @param int $courseid - 48 * @return array - 49 */ - 50function driprelease_update(\stdClass $fromform , int $courseid): array { - 51    global $DB; - 52    $dripreleaseid = $DB->get_field('tool_driprelease', 'id', ['courseid' => $courseid]); - 53 - 54    if ($dripreleaseid) { - 55        $driprelease = (object) [ - 56            'id' => $dripreleaseid, - 57            'modtype' => $fromform->modtype, - 58            'courseid' => $courseid, - 59            'activitiespersession' => $fromform->activitiespersession, - 60            'sessionlength' => $fromform->sessiongroup['sessionlength'] ?? $fromform->sessionlength, - 61            'schedulestart' => $fromform->schedulestart, - 62            'schedulefinish' => $fromform->schedulefinish, - 63            'coursegroup' => $fromform->coursegroup, - 64            'stayavailable' => $fromform->stayavailable, - 65            'hideunselected' => $fromform->hideunselected, - 66            'resetunselected' => $fromform->resetunselected, - 67            'displaydisabled' => $fromform->displaydisabled, - 68        ]; - 69        $DB->update_record('tool_driprelease', $driprelease); - 70        manage_selections($fromform, $dripreleaseid); - 71    } else { - 72        $driprelease = (object) [ - 73            'courseid' => $courseid, - 74            'modtype' => $fromform->modtype, - 75            'activitiespersession' => $fromform->activitiespersession, - 76            'sessionlength' => $fromform->sessionlength, - 77            'schedulestart' => $fromform->schedulestart, - 78            'schedulefinish' => $fromform->schedulefinish, - 79            'coursegroup' => $fromform->coursegroup, - 80            'stayavailable' => $fromform->stayavailable, - 81            'hideunselected' => $fromform->hideunselected, - 82            'resetunselected' => $fromform->resetunselected, - 83            'displaydisabled' => $fromform->displaydisabled, - 84        ]; - 85        $dripreleaseid = $DB->insert_record('tool_driprelease', $driprelease); - 86        $driprelease->id = $dripreleaseid; - 87    } - 88    manage_selections($fromform, $dripreleaseid); - 89    $selections = $DB->get_records_menu('tool_driprelease_cmids', ['driprelease' => $dripreleaseid], null, 'id,coursemoduleid'); - 90    return [$selections, $driprelease]; - 91} - 92 - 93/** - 94 * Process the checkbox selections and upsert the database records - 95 * - 96 * @param \stdClass $fromform - 97 * @param int $dripreleaseid - 98 * @return int $insertedcount // For future testing purposes. - 99 */ - 100function manage_selections(\stdClass $fromform, int $dripreleaseid): int { - 101    global $DB; - 102    if (!isset($fromform->activitygroup)) { - 103        return 0; - 104    } - 105    $moduleids = []; - 106    foreach ($fromform->activitygroup as $key => $value) { - 107        if ($value == 1) { - 108            $moduleids[] = explode('_', $key)[1]; - 109        } - 110    } - 111    $selections = $DB->get_records_menu('tool_driprelease_cmids', ['driprelease' => $dripreleaseid], null, 'id,coursemoduleid'); - 112 - 113    $todelete = array_diff($selections, $moduleids); - 114    if ($todelete) { - 115        list($insql, $inparams) = $DB->get_in_or_equal($todelete); - 116        $DB->delete_records_select("tool_driprelease_cmids", "coursemoduleid $insql", $inparams); - 117    } - 118    $toinsert = array_diff($moduleids, $selections); - 119    $insertedcount = 0; - 120    foreach ($toinsert as $moduleid) { - 121        $dataobject = (object) [ - 122            'driprelease' => $dripreleaseid, - 123            'coursemoduleid' => $moduleid, - 124        ]; - 125        $DB->insert_record('tool_driprelease_cmids', $dataobject); - 126        $insertedcount ++; - 127    } - 128    return $insertedcount; - 129} - 130/** - 131 * Get names of modules on course for showing - 132 * in the select element on the form. - 133 * - 134 * @param int $courseid - 135 * @return array - 136 */ - 137function get_course_module_types(int $courseid): array { - 138    $modinfo = get_fast_modinfo($courseid); - 139    $modtypes = []; - 140    foreach ($modinfo->cms as $cm) { - 141        $modtypes[$cm->modname] = get_string('pluginname', $cm->modname); - 142    } - 143    return $modtypes; - 144} - 145 - 146/** - 147 * Get course modules given an instance of driprelease - 148 * - 149 * @param \stdClass $driprelease - 150 * @return array - 151 */ - 152function get_modules(\stdClass $driprelease): array { - 153    global $DB; - 154    $course = $DB->get_record('course', ['id' => $driprelease->courseid]); - 155    $modinfo = get_fast_modinfo($course); - 156    if (!$modinfo->instances || (!array_key_exists($driprelease->modtype, $modinfo->instances))) { - 157        return []; - 158    }; - 159    $modules = []; - 160    foreach ($modinfo->instances[$driprelease->modtype] as $cm) { - 161        $modules[$cm->id] = $cm; - 162    } - 163    return $modules; - 164} - 165/** - 166 * Add another session header row in the display/preview of scheduled modules - 167 * - 168 * @param array $row - 169 * @return array - 170 */ - 171function add_header(array $row): array { - 172    $header = $row; - 173    $header['isheader'] = true; - 174    $header['cm'] = (object) ['id' => -1]; - 175    $header['name'] = 'Session'; - 176    return $header; - 177} - 178/** - 179 * Get the rows to be displayed in the schedule of dripped out modules - 180 * - 181 * @param \stdClass $driprelease - 182 * @return array - 183 */ - 184function get_table_data(\stdClass $driprelease): array { - 185    global $DB; - 186    $modules = get_modules($driprelease); - 187    $contentcounter = 0; - 188    $sessioncounter = 0; - 189    $selections = []; - 190    if (isset($driprelease->id)) { - 191        $selections = $DB->get_records_menu('tool_driprelease_cmids', ['driprelease' => $driprelease->id], - 192            null, 'id,coursemoduleid'); - 193    } - 194    foreach ($modules as $cm) { - 195        $row['selected'] = in_array($cm->id, $selections) ? 'checked' : ""; - 196 - 197        if ($contentcounter % ($driprelease->activitiespersession) == 0) { - 198            if ($row['selected'] > "") { - 199                $row['calculatedavailability'] = driprelease_calculate_availability($driprelease, $sessioncounter); - 200                $sessioncounter++; - 201            } - 202            $data[] = add_header($row); - 203        } - 204        $contentcounter++; - 205        $row['modtype'] = $driprelease->modtype; - 206        $data[] = row_fill($row, $cm); - 207    } - 208    return $data ?? []; - 209} - 210 - 211/** - 212 * Simplify get_table_data - 213 * - 214 * @param array $row - 215 * @param cm_info $cm - 216 * @return array - 217 */ - 218function row_fill(array $row, cm_info $cm): array { - 219    global $DB; - 220 - 221    $details = $DB->get_record($row['modtype'], ['id' => $cm->instance]); - 222    $row['cm'] = $cm; - 223    $row['intro'] = strip_tags($details->intro); - 224    if ($cm->modname == 'quiz') { - 225        $questions = $DB->get_records('quiz_slots', ['quizid' => $cm->instance]); - 226        $row['questioncount'] = count($questions); - 227    } - 228    $row['isheader'] = false; - 229    $row['id'] = $cm->id; - 230    $row['name'] = $cm->name; - 231    $row['moduleavailability'] = get_availability($cm->availability); - 232    return $row; - 233} - 234 - 235/** - 236 * Write the availability back to the course_modules table - 237 * See https://moodledev.io/docs/apis/subsystems/availability/ - 238 * @param array $tabledata - 239 * @param \stdClass $driprelease - 240 * @return void - 241 */ - 242function update_availability(array $tabledata, \stdClass $driprelease) { - 243    global $DB, $COURSE; - 244    $updatecount = 0; - 245 - 246    foreach ($tabledata as $module) { - 247        if (!$module['isheader']) { - 248            if (!$module['selected'] == "checked") { - 249                $cm = $module['cm']; - 250                if ($driprelease->hideunselected) { - 251                    set_coursemodule_visible($cm->id, false, false); - 252                    \core\event\course_module_updated::create_from_cm($cm)->trigger(); - 253                } else { - 254                    set_coursemodule_visible($cm->id, true, true); - 255                } - 256                if ($driprelease->resetunselected) { - 257                    $DB->set_field( - 258                        'course_modules', - 259                        'availability', - 260                        '', - 261                        ['id' => $module['cm']->id] - 262                    ); - 263                } - 264                continue; - 265            } - 266            if (!array_key_exists('calculatedavailability', $module)) { - 267                continue; - 268            } - 269            // Don't write any availability restrictions after the end of the schedule. - 270            if ($module['calculatedavailability']['start'] > $driprelease->schedulefinish) { - 271                    continue; - 272            } - 273            $cm = $module['cm']; - 274            set_coursemodule_visible($cm->id, true, true); - 275            \core\event\course_module_updated::create_from_cm($cm)->trigger(); - 276 - 277            $availability = $module['calculatedavailability']; - 278            $restrictions = []; - 279            if ($driprelease->coursegroup) { - 280                $restrictions[] = \availability_group\condition::get_json($driprelease->coursegroup); - 281            } - 282            $restrictions[] = \availability_date\condition::get_json(">=", $availability['start']); - 283            if (!$driprelease->stayavailable) { - 284                $restrictions[] = \availability_date\condition::get_json("<", $availability['end']); - 285            } - 286            $showvalue = false; - 287            if ($driprelease->displaydisabled) { - 288                $showvalue = true; - 289            } - 290 - 291            $showc = array_fill(0, count($restrictions), $showvalue); - 292            $restrictionsclass = tree::get_root_json($restrictions, tree::OP_AND, $showc); - 293 - 294            $DB->set_field( - 295                'course_modules', - 296                'availability', - 297                json_encode($restrictionsclass), - 298                ['id' => $module['cm']->id] - 299            ); - 300            $updatecount++; - 301        } - 302    } - 303    $modulenameplural = get_string('modulenameplural', $driprelease->modtype); - 304    $msg = get_string('updated', 'moodle', $updatecount). " ".$modulenameplural; - 305    $refresh = optional_param('refresh', 0, PARAM_RAW); - 306    if (! $refresh) { - 307        \core\notification::add($msg, \core\notification::SUCCESS); - 308        rebuild_course_cache($COURSE->id); - 309    } - 310} - 311 - 312 - 313/** - 314 * Get the date related availability for an activity - 315 * - 316 * @param string $json - 317 * @return array - 318 */ - 319function get_availability(?string $json): array { - 320    global $USER; - 321    $availability = []; - 322 - 323    if ($json > "" && $json <> '{}') { - 324        $decoded = json_decode($json); - 325        foreach ($decoded->c as $restriction) { - 326            if (property_exists($restriction, 'type') && $restriction->type == "date") { - 327                $operator = $restriction->d; - 328                if ($operator == ">=") { - 329                    $datetime = $restriction->t; - 330                    $availability['from'] = userdate($datetime, '%a %d %b %Y %H:%M'); - 331                } else { - 332                    $datetime = $restriction->t; - 333                    $availability['to'] = userdate($datetime, '%a %d %b %Y %H:%M'); - 334                } - 335            } - 336        } - 337    } - 338    return $availability; - 339} - 340 - 341  /** - 342   * Calculate the dripping out of availability and format the dates for the session labels - 343   * - 344   * @param \stdClass $driprelease - 345   * @param int $sessioncounter - 346   * @return array - 347   */ - 348function driprelease_calculate_availability(\stdClass $driprelease, int $sessioncounter): array { - 349    $row = []; - 350    $daysrepeat = $sessioncounter * $driprelease->sessionlength; - 351    $daysoffset = " + $daysrepeat day"; - 352    $start = strtotime(' + ' . $daysrepeat . ' day', $driprelease->schedulestart); - 353    $daysoffset = " + " . (($daysrepeat - 1) + $driprelease->sessionlength) . " day "; - 354    $end = strtotime($daysoffset, $driprelease->schedulestart); - 355 - 356    $midnight = strtotime('today midnight', $driprelease->schedulefinish); - 357    $endminutes = $driprelease->schedulefinish - $midnight; - 358    $end = strtotime('today midnight', $end ); - 359    $end += $endminutes; - 360 - 361    $row['sessioncounter'] = $sessioncounter + 1; - 362    $row['start'] = $start; - 363    $row['end'] = $end; - 364    return $row; - 365} - 366 - 367/** - 368 * This is designed to return the coursemods in the order they are displayed on the course - 369 * It is currently not used and may be deleted at some point, or the need for it may be obscured - 370 * by the way test data means course activities are always in the order they were created. - 371 * - 372 * @param \stdClass $data - 373 * @return array - 374 */ - 375function get_sequence(\stdClass $data): array { - 376    global $DB; - 377    $sql = 'SELECT sequence FROM {course_sections} WHERE course = :course AND sequence > "" ORDER BY section'; - 378    $coursesequence = $DB->get_records_sql($sql, ['course' => $data->course]); - 379    $activitiesordered = []; - 380    $i = 0; - 381    foreach ($coursesequence as $item) { - 382        $temp = explode(',', $item->sequence); - 383        foreach ($temp as $t) { - 384            if (array_key_exists($t, $data->activities)) { - 385                $activitiesordered[$i] = $t; - 386                $i++; - 387            } - 388        } - 389    } - 390    return $activitiesordered; - 391} @@ -736,7 +144,7 @@

Legend

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

- Generated by php-code-coverage 9.2.31 using PHP 8.2.19 and PHPUnit 9.6.18 at Sun Aug 11 8:46:25 AWST 2024. + Generated by php-code-coverage 9.2.31 using PHP 8.2.19 and PHPUnit 9.6.18 at Thu Oct 24 19:13:44 AWST 2024.

diff --git a/tests/coverage-html/view.php.html b/tests/coverage-html/view.php.html index 509e73a..06bf2b3 100644 --- a/tests/coverage-html/view.php.html +++ b/tests/coverage-html/view.php.html @@ -50,7 +50,7 @@
0.00%
-
0 / 81
+
0 / 85
n/a
0 / 0
@@ -95,124 +95,129 @@
27 28use tool_driprelease\event\driprelease_updated; 29use tool_driprelease\event\driprelease_viewed; - 30 - 31// Course module id. - 32$courseid = optional_param('courseid', 0, PARAM_INT); - 33$modtype = optional_param('modtype', 'quiz', PARAM_RAW); - 34 - 35if (!$courseid) { - 36    redirect(new moodle_url('/')); - 37} - 38$context = context_course::instance($courseid); - 39 - 40if (!has_capability('moodle/course:update', $context)) { - 41    redirect(new moodle_url('/course/view.php', ['id' => $courseid])); - 42} - 43$cancel = optional_param('cancel', null, PARAM_TEXT); - 44if (isset($cancel)) { - 45    redirect (new moodle_url('/course/view.php', ['id' => $courseid])); - 46} - 47require_login($courseid); - 48 - 49require_once($CFG->dirroot . '/admin/tool/driprelease/driprelease_form.php'); + 30use tool_driprelease\driprelease; + 31$driprelease = new driprelease(); + 32 + 33// Course module id. + 34$courseid = optional_param('courseid', 0, PARAM_INT); + 35$modtype = optional_param('modtype', 'quiz', PARAM_RAW); + 36 + 37if (!$courseid) { + 38    redirect(new moodle_url('/')); + 39} + 40$context = context_course::instance($courseid); + 41 + 42if (!has_capability('moodle/course:update', $context)) { + 43    redirect(new moodle_url('/course/view.php', ['id' => $courseid])); + 44} + 45$cancel = optional_param('cancel', null, PARAM_TEXT); + 46if (isset($cancel)) { + 47    redirect (new moodle_url('/course/view.php', ['id' => $courseid])); + 48} + 49require_login($courseid); 50 - 51$PAGE->set_context($context); + 51require_once($CFG->dirroot . '/admin/tool/driprelease/driprelease_form.php'); 52 - 53$PAGE->set_url('/admin/tool/driprelease/view.php', ['courseid' => $courseid]); + 53$PAGE->set_context($context); 54 - 55if (!$course = $DB->get_record('course', ['id' => $courseid])) { - 56    throw new moodle_exception('invalid course id'); - 57} - 58 - 59$PAGE->set_course($course); - 60global $DB, $USER; - 61 - 62$driprelease = $DB->get_record('tool_driprelease' , ['courseid' => $courseid], '*', IGNORE_MISSING); - 63if (!$driprelease) { - 64    $config = get_config('tool_driprelease'); - 65    $driprelease = (object)[ - 66        'courseid' => $courseid, - 67        'modtype' => $modtype, - 68        'activitiespersession' => $config->activitiespersession ?? 0, - 69        'schedulestart' => time(), - 70        'coursegroup' => '', - 71        'sessionlength' => $config->sessionlength ?? 0, - 72    ]; - 73} else { - 74    $driprelease->modtype = $modtype; - 75} - 76 - 77if (!$driprelease) { - 78    $driprelease = (object) ['courseid' => $courseid]; - 79} - 80 - 81$mform = new tool_driprelease_form(null, ['driprelease' => $driprelease]); - 82 - 83navigation_node::override_active_url(new moodle_url('admin/tool/driprelease/view.php', ['courseid' => $courseid])); - 84$eventdata = [ - 85    'context' => context_course::instance($courseid), - 86    'other' => [ - 87        'username' => $USER->username, - 88        'course' => $course->shortname, - 89    ], - 90]; - 91 - 92if ($fromform = $mform->get_data()) { - 93 - 94    if (isset($fromform->submitbutton) || isset($fromform->submitbutton2) || isset($fromform->refresh)) { - 95        $driprelease->schedulestart = $fromform->schedulestart; - 96        $driprelease->stayavailable = $fromform->stayavailable; - 97        $driprelease->hideunselected = $fromform->hideunselected; - 98        $driprelease->coursegroup = $fromform->coursegroup; - 99        xdebug_break(); - 100        $driprelease->moduletype = $fromform->modtype; - 101        $driprelease->refresh = true; - 102        list($selections, $driprelease) = driprelease_update($fromform, $courseid); - 103        if (count($selections) == 0 && !isset($fromform->refresh)) { - 104            $msg = get_string('noselections', 'tool_driprelease'); - 105            \core\notification::add($msg, \core\notification::WARNING); - 106        } - 107 - 108        $tabledata = get_table_data($driprelease); - 109        update_availability($tabledata, $driprelease); - 110 - 111        $event = driprelease_updated::create($eventdata); - 112        $event->trigger(); - 113    } - 114    if (isset($fromform->submitbutton2)) { - 115        redirect (new moodle_url('/course/view.php', ['id' => $courseid])); - 116    } - 117} - 118 - 119$tabledata = get_table_data($driprelease); - 120 - 121$templates = []; - 122$iterator = new DirectoryIterator(__DIR__ . '/templates'); - 123foreach ($iterator as $item) { - 124    if ($item->isDot()) { - 125        continue; - 126    } - 127    $templates[] = strtok($item->getFilename(), "."); - 128} - 129 - 130$templatefile = $modtype; - 131if (!in_array($modtype, $templates)) { - 132    $templatefile = 'genericmod'; + 55$PAGE->set_url('/admin/tool/driprelease/view.php', ['courseid' => $courseid]); + 56 + 57if (!$course = $DB->get_record('course', ['id' => $courseid])) { + 58    throw new moodle_exception('invalid course id'); + 59} + 60 + 61$PAGE->set_course($course); + 62global $DB, $USER; + 63 + 64$dripdata = $DB->get_record('tool_driprelease' , ['courseid' => $courseid], '*', IGNORE_MISSING); + 65if (!$dripdata) { + 66    $config = get_config('tool_driprelease'); + 67    $dripdata = (object)[ + 68        'courseid' => $courseid, + 69        'modtype' => $modtype, + 70        'activitiespersession' => $config->activitiespersession ?? 0, + 71        'schedulestart' => time(), + 72        'coursegroup' => '', + 73        'sessionlength' => $config->sessionlength ?? 0, + 74        'mydtype' => '', + 75    ]; + 76} else { + 77    $dripdata->modtype = $modtype; + 78} + 79 + 80if (!$dripdata) { + 81    $dripdata = (object) [ + 82        'courseid' => $courseid, + 83        'modtype' => '', + 84    ]; + 85} + 86 + 87$mform = new tool_driprelease_form(null, ['driprelease' => $dripdata]); + 88 + 89navigation_node::override_active_url(new moodle_url('admin/tool/driprelease/view.php', ['courseid' => $courseid])); + 90$eventdata = [ + 91    'context' => context_course::instance($courseid), + 92    'other' => [ + 93        'username' => $USER->username, + 94        'course' => $course->shortname, + 95    ], + 96]; + 97 + 98if ($fromform = $mform->get_data()) { + 99 + 100    if (isset($fromform->submitbutton) || isset($fromform->submitbutton2) || isset($fromform->refresh)) { + 101        $dripdata->schedulestart = $fromform->schedulestart; + 102        $dripdata->stayavailable = $fromform->stayavailable; + 103        $dripdata->hideunselected = $fromform->hideunselected; + 104        $dripdata->coursegroup = $fromform->coursegroup; + 105        $dripdata->moduletype = $fromform->modtype; + 106        $dripdata->refresh = true; + 107        list($selections, $dripdata) = $driprelease->update($fromform, $courseid); + 108        if (count($selections) == 0 && !isset($fromform->refresh)) { + 109            $msg = get_string('noselections', 'tool_driprelease'); + 110            \core\notification::add($msg, \core\notification::WARNING); + 111        } + 112 + 113        $tabledata = $driprelease->get_table_data($dripdata); + 114        $driprelease->update_availability($tabledata, $dripdata); + 115 + 116        $event = driprelease_updated::create($eventdata); + 117        $event->trigger(); + 118    } + 119    if (isset($fromform->submitbutton2)) { + 120        redirect (new moodle_url('/course/view.php', ['id' => $courseid])); + 121    } + 122} + 123 + 124$tabledata = $driprelease->get_table_data($dripdata); + 125 + 126$templates = []; + 127$iterator = new DirectoryIterator(__DIR__ . '/templates'); + 128foreach ($iterator as $item) { + 129    if ($item->isDot()) { + 130        continue; + 131    } + 132    $templates[] = strtok($item->getFilename(), "."); 133} 134 - 135$out = $OUTPUT->render_from_template('tool_driprelease/'.$templatefile, - 136     ['tabledata' => $tabledata, 'modtype' => get_string("pluginname", $modtype)]); - 137 - 138$mform->set_data($driprelease); + 135$templatefile = $modtype; + 136if (!in_array($modtype, $templates)) { + 137    $templatefile = 'genericmod'; + 138} 139 - 140$event = driprelease_viewed::create($eventdata); - 141$event->trigger(); + 140$out = $OUTPUT->render_from_template('tool_driprelease/'.$templatefile, + 141     ['tabledata' => $tabledata, 'modtype' => get_string("pluginname", $modtype)]); 142 - 143echo $OUTPUT->header(); - 144$mform->display(); - 145echo $out; - 146echo $OUTPUT->footer(); + 143$mform->set_data($dripdata); + 144 + 145$event = driprelease_viewed::create($eventdata); + 146$event->trigger(); 147 + 148echo $OUTPUT->header(); + 149$mform->display(); + 150echo $out; + 151echo $OUTPUT->footer(); + 152 @@ -223,7 +228,7 @@

Legend

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

- Generated by php-code-coverage 9.2.31 using PHP 8.2.19 and PHPUnit 9.6.18 at Sun Aug 11 8:46:25 AWST 2024. + Generated by php-code-coverage 9.2.31 using PHP 8.2.19 and PHPUnit 9.6.18 at Thu Oct 24 19:13:44 AWST 2024.

diff --git a/tests/driprelease_test.php b/tests/driprelease_test.php index 522427b..f1f122b 100644 --- a/tests/driprelease_test.php +++ b/tests/driprelease_test.php @@ -32,15 +32,25 @@ global $CFG; require_once($CFG->dirroot . '/mod/quiz/locallib.php'); -/** + +/*** * Unit test for the driprelease functionality. * * @package tool_driprelease * @category test - * @copyright 2023 Marcus Green + * @copyright 2024 Marcus Green * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +use tool_driprelease; +/** + * Test the code mainly in the tool_driprelease class + */ final class driprelease_test extends \advanced_testcase { + /** + * Instance containing most of the code + * @var driprelease + */ + public $driprelease; /** * Test course @@ -57,11 +67,10 @@ final class driprelease_test extends \advanced_testcase { public $modules; /** - * instance of driprelease - * + * data to be processed * @var \stdClass */ - public $driprelease; + public $dripdata; /** * data from form submission @@ -72,6 +81,7 @@ final class driprelease_test extends \advanced_testcase { public function setUp(): void { global $CFG, $DB; + $this->driprelease = new driprelease(); // Create course with availability enabled. $CFG->enableavailability = true; $generator = $this->getDataGenerator(); @@ -80,17 +90,17 @@ public function setUp(): void { $quizgenerator = $generator->get_plugin_generator('mod_quiz'); - $this->modules[] = $quizgenerator->create_instance(array('course' => $course->id, + $this->modules[] = $quizgenerator->create_instance(['course' => $course->id, 'grademethod' => QUIZ_GRADEHIGHEST, 'grade' => 100.0, 'sumgrades' => 10.0, - 'attempts' => 10)); + 'attempts' => 10]); - $this->modules[] = $quizgenerator->create_instance(array('course' => $course->id, + $this->modules[] = $quizgenerator->create_instance(['course' => $course->id, 'grademethod' => QUIZ_GRADEHIGHEST, 'grade' => 100.0, 'sumgrades' => 10.0, - 'attempts' => 10)); + 'attempts' => 10]); - $this->modules[] = $quizgenerator->create_instance(array('course' => $course->id, + $this->modules[] = $quizgenerator->create_instance(['course' => $course->id, 'grademethod' => QUIZ_GRADEHIGHEST, 'grade' => 100.0, 'sumgrades' => 10.0, - 'attempts' => 10)); + 'attempts' => 10]); foreach ($this->modules as $module) { $activitygroup['activity_'.$module->cmid] = 1; @@ -110,15 +120,15 @@ public function setUp(): void { 'displaydisabled' => 0, ]; - list($selections, $driprelease) = driprelease_update($this->fromform , $this->course1->id); + list($selections, $this->dripdata) = $this->driprelease->update($this->fromform , $this->course1->id); $this->assertCount(3, $selections); - $this->driprelease = $DB->get_record('tool_driprelease', ['id' => $driprelease->id]); + $this->dripdata = $DB->get_record('tool_driprelease', ['id' => $this->dripdata->id]); } /** * Confirm course_modules table has been * written to * - * @covers ::update_availability() + * @covers \tool_driprelease\driprelease::update_availability() */ public function test_update_availability(): void { $this->resetAfterTest(); @@ -126,13 +136,14 @@ public function test_update_availability(): void { $coursemodules = $DB->get_records('course_modules'); $cm = reset($coursemodules); $this->assertEquals($cm->availability, ''); - $tabledata = get_table_data($this->driprelease); + $tabledata = $this->driprelease->get_table_data($this->dripdata); // Element 0 is a header row. $tabledata[1]['selected'] = 1; - update_availability($tabledata, $this->driprelease); + + $this->driprelease->update_availability($tabledata, $this->dripdata); $coursemodules = $DB->get_records('course_modules'); $cm = reset($coursemodules); - $startdate = $this->driprelease->schedulestart; + $startdate = $this->dripdata->schedulestart; // Sessions set to one day in setUp. $this->assertStringContainsString($startdate, $cm->availability); @@ -140,15 +151,41 @@ public function test_update_availability(): void { } /** - * Confirm modules/quizzes in a course are returned - * as expected + * If reset unselected is checked then the availability data + * for the module will be blanked out * + * @covers \tool_driprelease\driprelease::process_unselected * - * @covers ::get_modules() + * @return void + */ + public function test_process_unselected(): void { + $this->resetAfterTest(); + global $DB; + $modules = $this->driprelease->get_table_data($this->dripdata); + $module = $modules[1]; // A non header. + $DB->set_field( + 'course_modules', + 'availability', + 'XXX', + ['id' => $module['cm']->id] + ); + $before = $DB->get_record('course_modules', ['id' => $module['cm']->id]); + $this->assertEquals($before->availability, 'XXX'); + $this->dripdata->resetunselected = 1; + $this->driprelease->process_unselected($module, $this->dripdata); + $after = $DB->get_record('course_modules', ['id' => $module['cm']->id]); + $this->assertEquals($after->availability, ''); + + } + + /** + * Confirm modules/quizzes in a course are returned + * as expected + * @covers \tool_driprelease\driprelease::get_modules */ public function test_get_course_modules(): void { $this->resetAfterTest(); - $modules = get_modules($this->driprelease); + $modules = $this->driprelease->get_modules($this->dripdata); $modulecount = count($modules); $this->assertEquals(count($this->modules), $modulecount); } @@ -158,21 +195,21 @@ public function test_get_course_modules(): void { * as expected * * - * @covers ::get_course_module_types() + * @covers \tool_driprelease\driprelease::get_course_module_types() */ public function test_get_course_module_types(): void { $this->resetAfterTest(); - $moduletypes = get_course_module_types($this->course1->id); + $moduletypes = $this->driprelease->get_course_module_types($this->course1->id); $this->assertArrayHasKey('quiz', $moduletypes); } /** * Get the data that will be output by the mustache table * - * @covers ::get_table_data() + * @covers \tool_driprelease\driprelease::get_table_data() */ public function test_get_table_data(): void { $this->resetAfterTest(); - $tabledata = get_table_data($this->driprelease); + $tabledata = $this->driprelease->get_table_data($this->dripdata); // First row is header row. $header = $tabledata[0]; $this->assertEquals($header['isheader'], true); @@ -196,7 +233,7 @@ public function test_get_table_data(): void { * Check that update doesn't fall over and * selections are set as expected * - * @covers ::driprelease_update() + * @covers \tool_driprelease\driprelease::update() */ public function test_update_instance(): void { $this->resetAfterTest(); @@ -206,9 +243,9 @@ public function test_update_instance(): void { $activitygroup['activity_'.$module->id] = 1; } $this->fromform->activitygroup = $activitygroup; - list($selections, $driprelease) = driprelease_update($this->fromform , $this->course1->id); + list($selections, $this->dripdata) = $this->driprelease->update($this->fromform , $this->course1->id); $this->assertCount(3, $selections); - $this->assertEquals($driprelease->id, $this->driprelease->id); + $this->assertEquals($this->dripdata->id, $this->dripdata->id); } /** @@ -216,7 +253,7 @@ public function test_update_instance(): void { * when when they have been selected in * the form. * - * @covers ::manage_selections() + * @covers \tool_driprelease\driprelease::manage_selections() */ public function test_manage_selections(): void { $this->resetAfterTest(); @@ -225,7 +262,7 @@ public function test_manage_selections(): void { // Three records created by setUp. $this->assertCount(3, $cmids); $this->fromform->activitygroup['activity_101'] = 1; - manage_selections($this->fromform, $this->driprelease->id); + $this->driprelease->manage_selections($this->fromform, $this->dripdata->id); $cmids = $DB->get_records('tool_driprelease_cmids'); // Four after manage_selections was called. $this->assertCount(4, $cmids); @@ -237,11 +274,11 @@ public function test_manage_selections(): void { * and end of a activity session, * e.g. a weeks worth of quizzes. * - * @covers ::add_header() + * @covers \tool_driprelease\driprelease::add_header() */ public function test_add_header(): void { $this->resetAfterTest(); - $header = add_header([]); + $header = $this->driprelease->add_header([]); $this->assertEquals(true, $header['isheader']); $this->assertEquals('Session', $header['name']); $this->assertEquals(-1, $header['cm']->id); @@ -251,17 +288,17 @@ public function test_add_header(): void { * Check get_modules returns items * configured in setUp function * - * @covers ::get_modules() + * @covers \tool_driprelease\driprelease::get_modules() */ public function test_get_modules(): void { $this->resetAfterTest(); - $cmids = get_modules($this->driprelease); + $cmids = $this->driprelease->get_modules($this->dripdata); $this->assertCount(3, $cmids); } /** * Test get_availability with date restrictions - * @covers ::get_availability() + * @covers \tool_driprelease\driprelease::get_availability() */ public function test_get_availability_with_dates(): void { $this->resetAfterTest(); @@ -278,7 +315,7 @@ public function test_get_availability_with_dates(): void { 'to' => 'Mon 1 Feb 2021 00:00', ]; - $availability = get_availability($json); + $availability = $this->driprelease->get_availability($json); // Assert the output. $this->assertSame($expectedoutput, $availability); @@ -286,13 +323,13 @@ public function test_get_availability_with_dates(): void { /** * Test get_availability with no date restrictions - * @covers ::get_availability() + * @covers \tool_driprelease\driprelease::get_availability() */ public function test_get_availability_with_no_dates(): void { $this->resetAfterTest(); $json = ""; - $availability = get_availability($json); + $availability = $this->driprelease->get_availability($json); // Assert the output. $this->assertSame([], $availability); @@ -300,12 +337,12 @@ public function test_get_availability_with_no_dates(): void { /** * Test get_availability with null json - * @covers ::get_availability() + * @covers \tool_driprelease\driprelease::get_availability() */ public function test_get_availability_with_null(): void { $this->resetAfterTest(); - $availability = get_availability(null); + $availability = $this->driprelease->get_availability(null); // Assert the output. $this->assertSame([], $availability); diff --git a/view.php b/view.php index fb760cd..6c68b17 100644 --- a/view.php +++ b/view.php @@ -27,6 +27,8 @@ use tool_driprelease\event\driprelease_updated; use tool_driprelease\event\driprelease_viewed; +use tool_driprelease\driprelease; +$driprelease = new driprelease(); // Course module id. $courseid = optional_param('courseid', 0, PARAM_INT); @@ -59,26 +61,30 @@ $PAGE->set_course($course); global $DB, $USER; -$driprelease = $DB->get_record('tool_driprelease' , ['courseid' => $courseid], '*', IGNORE_MISSING); -if (!$driprelease) { +$dripdata = $DB->get_record('tool_driprelease' , ['courseid' => $courseid], '*', IGNORE_MISSING); +if (!$dripdata) { $config = get_config('tool_driprelease'); - $driprelease = (object)[ + $dripdata = (object)[ 'courseid' => $courseid, 'modtype' => $modtype, 'activitiespersession' => $config->activitiespersession ?? 0, 'schedulestart' => time(), 'coursegroup' => '', 'sessionlength' => $config->sessionlength ?? 0, + 'mydtype' => '', ]; } else { - $driprelease->modtype = $modtype; + $dripdata->modtype = $modtype; } -if (!$driprelease) { - $driprelease = (object) ['courseid' => $courseid]; +if (!$dripdata) { + $dripdata = (object) [ + 'courseid' => $courseid, + 'modtype' => '', + ]; } -$mform = new tool_driprelease_form(null, ['driprelease' => $driprelease]); +$mform = new tool_driprelease_form(null, ['driprelease' => $dripdata]); navigation_node::override_active_url(new moodle_url('admin/tool/driprelease/view.php', ['courseid' => $courseid])); $eventdata = [ @@ -92,20 +98,20 @@ if ($fromform = $mform->get_data()) { if (isset($fromform->submitbutton) || isset($fromform->submitbutton2) || isset($fromform->refresh)) { - $driprelease->schedulestart = $fromform->schedulestart; - $driprelease->stayavailable = $fromform->stayavailable; - $driprelease->hideunselected = $fromform->hideunselected; - $driprelease->coursegroup = $fromform->coursegroup; - $driprelease->moduletype = $fromform->modtype; - $driprelease->refresh = true; - list($selections, $driprelease) = driprelease_update($fromform, $courseid); + $dripdata->schedulestart = $fromform->schedulestart; + $dripdata->stayavailable = $fromform->stayavailable; + $dripdata->hideunselected = $fromform->hideunselected; + $dripdata->coursegroup = $fromform->coursegroup; + $dripdata->moduletype = $fromform->modtype; + $dripdata->refresh = true; + list($selections, $dripdata) = $driprelease->update($fromform, $courseid); if (count($selections) == 0 && !isset($fromform->refresh)) { $msg = get_string('noselections', 'tool_driprelease'); \core\notification::add($msg, \core\notification::WARNING); } - $tabledata = get_table_data($driprelease); - update_availability($tabledata, $driprelease); + $tabledata = $driprelease->get_table_data($dripdata); + $driprelease->update_availability($tabledata, $dripdata); $event = driprelease_updated::create($eventdata); $event->trigger(); @@ -115,7 +121,7 @@ } } -$tabledata = get_table_data($driprelease); +$tabledata = $driprelease->get_table_data($dripdata); $templates = []; $iterator = new DirectoryIterator(__DIR__ . '/templates'); @@ -134,7 +140,7 @@ $out = $OUTPUT->render_from_template('tool_driprelease/'.$templatefile, ['tabledata' => $tabledata, 'modtype' => get_string("pluginname", $modtype)]); -$mform->set_data($driprelease); +$mform->set_data($dripdata); $event = driprelease_viewed::create($eventdata); $event->trigger();