From c93f4a230d232dfe216f4b86e9693e34144bfafc Mon Sep 17 00:00:00 2001 From: vasanthlmsace Date: Wed, 27 Nov 2024 18:51:11 +0530 Subject: [PATCH] Bug fixes - DES-903. --- classes/cache/loader.php | 129 ++++++++++++++ classes/events.php | 214 ++++++++++++++++++++++- classes/helper.php | 16 +- classes/options.php | 40 +++-- classes/output/renderer.php | 334 +++++++++++++++++++----------------- db/caches.php | 34 ++++ db/events.php | 40 +++++ lib.php | 31 ++-- version.php | 2 +- 9 files changed, 639 insertions(+), 201 deletions(-) create mode 100644 classes/cache/loader.php create mode 100644 db/caches.php diff --git a/classes/cache/loader.php b/classes/cache/loader.php new file mode 100644 index 0000000..35217a3 --- /dev/null +++ b/classes/cache/loader.php @@ -0,0 +1,129 @@ +. + +/** + * Format Designer - Custom cache loader for the smart menus. + * + * @package format_designer + * @copyright 2023 bdecent GmbH + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace format_designer\cache; + +defined('MOODLE_INTERNAL') || die(); + +require_once($CFG->dirroot.'/cache/classes/loaders.php'); + +/** + * Custom cache loader to handle the smart menus and items deletion. + */ +class loader extends \cache_application { + + /** + * Delete the cached menus or menu items for all of its users. + * @param mixed $courseid + * @return void + */ + public function delete_vaild_section_completed_cache($courseid) { + $store = $this->get_store(); + $prefix = "v_s_c_c_{$courseid}"; + if ($list = $store->find_by_prefix($prefix)) { + $keys = array_map(function($key) { + $key = current(explode('-', $key)); + return $key; + }, $list); + $this->delete_many($keys); + } + } + + /** + * Delete user section completed cache. + * @param mixed $courseid + * @return void + */ + public function delete_user_section_completed_cache($courseid) { + $prefix = "s_c_c_{$courseid}"; + $this->delete_prefix_cache($prefix); + } + + /** + * Delete due overdue activities count. + * @param mixed $courseid + * @param mixed $userid + * @return void + */ + public function delete_due_overdue_activities_count($courseid, $userid = 0) { + $prefix = "d_o_a_c_c{$courseid}"; + if ($userid) { + $prefix .= "_u{$userid}"; + } + $this->delete_prefix_cache($prefix); + } + + /** + * Deleted course uncompletion criteria. + * @param mixed $courseid + * @param mixed $userid + * @return void + */ + public function delete_course_progress_uncompletion_criteria($courseid, $userid = 0) { + $prefix = "u_c_c_s{$courseid}"; + if ($userid) { + $prefix .= "_u{$userid}"; + } + $this->delete_prefix_cache($prefix); + } + + /** + * Deleted criteria progress, + * @param mixed $courseid + * @param mixed $userid + * @return void + */ + public function delete_criteria_progress($courseid, $userid = 0) { + $prefix = "c_p_c{$courseid}"; + if ($userid) { + $prefix .= "_u_{$userid}"; + } + $this->delete_prefix_cache($prefix); + } + + /** + * Delete prerequisites courses. + * @return void + */ + public function delete_prerequisites_courses() { + $prefix = "data_prereq_main_c"; + $this->delete_prefix_cache($prefix); + } + + /** + * Delete the prefix cache. + * @param mixed $prefix + * @return void + */ + public function delete_prefix_cache($prefix) { + $store = $this->get_store(); + if ($list = $store->find_by_prefix($prefix)) { + $keys = array_map(function($key) { + $key = current(explode('-', $key)); + return $key; + }, $list); + $this->delete_many($keys); + } + } +} diff --git a/classes/events.php b/classes/events.php index 409fcf2..1b6c8a2 100644 --- a/classes/events.php +++ b/classes/events.php @@ -24,6 +24,10 @@ namespace format_designer; +defined('MOODLE_INTERNAL') || die(); + +require_once($CFG->dirroot . "/course/format/designer/lib.php"); + /** * Designer format event observer. */ @@ -42,7 +46,7 @@ public static function course_section_created($event) { $sectionid = $data['objectid']; $sectionnum = $data['other']['sectionnum']; $contextid = $data['contextid']; - $courseid = $data['courseid'];; + $courseid = $data['courseid']; $filearea = 'sectiondesignbackground'; $option = get_config('format_designer', 'sectiondesignerbackgroundimage'); $coursecontext = \context_course::instance($courseid); @@ -50,6 +54,9 @@ public static function course_section_created($event) { return true; } + // Course_section_cache_updated. + self::course_section_cache_updated($courseid, $sectionid); + $format = course_get_format($courseid); $options = $format->section_format_options(); $sectiondata = ['id' => $sectionid]; @@ -64,6 +71,92 @@ public static function course_section_created($event) { } } + + /** + * After course deleted, deleted the format_designer_options data related to the format_designer options. + * + * @param object $event + * @return void + */ + public static function course_deleted($event) { + global $DB; + $courseid = $event->courseid; + $DB->delete_records('format_designer_options', ['courseid' => $courseid]); + $cache = format_designer_get_cache_object(); + $cache->delete_prerequisites_courses(); + self::course_cache_updated($courseid); + } + + /** + * Event handle course completion update. + * @param mixed $event + * @return bool + */ + public static function course_completion_updated($event) { + $data = $event->get_data(); + $courseid = $data['courseid']; + if (course_get_format($courseid)->get_course()->format !== 'designer') { + return true; + } + self::course_cache_updated($courseid); + } + + /** + * Event handle course update. + * @param mixed $event + * @return bool + */ + public static function course_updated($event) { + $courseid = $event->courseid; + if (course_get_format($courseid)->get_course()->format !== 'designer') { + return true; + } + self::course_cache_updated($courseid); + } + + /** + * Event handle course complete. + * @param mixed $event + * @return bool + */ + public static function course_completed($event) { + global $DB; + $userid = $event->relateduserid; + $courseid = $event->courseid; + if (course_get_format($courseid)->get_course()->format !== 'designer') { + return true; + } + self::course_user_cache_updated($courseid, $userid); + // Related the course data cache deleted. + $records = $DB->get_records('course_completion_criteria', ['courseinstance' => $courseid]); + foreach ($records as $record) { + self::course_user_cache_updated($record->course, $userid); + } + } + + /** + * Event course completion updated. + * @param mixed $event + * @return bool + */ + public static function course_module_completion_updated($event) { + $userid = $event->relateduserid; + $courseid = $event->courseid; + if (course_get_format($courseid)->get_course()->format !== 'designer') { + return true; + } + self::course_user_cache_updated($courseid, $userid); + } + + /** + * Event Course module created + * @param mixed $event + * @return void + */ + public static function course_module_created($event) { + self::course_section_module_cache_updated($event->courseid, $event->objectid); + } + /** * After course module deleted, deleted the format_designer_options data related to the format_designer options. * @@ -73,19 +166,126 @@ public static function course_section_created($event) { public static function course_module_deleted($event) { global $DB; $courseid = $event->courseid; + if (course_get_format($courseid)->get_course()->format !== 'designer') { + return true; + } $cmid = $event->objectid; $DB->delete_records('format_designer_options', ['courseid' => $courseid, 'cmid' => $cmid]); + + // Clear cache. + self::course_section_module_cache_updated($event->courseid, $event->objectid); } /** - * After course deleted, deleted the format_designer_options data related to the format_designer options. - * - * @param object $event + * Event course module update. + * @param mixed $event * @return void */ - public static function course_deleted($event) { + public static function course_module_updated($event) { + self::course_section_module_cache_updated($event->courseid, $event->objectid); + } + + /** + * Event course section deleted. + * @param mixed $event + * @return void + */ + public static function course_section_deleted($event) { + $data = $event->get_data(); + $sectionid = $data['objectid']; + $courseid = $data['courseid']; + self::course_section_cache_updated($courseid, $sectionid); + } + + /** + * Event course section updated. + * @param mixed $event + * @return void + */ + public static function course_section_updated($event) { + $data = $event->get_data(); + $sectionid = $data['objectid']; + $courseid = $data['courseid']; + self::course_section_cache_updated($courseid, $sectionid); + } + + /** + * Course cache updated. + * @param mixed $courseid + * @return void + */ + public static function course_cache_updated($courseid) { + $cache = format_designer_get_cache_object(); + $cache->delete_vaild_section_completed_cache($courseid); + $cache->delete_user_section_completed_cache($courseid); + $cache->delete_course_progress_uncompletion_criteria($courseid); + $cache->delete_due_overdue_activities_count($courseid); + $cache->delete_criteria_progress($courseid); + $cache->delete("g_c_a{$courseid}"); + $cache->delete("g_c_s_ic{$courseid}"); + } + + /** + * Course user cache updated. + * @param mixed $courseid + * @param mixed $userid + * @return void + */ + public static function course_user_cache_updated($courseid , $userid) { + $cache = format_designer_get_cache_object(); + $cache->delete_vaild_section_completed_cache($courseid); + $cache->delete_user_section_completed_cache($courseid); + $cache->delete_course_progress_uncompletion_criteria($courseid, $userid); + $cache->delete_due_overdue_activities_count($courseid, $userid); + $cache->delete_criteria_progress($courseid, $userid); + $cache->delete("g_c_a{$courseid}"); + $cache->delete("g_c_s_ic{$courseid}"); + } + + /** + * Handled the Course section module cache updated. + * @param mixed $courseid + * @param mixed $cmid + * @return bool + */ + public static function course_section_module_cache_updated($courseid, $cmid) { global $DB; - $courseid = $event->courseid; - $DB->delete_records('format_designer_options', ['courseid' => $courseid]); + + if (course_get_format($courseid)->get_course()->format !== 'designer') { + return true; + } + + $cm = $DB->get_record("course_modules", ['id' => $cmid]); + // Clear cache. + $cache = format_designer_get_cache_object(); + $cache->delete_vaild_section_completed_cache($courseid); + $cache->delete_user_section_completed_cache($courseid); + $cache->delete_course_progress_uncompletion_criteria($courseid); + $cache->delete_due_overdue_activities_count($courseid); + $cache->delete_criteria_progress($courseid); + $cache->delete("fdo_cm_j_{$courseid}"); + $cache->delete("g_c_a{$courseid}"); + $cache->delete("g_c_s_ic{$courseid}"); + } + + /** + * Course section cache updated. + * @param mixed $courseid + * @param mixed $sectionid + * @return bool + */ + public static function course_section_cache_updated($courseid, $sectionid) { + if (course_get_format($courseid)->get_course()->format !== 'designer') { + return true; + } + // Clear cache. + $cache = format_designer_get_cache_object(); + $cache->delete_vaild_section_completed_cache($courseid, $sectionid); + $cache->delete_user_section_completed_cache($courseid, $sectionid); + $cache->delete_due_overdue_activities_count($courseid); + $cache->delete_course_progress_uncompletion_criteria($courseid); + $cache->delete_criteria_progress($courseid); + $cache->delete("g_c_a{$courseid}"); + $cache->delete("g_c_s_ic{$courseid}"); } } diff --git a/classes/helper.php b/classes/helper.php index 7664852..eebcc75 100644 --- a/classes/helper.php +++ b/classes/helper.php @@ -154,17 +154,11 @@ public function get_course_staff_users($course) { */ protected function get_staffs_users($course) { $staffids = []; - $staffroleids = explode(",", $course->coursestaff); - $enrolusers = enrol_get_course_users_roles($course->id); - if (!empty($enrolusers)) { - foreach ($enrolusers as $userid => $roles) { - foreach ($staffroleids as $staffid) { - if (isset($roles[$staffid])) { - $staffids[] = $userid; - } - } - } + if (!empty($course->coursestaff)) { + $staffroleids = explode(",", $course->coursestaff); + $coursecontext = \context_course::instance($course->id); + $staffids = get_role_users($staffroleids, $coursecontext, false, 'ra.id, u.lastname, u.firstname, u.id'); } - return array_unique($staffids); + return array_keys($staffids); } } diff --git a/classes/options.php b/classes/options.php index 6a28304..b353a2d 100644 --- a/classes/options.php +++ b/classes/options.php @@ -165,29 +165,41 @@ public static function is_vaild_section_completed($section, $course, $modinfo, $ * @return bool|array Result of section completion or Current progress data. */ public static function is_section_completed($section, $course, $modinfo, $result = false, $onlyrelative = false) { - + global $USER; $completioninfo = new \completion_info($course); $completionactivities = array_column($completioninfo->get_criteria(COMPLETION_CRITERIA_TYPE_ACTIVITY), 'moduleinstance'); $cmcompleted = 0; $totalmods = 0; $issectioncompletion = 0; - if (!empty($modinfo->sections[$section->section]) && $section->uservisible) { - foreach ($modinfo->sections[$section->section] as $modnumber) { - $mod = $modinfo->cms[$modnumber]; - if (!empty($mod)) { - if ($onlyrelative && !in_array($mod->id, $completionactivities)) { - continue; - } - $cmcompletion = new cm_completion($mod); - if ($mod->is_visible_on_course_page() && $cmcompletion->get_completion_mode() != COMPLETION_TRACKING_NONE) { - $totalmods++; - $cmcompletionstate = $cmcompletion->get_completion_state(); - if ($cmcompletionstate == COMPLETION_COMPLETE || $cmcompletionstate == COMPLETION_COMPLETE_PASS ) { - $cmcompleted++; + $cache = format_designer_get_cache_object(); + // Vaild section completed c _courseid _sectionid. + $cachekey = "s_c_c_{$course->id}_s_{$section->id}_u_{$USER->id}"; + if (!$cache->get($cachekey)) { + if (!empty($modinfo->sections[$section->section]) && $section->uservisible) { + foreach ($modinfo->sections[$section->section] as $modnumber) { + $mod = $modinfo->cms[$modnumber]; + if (!empty($mod)) { + if ($onlyrelative && !in_array($mod->id, $completionactivities)) { + continue; + } + $cmcompletion = new cm_completion($mod); + if ($mod->is_visible_on_course_page() && $cmcompletion->get_completion_mode() != COMPLETION_TRACKING_NONE) { + $totalmods++; + $cmcompletionstate = $cmcompletion->get_completion_state(); + if ($cmcompletionstate == COMPLETION_COMPLETE || $cmcompletionstate == COMPLETION_COMPLETE_PASS ) { + $cmcompleted++; + } } } } } + $cache->set($cachekey, ['totalmods' => $totalmods, 'cmcompleted' => $cmcompleted]); + } + + if ($cache->get($cachekey)) { + $cachedata = $cache->get($cachekey); + $totalmods = $cachedata['totalmods']; + $cmcompleted = $cachedata['cmcompleted']; } if ($totalmods) { diff --git a/classes/output/renderer.php b/classes/output/renderer.php index 4f57818..d862072 100644 --- a/classes/output/renderer.php +++ b/classes/output/renderer.php @@ -520,25 +520,29 @@ public function course_header_metadata_details(\stdClass $course, bool $dataonly */ public function due_overdue_activities_count(): array { global $USER, $DB; - $duecount = $overduecount = 0; - $modinfo = $this->modinfo; - $completion = new \completion_info($this->modinfo->get_course()); - - foreach ($modinfo->sections as $modnumbers) { - foreach ($modnumbers as $modnumber) { - $mod = $modinfo->cms[$modnumber]; - if (!empty($mod) && $DB->record_exists('course_modules', ['id' => $mod->id, 'deletioninprogress' => 0]) - && $mod->uservisible) { - $data = $completion->get_data($mod, true, $USER->id); - if ($data->completionstate != COMPLETION_COMPLETE) { - $cmcompletion = new cm_completion($mod); - $overduecount = ($cmcompletion->is_overdue()) ? $overduecount + 1 : $overduecount; - $duecount = ($cmcompletion->is_due_today()) ? $duecount + 1 : $duecount; + $cache = format_designer_get_cache_object(); + $cachekey = "d_o_a_c_c{$this->modinfo->get_course()->id}_u{$USER->id}"; + if (!$cache->get($cachekey)) { + $duecount = $overduecount = 0; + $modinfo = $this->modinfo; + $completion = new \completion_info($this->modinfo->get_course()); + foreach ($modinfo->sections as $modnumbers) { + foreach ($modnumbers as $modnumber) { + $mod = $modinfo->cms[$modnumber]; + if (!empty($mod) && $DB->record_exists('course_modules', ['id' => $mod->id, 'deletioninprogress' => 0]) + && $mod->uservisible) { + $data = $completion->get_data($mod, true, $USER->id); + if ($data->completionstate != COMPLETION_COMPLETE) { + $cmcompletion = new cm_completion($mod); + $overduecount = ($cmcompletion->is_overdue()) ? $overduecount + 1 : $overduecount; + $duecount = ($cmcompletion->is_due_today()) ? $duecount + 1 : $duecount; + } } } } + $cache->set($cachekey, ['dues' => $duecount, 'overdues' => $overduecount]); } - return ['dues' => $duecount, 'overdues' => $overduecount]; + return $cache->get($cachekey); } /** @@ -547,15 +551,20 @@ public function due_overdue_activities_count(): array { * @return cm_info[] Array from $cmid => $cm of all activities with completion enabled, */ public static function get_completion_activities($course) { - $modinfo = get_fast_modinfo($course); - $result = []; - foreach ($modinfo->get_cms() as $cm) { - if ($cm->completion != COMPLETION_TRACKING_NONE && !$cm->deletioninprogress - && $cm->is_visible_on_course_page()) { - $result[$cm->id] = $cm; + $cache = format_designer_get_cache_object(); + $key = "g_c_a{$course->id}"; + if (!$cache->get($key)) { + $modinfo = get_fast_modinfo($course); + $result = []; + foreach ($modinfo->get_cms() as $cm) { + if ($cm->completion != COMPLETION_TRACKING_NONE && !$cm->deletioninprogress + && $cm->is_visible_on_course_page()) { + $result[$cm->id] = $cm; + } } + $cache->set($key, $result); } - return $result; + return $cache->get($key); } /** @@ -565,18 +574,24 @@ public static function get_completion_activities($course) { * @return int */ public static function get_count_sections_incourse($course) { - $sections = 0; - $modinfo = get_fast_modinfo($course); - $realtiveactivities = isset($course->calsectionprogress) && - ($course->calsectionprogress == DESIGNER_PROGRESS_RELEVANTACTIVITIES) ? true : false; - - foreach ($modinfo->sections as $sectionno => $modnumbers) { - $section = course_get_format($course)->get_section($sectionno); - if (\format_designer\options::is_vaild_section_completed($section, $course, $modinfo, $realtiveactivities)) { - $sections += 1; + $cache = format_designer_get_cache_object(); + $key = "g_c_s_ic{$course->id}"; + if (!$cache->get($key)) { + $sections = 0; + $modinfo = get_fast_modinfo($course); + $realtiveactivities = isset($course->calsectionprogress) && + ($course->calsectionprogress == DESIGNER_PROGRESS_RELEVANTACTIVITIES) ? true : false; + + foreach ($modinfo->sections as $sectionno => $modnumbers) { + $section = course_get_format($course)->get_section($sectionno); + if (\format_designer\options::is_vaild_section_completed($section, $course, + $modinfo, $realtiveactivities) == "true") { + $sections += 1; + } } + $cache->set($key, $sections); } - return $sections; + return $cache->get($key); } /** @@ -588,153 +603,166 @@ public static function get_count_sections_incourse($course) { */ public static function criteria_progress($course, $userid) { global $USER; - $completion = new \completion_info($course); - $modinfo = get_fast_modinfo($course); - $context = \context_course::instance($course->id); - // First, let's make sure completion is enabled. - if (!$completion->is_enabled()) { - return null; - } + $cache = format_designer_get_cache_object(); + $cachekey = "c_p_c{$course->id}_u_{$userid}"; + if ($cache->get($cachekey) === false) { - $result = []; - $completedcriteria = []; - $uncompletedcriteria = []; + $completion = new \completion_info($course); + if (!$completion->is_enabled()) { + $cache->set($cachekey, null); + } - // Get the number of modules that support completion. - $modules = self::get_completion_activities($course); - $completionactivities = $completion->get_criteria(COMPLETION_CRITERIA_TYPE_ACTIVITY); - $complteioncourses = $completion->get_criteria(COMPLETION_CRITERIA_TYPE_COURSE); + $modinfo = get_fast_modinfo($course); + $context = \context_course::instance($course->id); + // First, let's make sure completion is enabled. - $count = count($completionactivities); + $result = []; + $completedcriteria = []; + $uncompletedcriteria = []; - $isapplycompletioncourses = false; - if (!isset($course->calcourseprogress)) { - $isapplycompletioncourses = true; - } else if ($course->calcourseprogress == DESIGNER_PROGRESS_CRITERIA) { - $isapplycompletioncourses = true; - } + // Get the number of modules that support completion. + $modules = self::get_completion_activities($course); + $completionactivities = $completion->get_criteria(COMPLETION_CRITERIA_TYPE_ACTIVITY); + $complteioncourses = $completion->get_criteria(COMPLETION_CRITERIA_TYPE_COURSE); - if ($isapplycompletioncourses) { - $count += count($complteioncourses); - } - $cmidentifier = "moduleinstance"; + $count = count($completionactivities); - if (format_designer_has_pro()) { - $format = course_get_format($course); - $course = $format->get_course(); - if ($course->calcourseprogress == DESIGNER_PROGRESS_ALLACTIVITIES) { - $count = count($modules); - $completionactivities = $modules; - $cmidentifier = "id"; - } else if ($course->calcourseprogress == DESIGNER_PROGRESS_SECTIONS) { - $completionactivities = []; - $count = self::get_count_sections_incourse($course); + $isapplycompletioncourses = false; + if (!isset($course->calcourseprogress)) { + $isapplycompletioncourses = true; + } else if ($course->calcourseprogress == DESIGNER_PROGRESS_CRITERIA) { + $isapplycompletioncourses = true; } - } - if (!$count) { - return null; - } - // Get the number of modules that have been completed. - $completed = 0; - if ($completionactivities) { - foreach ($completionactivities as $activity) { - $cmid = $activity->{$cmidentifier}; - if (isset($modules[$cmid])) { - $data = $completion->get_data($modules[$cmid], true, $userid); - $completed += ($data->completionstate == COMPLETION_COMPLETE || - $data->completionstate == COMPLETION_COMPLETE_PASS) ? 1 : 0; - $modtooltiplink = html_writer::link($modules[$cmid]->url, - get_string('stractivity', 'format_designer') . ": " . $modules[$cmid]->name); - if ($data->completionstate == COMPLETION_COMPLETE || - $data->completionstate == COMPLETION_COMPLETE_PASS) { - $completedcriteria[] = $modtooltiplink; - } else { - $uncompletedcriteria[] = $modtooltiplink; - } - } + if ($isapplycompletioncourses) { + $count += count($complteioncourses); } - } + $cmidentifier = "moduleinstance"; - if ($isapplycompletioncourses && $complteioncourses) { - foreach ($complteioncourses as $coursecriteria) { - $courseid = $coursecriteria->courseinstance; - $course = get_course($courseid); - $completion = new \completion_info($course); - $coursetooltiplink = html_writer::link(new moodle_url('/course/view.php', - ['id' => $course->id]), get_string('strcourse', 'format_designer') . ": " . $course->fullname); - if ($completion->is_course_complete($userid)) { - $completed += 1; - $completedcriteria[] = $coursetooltiplink; - } else { - $uncompletedcriteria[] = $coursetooltiplink; + if (format_designer_has_pro()) { + $format = course_get_format($course); + $course = $format->get_course(); + if ($course->calcourseprogress == DESIGNER_PROGRESS_ALLACTIVITIES) { + $count = count($modules); + $completionactivities = $modules; + $cmidentifier = "id"; + } else if ($course->calcourseprogress == DESIGNER_PROGRESS_SECTIONS) { + $completionactivities = []; + $count = self::get_count_sections_incourse($course); } } - } - if (format_designer_has_pro()) { + if (!$count) { + $cache->set($cachekey, null); + } - if (isset($course->calcourseprogress) && $course->calcourseprogress == DESIGNER_PROGRESS_SECTIONS - && !empty($modinfo->sections)) { - foreach ($modinfo->sections as $sectionno => $modnumbers) { - $section = course_get_format($course)->get_section($sectionno); - if ($section->visible) { - $sectionname = get_section_name($course, $section); - $sectionurl = new moodle_url('/course/view.php', ['id' => $course->id, 'section' => $sectionno]); - $sectiontooltiplink = html_writer::link($sectionurl, - get_string('strsection', 'format_designer') . ": ". $sectionname); - $realtiveactivities = isset($course->calsectionprogress) && - ($course->calsectionprogress == DESIGNER_PROGRESS_RELEVANTACTIVITIES) ? true : false; - if (\format_designer\options::is_section_completed($section, $course, $modinfo, - true, $realtiveactivities)) { - $completed += 1; - $completedcriteria[] = $sectiontooltiplink; + // Get the number of modules that have been completed. + $completed = 0; + if ($completionactivities) { + foreach ($completionactivities as $activity) { + $cmid = $activity->{$cmidentifier}; + if (isset($modules[$cmid])) { + $data = $completion->get_data($modules[$cmid], true, $userid); + $completed += ($data->completionstate == COMPLETION_COMPLETE || + $data->completionstate == COMPLETION_COMPLETE_PASS) ? 1 : 0; + $modtooltiplink = html_writer::link($modules[$cmid]->url, + get_string('stractivity', 'format_designer') . ": " . $modules[$cmid]->name); + if ($data->completionstate == COMPLETION_COMPLETE || + $data->completionstate == COMPLETION_COMPLETE_PASS) { + $completedcriteria[] = $modtooltiplink; } else { - if (\format_designer\options::is_vaild_section_completed($section, $course, - $modinfo, $realtiveactivities)) { - $uncompletedcriteria[] = $sectiontooltiplink; + $uncompletedcriteria[] = $modtooltiplink; + } + } + } + } + + if ($isapplycompletioncourses && $complteioncourses) { + foreach ($complteioncourses as $coursecriteria) { + $courseid = $coursecriteria->courseinstance; + $course = get_course($courseid); + $completion = new \completion_info($course); + $coursetooltiplink = html_writer::link(new moodle_url('/course/view.php', + ['id' => $course->id]), get_string('strcourse', 'format_designer') . ": " . $course->fullname); + if ($completion->is_course_complete($userid)) { + $completed += 1; + $completedcriteria[] = $coursetooltiplink; + } else { + $uncompletedcriteria[] = $coursetooltiplink; + } + } + } + + if (format_designer_has_pro()) { + $sectiontooltiplink = ''; + if (isset($course->calcourseprogress) && $course->calcourseprogress == DESIGNER_PROGRESS_SECTIONS + && !empty($modinfo->sections)) { + foreach ($modinfo->sections as $sectionno => $modnumbers) { + $section = course_get_format($course)->get_section($sectionno); + if ($section->visible) { + $sectionname = get_section_name($course, $section); + $sectionurl = new moodle_url('/course/view.php', ['id' => $course->id, 'section' => $sectionno]); + $sectiontooltiplink = html_writer::link($sectionurl, + get_string('strsection', 'format_designer') . ": ". $sectionname); + $realtiveactivities = isset($course->calsectionprogress) && + ($course->calsectionprogress == DESIGNER_PROGRESS_RELEVANTACTIVITIES) ? true : false; + if (\format_designer\options::is_section_completed($section, $course, $modinfo, + true, $realtiveactivities)) { + $completed += 1; + $completedcriteria[] = $sectiontooltiplink; + } else { + if (\format_designer\options::is_vaild_section_completed($section, $course, + $modinfo, $realtiveactivities) == "true") { + $uncompletedcriteria[] = $sectiontooltiplink; + } } } } } + $completedcriteria[] = $sectiontooltiplink; } - } - $percent = ($count > 0) ? (($completed / $count) * 100) : 0; - $completioncriteriahtml = ''; - $uncompletioncriteriahtml = ''; + $percent = ($count > 0) ? (($completed / $count) * 100) : 0; + $completioncriteriahtml = ''; + $uncompletioncriteriahtml = ''; + + if (!empty($completedcriteria)) { + $completioncriteriahtml = html_writer::start_div('completion-criteria-toolblock designer-criteria-tooltip'); + $completioncriteriahtml .= html_writer::start_div('head-block'); + $completioncriteriahtml .= get_string('struppercompleted', 'format_designer'); + $completioncriteriahtml .= html_writer::end_div(); + $completioncriteriahtml .= html_writer::start_div('info-block'); + $completioncriteriahtml .= implode("
", $completedcriteria); + $completioncriteriahtml .= html_writer::end_div(); - if (!empty($completedcriteria)) { - $completioncriteriahtml = html_writer::start_div('completion-criteria-toolblock designer-criteria-tooltip'); - $completioncriteriahtml .= html_writer::start_div('head-block'); - $completioncriteriahtml .= get_string('struppercompleted', 'format_designer'); - $completioncriteriahtml .= html_writer::end_div(); - $completioncriteriahtml .= html_writer::start_div('info-block'); - $completioncriteriahtml .= implode("
", $completedcriteria); $completioncriteriahtml .= html_writer::end_div(); + } - $completioncriteriahtml .= html_writer::end_div(); - } + if (!empty($uncompletedcriteria)) { + $uncompletioncriteriahtml = html_writer::start_div('uncompletion-criteria-toolblock designer-criteria-tooltip'); + $uncompletioncriteriahtml .= html_writer::start_div('head-block'); + $uncompletioncriteriahtml .= get_string('strtodo', 'format_designer'); + $uncompletioncriteriahtml .= html_writer::end_div(); + $uncompletioncriteriahtml .= html_writer::start_div('info-block'); + $uncompletioncriteriahtml .= implode("
", $uncompletedcriteria); + $uncompletioncriteriahtml .= html_writer::end_div(); + $uncompletioncriteriahtml .= html_writer::end_div(); + } - if (!empty($uncompletedcriteria)) { - $uncompletioncriteriahtml = html_writer::start_div('uncompletion-criteria-toolblock designer-criteria-tooltip'); - $uncompletioncriteriahtml .= html_writer::start_div('head-block'); - $uncompletioncriteriahtml .= get_string('strtodo', 'format_designer'); - $uncompletioncriteriahtml .= html_writer::end_div(); - $uncompletioncriteriahtml .= html_writer::start_div('info-block'); - $uncompletioncriteriahtml .= implode("
", $uncompletedcriteria); - $uncompletioncriteriahtml .= html_writer::end_div(); - $uncompletioncriteriahtml .= html_writer::end_div(); - } + $cachedata = [ + 'count' => $count, + 'completed' => $completed, + 'percent' => round($percent), + 'remain' => 100 - $percent, + 'completioncriteriahtml' => $completioncriteriahtml, + 'uncompletioncriteriahtml' => $uncompletioncriteriahtml, + ]; - return [ - 'count' => $count, - 'completed' => $completed, - 'percent' => round($percent), - 'remain' => 100 - $percent, - 'completioncriteriahtml' => $completioncriteriahtml, - 'uncompletioncriteriahtml' => $uncompletioncriteriahtml, - ]; + if (!$cache->get($cachekey)) { + $cache->set($cachekey, $cachedata); + } + } + return $cache->get($cachekey); } diff --git a/db/caches.php b/db/caches.php new file mode 100644 index 0000000..458fcc9 --- /dev/null +++ b/db/caches.php @@ -0,0 +1,34 @@ +. + +/** + * Code to be executed after the plugin's database scheme has been installed is defined here. + * + * @package format_designer + * @copyright Lmsace dev team + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$definitions = array( + 'designeroptions' => array( + 'mode' => cache_store::MODE_APPLICATION, + 'simplekeys' => true, + 'simpledata' => false, + 'overrideclass' => '\format_designer\cache\loader', + ), +); diff --git a/db/events.php b/db/events.php index 0f7eab2..40ab24e 100644 --- a/db/events.php +++ b/db/events.php @@ -37,8 +37,48 @@ 'eventname' => 'core\event\course_module_deleted', 'callback' => '\format_designer\events::course_module_deleted', ], + [ + 'eventname' => 'core\event\course_module_deleted', + 'callback' => '\format_designer\events::course_module_deleted', + ], + [ + 'eventname' => 'core\event\course_completed', + 'callback' => '\format_designer\events::course_completed', + ], + [ + 'eventname' => 'core\event\course_module_completion_updated', + 'callback' => '\format_designer\events::course_module_completion_updated', + ], [ 'eventname' => 'core\event\course_deleted', 'callback' => '\format_designer\events::course_deleted', ], + [ + 'eventname' => 'core\event\course_completion_updated', + 'callback' => '\format_designer\events::course_completion_updated', + ], + [ + 'eventname' => 'core\event\course_updated', + 'callback' => '\format_designer\events::course_updated', + ], + [ + 'eventname' => 'core\event\course_module_created', + 'callback' => '\format_designer\events::course_module_created', + ], + [ + 'eventname' => 'core\event\course_module_updated', + 'callback' => '\format_designer\events::course_module_updated', + ], + [ + 'eventname' => 'core\event\course_module_deleted', + 'callback' => '\format_designer\events::course_module_deleted', + ], + [ + 'eventname' => 'core\event\course_section_deleted', + 'callback' => '\format_designer\events::course_section_deleted', + ], + [ + 'eventname' => 'core\event\course_section_updated', + 'callback' => '\format_designer\events::course_section_updated', + ], ]; diff --git a/lib.php b/lib.php index b69794d..4bc5406 100644 --- a/lib.php +++ b/lib.php @@ -458,6 +458,7 @@ public static function course_format_options_list($foreditform = false) { static $courseformatoptions = false; $teacher = get_archetype_roles('editingteacher'); $teacher = reset($teacher); + $courseformatoptionsedit = []; if ($courseformatoptions === false) { $courseconfig = get_config('moodlecourse'); $courseformatoptions = [ @@ -569,6 +570,12 @@ public static function course_format_options_list($foreditform = false) { 'default' => 0, 'type' => PARAM_INT, ]; + $courseformatoptionsedit[$field->inputname] = [ + 'label' => $field->field->name, + 'element_type' => 'advcheckbox', + 'help' => 'profilefieditem', + 'help_component' => 'format_designer', + ]; } } } @@ -600,7 +607,7 @@ public static function course_format_options_list($foreditform = false) { } if ($foreditform && !isset($courseformatoptions['coursedisplay']['label'])) { - $courseformatoptionsedit = [ + $courseformatoptionsedit += [ 'hiddensections' => [ 'label' => new lang_string('hiddensections'), 'help' => 'hiddensections', @@ -825,20 +832,6 @@ public static function course_format_options_list($foreditform = false) { 'help_component' => 'format_designer', ]; - if (format_designer_has_pro() != 1 ) { - $userprofilefields = profile_get_user_fields_with_data(0); - if (!empty($userprofilefields)) { - foreach ($userprofilefields as $field) { - $courseformatoptionsedit[$field->inputname] = [ - 'label' => $field->field->name, - 'element_type' => 'advcheckbox', - 'help' => 'profilefieditem', - 'help_component' => 'format_designer', - ]; - } - } - } - $courseformatoptionsedit['courseheroactivityheader'] = [ 'label' => new lang_string('heroactivity', 'format_designer'), 'element_type' => 'header', @@ -2578,3 +2571,11 @@ function format_designer_is_support_subpanel() { } return false; } + +/** + * Designer get the cache object. + * @return cache_application|cache_session|cache_store + */ +function format_designer_get_cache_object() { + return cache::make('format_designer', 'designeroptions'); +} diff --git a/version.php b/version.php index 4d28e05..f65baa7 100644 --- a/version.php +++ b/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2024110800; // The current plugin version (Date: YYYYMMDDXX). +$plugin->version = 2024112700; // The current plugin version (Date: YYYYMMDDXX). $plugin->requires = 2020061500; // Requires this Moodle version. $plugin->component = 'format_designer'; // Full name of the plugin (used for diagnostics). $plugin->release = 'Version 1.6';