MDL-86856 course: Deprecate course_delete_module
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
issueNumber: MDL-86856
|
||||
notes:
|
||||
core_course:
|
||||
- message: >-
|
||||
The following methods have been deprecated and should no longer be used:
|
||||
- `course_delete_module`
|
||||
- `course_module_flag_for_async_deletion`
|
||||
Please consider using the equivalent methods, delete and delete_async, in `core_courseformat\local\cmactions` instead.
|
||||
type: deprecated
|
||||
+27
-196
@@ -700,153 +700,20 @@ function set_coursemodule_name($cmid, $name) {
|
||||
* @param bool $async whether or not to try to delete the module using an adhoc task. Async also depends on a plugin hook.
|
||||
* @throws moodle_exception
|
||||
* @since Moodle 2.5
|
||||
* @deprecated since Moodle 5.2.
|
||||
* @todo MDL-86956 Final deprecation in Moodle 6.0.
|
||||
*/
|
||||
#[\core\attribute\deprecated(
|
||||
replacement: 'core_courseformat\local\cmactions::delete',
|
||||
since: '5.2',
|
||||
mdl: 'MDL-86856',
|
||||
reason: 'Course activity editing global functions have been moved to format actions',
|
||||
)]
|
||||
function course_delete_module($cmid, $async = false) {
|
||||
// Check the 'course_module_background_deletion_recommended' hook first.
|
||||
// Only use asynchronous deletion if at least one plugin returns true and if async deletion has been requested.
|
||||
// Both are checked because plugins should not be allowed to dictate the deletion behaviour, only support/decline it.
|
||||
// It's up to plugins to handle things like whether or not they are enabled.
|
||||
if ($async && $pluginsfunction = get_plugins_with_function('course_module_background_deletion_recommended')) {
|
||||
foreach ($pluginsfunction as $plugintype => $plugins) {
|
||||
foreach ($plugins as $pluginfunction) {
|
||||
if ($pluginfunction()) {
|
||||
return course_module_flag_for_async_deletion($cmid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
\core\deprecation::emit_deprecation(__FUNCTION__);
|
||||
|
||||
global $CFG, $DB;
|
||||
|
||||
require_once($CFG->libdir.'/gradelib.php');
|
||||
require_once($CFG->libdir.'/questionlib.php');
|
||||
require_once($CFG->dirroot.'/blog/lib.php');
|
||||
require_once($CFG->dirroot.'/calendar/lib.php');
|
||||
|
||||
// Get the course module.
|
||||
if (!$cm = $DB->get_record('course_modules', array('id' => $cmid))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the module context.
|
||||
$modcontext = context_module::instance($cm->id);
|
||||
|
||||
// Get the course module name.
|
||||
$modulename = $DB->get_field('modules', 'name', array('id' => $cm->module), MUST_EXIST);
|
||||
|
||||
// Get the file location of the delete_instance function for this module.
|
||||
$modlib = "$CFG->dirroot/mod/$modulename/lib.php";
|
||||
|
||||
// Include the file required to call the delete_instance function for this module.
|
||||
if (file_exists($modlib)) {
|
||||
require_once($modlib);
|
||||
} else {
|
||||
throw new moodle_exception('cannotdeletemodulemissinglib', '', '', null,
|
||||
"Cannot delete this module as the file mod/$modulename/lib.php is missing.");
|
||||
}
|
||||
|
||||
// Warning! there is very similar code in remove_course_contents.
|
||||
// If you are changing this code, you probably need to change that too.
|
||||
$deleteinstancefunction = $modulename . '_delete_instance';
|
||||
|
||||
// Ensure the delete_instance function exists for this module.
|
||||
if (!function_exists($deleteinstancefunction)) {
|
||||
throw new moodle_exception('cannotdeletemodulemissingfunc', '', '', null,
|
||||
"Cannot delete this module as the function {$modulename}_delete_instance is missing in mod/$modulename/lib.php.");
|
||||
}
|
||||
|
||||
// Allow plugins to use this course module before we completely delete it.
|
||||
if ($pluginsfunction = get_plugins_with_function('pre_course_module_delete')) {
|
||||
foreach ($pluginsfunction as $plugintype => $plugins) {
|
||||
foreach ($plugins as $pluginfunction) {
|
||||
$pluginfunction($cm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($cm->instance)) {
|
||||
throw new moodle_exception('cannotdeletemodulemissinginstance', '', '', null,
|
||||
"Cannot delete course module with ID $cm->id because it does not have a valid activity instance.");
|
||||
}
|
||||
|
||||
// Call the delete_instance function, if it returns false throw an exception.
|
||||
if (!$deleteinstancefunction($cm->instance)) {
|
||||
throw new moodle_exception('cannotdeletemoduleinstance', '', '', null,
|
||||
"Cannot delete the module $modulename (instance).");
|
||||
}
|
||||
|
||||
// We delete the questions after the activity database is removed,
|
||||
// because questions are referenced via question reference tables
|
||||
// and cannot be deleted while the activities that use them still exist.
|
||||
question_delete_activity($cm);
|
||||
|
||||
// Remove all module files in case modules forget to do that.
|
||||
$fs = get_file_storage();
|
||||
$fs->delete_area_files($modcontext->id);
|
||||
|
||||
// Delete events from calendar.
|
||||
if ($events = $DB->get_records('event', array('instance' => $cm->instance, 'modulename' => $modulename))) {
|
||||
$coursecontext = context_course::instance($cm->course);
|
||||
foreach($events as $event) {
|
||||
$event->context = $coursecontext;
|
||||
$calendarevent = calendar_event::load($event);
|
||||
$calendarevent->delete();
|
||||
}
|
||||
}
|
||||
|
||||
// Delete grade items, outcome items and grades attached to modules.
|
||||
if ($grade_items = grade_item::fetch_all(array('itemtype' => 'mod', 'itemmodule' => $modulename,
|
||||
'iteminstance' => $cm->instance, 'courseid' => $cm->course))) {
|
||||
foreach ($grade_items as $grade_item) {
|
||||
$grade_item->delete('moddelete');
|
||||
}
|
||||
}
|
||||
|
||||
// Delete associated blogs and blog tag instances.
|
||||
blog_remove_associations_for_module($modcontext->id);
|
||||
|
||||
// Delete completion and availability data; it is better to do this even if the
|
||||
// features are not turned on, in case they were turned on previously (these will be
|
||||
// very quick on an empty table).
|
||||
$DB->delete_records('course_modules_completion', array('coursemoduleid' => $cm->id));
|
||||
$DB->delete_records('course_modules_viewed', ['coursemoduleid' => $cm->id]);
|
||||
$DB->delete_records('course_completion_criteria', array('moduleinstance' => $cm->id,
|
||||
'course' => $cm->course,
|
||||
'criteriatype' => COMPLETION_CRITERIA_TYPE_ACTIVITY));
|
||||
|
||||
// Delete all tag instances associated with the instance of this module.
|
||||
core_tag_tag::delete_instances('mod_' . $modulename, null, $modcontext->id);
|
||||
core_tag_tag::remove_all_item_tags('core', 'course_modules', $cm->id);
|
||||
|
||||
// Notify the competency subsystem.
|
||||
\core_competency\api::hook_course_module_deleted($cm);
|
||||
|
||||
// Delete the context.
|
||||
context_helper::delete_instance(CONTEXT_MODULE, $cm->id);
|
||||
|
||||
// Delete the module from the course_modules table.
|
||||
$DB->delete_records('course_modules', array('id' => $cm->id));
|
||||
|
||||
// Delete module from that section.
|
||||
if (!delete_mod_from_section($cm->id, $cm->section)) {
|
||||
throw new moodle_exception('cannotdeletemodulefromsection', '', '', null,
|
||||
"Cannot delete the module $modulename (instance) from section.");
|
||||
}
|
||||
|
||||
// Trigger event for course module delete action.
|
||||
$event = \core\event\course_module_deleted::create(array(
|
||||
'courseid' => $cm->course,
|
||||
'context' => $modcontext,
|
||||
'objectid' => $cm->id,
|
||||
'other' => array(
|
||||
'modulename' => $modulename,
|
||||
'instanceid' => $cm->instance,
|
||||
)
|
||||
));
|
||||
$event->add_record_snapshot('course_modules', $cm);
|
||||
$event->trigger();
|
||||
\course_modinfo::purge_course_module_cache($cm->course, $cm->id);
|
||||
rebuild_course_cache($cm->course, false, true);
|
||||
$coursecontext = context_module::instance($cmid)->get_course_context();
|
||||
formatactions::cm($coursecontext->instanceid)->delete($cmid, $async);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -858,61 +725,25 @@ function course_delete_module($cmid, $async = false) {
|
||||
* @param int $cmid the course module id.
|
||||
* @return ?bool whether the module was successfully scheduled for deletion.
|
||||
* @throws \moodle_exception
|
||||
* @deprecated since Moodle 5.2.
|
||||
* @todo MDL-86956 Final deprecation in Moodle 6.0.
|
||||
*/
|
||||
#[\core\attribute\deprecated(
|
||||
replacement: 'core_courseformat\local\cmactions::delete_async',
|
||||
since: '5.2',
|
||||
mdl: 'MDL-86856',
|
||||
reason: 'Course activity editing global functions have been moved to format actions',
|
||||
)]
|
||||
function course_module_flag_for_async_deletion($cmid) {
|
||||
global $CFG, $DB, $USER;
|
||||
require_once($CFG->libdir.'/gradelib.php');
|
||||
require_once($CFG->libdir.'/questionlib.php');
|
||||
require_once($CFG->dirroot.'/blog/lib.php');
|
||||
require_once($CFG->dirroot.'/calendar/lib.php');
|
||||
\core\deprecation::emit_deprecation(__FUNCTION__);
|
||||
|
||||
// Get the course module.
|
||||
if (!$cm = $DB->get_record('course_modules', array('id' => $cmid))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// We need to be reasonably certain the deletion is going to succeed before we background the process.
|
||||
// Make the necessary delete_instance checks, etc. before proceeding further. Throw exceptions if required.
|
||||
|
||||
// Get the course module name.
|
||||
$modulename = $DB->get_field('modules', 'name', array('id' => $cm->module), MUST_EXIST);
|
||||
|
||||
// Get the file location of the delete_instance function for this module.
|
||||
$modlib = "$CFG->dirroot/mod/$modulename/lib.php";
|
||||
|
||||
// Include the file required to call the delete_instance function for this module.
|
||||
if (file_exists($modlib)) {
|
||||
require_once($modlib);
|
||||
} else {
|
||||
throw new \moodle_exception('cannotdeletemodulemissinglib', '', '', null,
|
||||
"Cannot delete this module as the file mod/$modulename/lib.php is missing.");
|
||||
}
|
||||
|
||||
$deleteinstancefunction = $modulename . '_delete_instance';
|
||||
|
||||
// Ensure the delete_instance function exists for this module.
|
||||
if (!function_exists($deleteinstancefunction)) {
|
||||
throw new \moodle_exception('cannotdeletemodulemissingfunc', '', '', null,
|
||||
"Cannot delete this module as the function {$modulename}_delete_instance is missing in mod/$modulename/lib.php.");
|
||||
}
|
||||
|
||||
// We are going to defer the deletion as we can't be sure how long the module's pre_delete code will run for.
|
||||
$cm->deletioninprogress = '1';
|
||||
$DB->update_record('course_modules', $cm);
|
||||
|
||||
// Create an adhoc task for the deletion of the course module. The task takes an array of course modules for removal.
|
||||
$removaltask = new \core_course\task\course_delete_modules();
|
||||
$removaltask->set_custom_data(array(
|
||||
'cms' => array($cm),
|
||||
'userid' => $USER->id,
|
||||
'realuserid' => \core\session\manager::get_realuser()->id
|
||||
));
|
||||
|
||||
// Queue the task for the next run.
|
||||
\core\task\manager::queue_adhoc_task($removaltask);
|
||||
|
||||
// Reset the course cache to hide the module.
|
||||
rebuild_course_cache($cm->course, true);
|
||||
$coursecontext = context_module::instance($cmid)->get_course_context();
|
||||
// The new method is correctly declared as protected to prevent direct use, a visibility modifier that was not possible
|
||||
// in its original location.
|
||||
// To avoid code duplication, as a temporary solution, because this method will be removed in the near future,
|
||||
// it now calls the new protected method using reflection.
|
||||
$method = new ReflectionMethod(\core_courseformat\local\cmactions::class, 'delete_async');
|
||||
$method->invokeArgs(formatactions::cm($coursecontext->instanceid), [$cmid]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -109,7 +109,7 @@ final class course_delete_modules_test extends \advanced_testcase {
|
||||
$errormsg = str_replace('\\', '/', $e->getMessage()); // Normalise dir separator.
|
||||
$this->assertStringContainsString('cannotdeletemodulemissinglib', $errormsg);
|
||||
$this->assertStringContainsString('course/lib.php', $errormsg);
|
||||
$this->assertStringContainsString('mod/TestModuleToDelete/lib.php is missing', $errormsg);
|
||||
$this->assertStringContainsString('Missing file mod/TestModuleToDelete/lib.php', $errormsg);
|
||||
// Get line numbers array which contains the exception name.
|
||||
$lines = array_keys(preg_grep("/cannotdeletemodulemissinglib/", file(dirname(__DIR__) . '/lib.php')));
|
||||
// Increase 1 to keys to convert to actual line number.
|
||||
|
||||
Reference in New Issue
Block a user