Merge branch 'MDL-67548-master' of https://github.com/kabalin/moodle

This commit is contained in:
Adrian Greeve
2020-05-20 08:35:18 +08:00
7 changed files with 493 additions and 28 deletions
+56 -18
View File
@@ -171,6 +171,24 @@ class core_course_category implements renderable, cacheable_object, IteratorAggr
debugging('Can not unset core_course_category instance properties!', DEBUG_DEVELOPER);
}
/**
* Get list of plugin callback functions.
*
* @param string $name Callback function name.
* @return [callable] $pluginfunctions
*/
public function get_plugins_callback_function(string $name) : array {
$pluginfunctions = [];
if ($pluginsfunction = get_plugins_with_function($name)) {
foreach ($pluginsfunction as $plugintype => $plugins) {
foreach ($plugins as $pluginfunction) {
$pluginfunctions[] = $pluginfunction;
}
}
}
return $pluginfunctions;
}
/**
* Create an iterator because magic vars can't be seen by 'foreach'.
*
@@ -1900,13 +1918,12 @@ class core_course_category implements renderable, cacheable_object, IteratorAggr
return false;
}
$context = $this->get_context();
if (!$this->is_uservisible() ||
!has_capability('moodle/category:manage', $context)) {
if (!$this->has_manage_capability()) {
return false;
}
// Check all child categories (not only direct children).
$context = $this->get_context();
$sql = context_helper::get_preload_record_columns_sql('ctx');
$childcategories = $DB->get_records_sql('SELECT c.id, c.visible, '. $sql.
' FROM {context} ctx '.
@@ -1936,6 +1953,15 @@ class core_course_category implements renderable, cacheable_object, IteratorAggr
}
}
// Check if plugins permit deletion of category content.
$pluginfunctions = $this->get_plugins_callback_function('can_course_category_delete');
foreach ($pluginfunctions as $pluginfunction) {
// If at least one plugin does not permit deletion, stop and return false.
if (!$pluginfunction($this)) {
return false;
}
}
return true;
}
@@ -1961,13 +1987,9 @@ class core_course_category implements renderable, cacheable_object, IteratorAggr
$settimeout = core_php_time_limit::raise();
// Allow plugins to use this category before we completely delete it.
if ($pluginsfunction = get_plugins_with_function('pre_course_category_delete')) {
$category = $this->get_db_record();
foreach ($pluginsfunction as $plugintype => $plugins) {
foreach ($plugins as $pluginfunction) {
$pluginfunction($category);
}
}
$pluginfunctions = $this->get_plugins_callback_function('pre_course_category_delete');
foreach ($pluginfunctions as $pluginfunction) {
$pluginfunction($this->get_db_record());
}
$deletedcourses = array();
@@ -2076,25 +2098,35 @@ class core_course_category implements renderable, cacheable_object, IteratorAggr
public function can_move_content_to($newcatid) {
global $CFG;
require_once($CFG->libdir . '/questionlib.php');
$context = $this->get_context();
if (!$this->is_uservisible() ||
!has_capability('moodle/category:manage', $context)) {
if (!$this->has_manage_capability()) {
return false;
}
$testcaps = array();
// If this category has courses in it, user must have 'course:create' capability in target category.
if ($this->has_courses()) {
$testcaps[] = 'moodle/course:create';
}
// If this category has subcategories or questions, user must have 'category:manage' capability in target category.
if ($this->has_children() || question_context_has_any_questions($context)) {
if ($this->has_children() || question_context_has_any_questions($this->get_context())) {
$testcaps[] = 'moodle/category:manage';
}
if (!empty($testcaps)) {
return has_all_capabilities($testcaps, context_coursecat::instance($newcatid));
if (!empty($testcaps) && !has_all_capabilities($testcaps, context_coursecat::instance($newcatid))) {
// No sufficient capabilities to perform this task.
return false;
}
// Check if plugins permit moving category content.
$pluginfunctions = $this->get_plugins_callback_function('can_course_category_delete_move');
$newparentcat = self::get($newcatid, MUST_EXIST, true);
foreach ($pluginfunctions as $pluginfunction) {
// If at least one plugin does not permit move on deletion, stop and return false.
if (!$pluginfunction($this, $newparentcat)) {
return false;
}
}
// There is no content but still return true.
return true;
}
@@ -2124,6 +2156,12 @@ class core_course_category implements renderable, cacheable_object, IteratorAggr
$coursesids = $DB->get_fieldset_select('course', 'id', 'category = :category ORDER BY sortorder ASC', $params);
$context = $this->get_context();
// Allow plugins to make necessary changes before we move the category content.
$pluginfunctions = $this->get_plugins_callback_function('pre_course_category_delete_move');
foreach ($pluginfunctions as $pluginfunction) {
$pluginfunction($this, $newparentcat);
}
if ($children) {
foreach ($children as $childcat) {
$childcat->change_parent_raw($newparentcat);
@@ -2186,7 +2224,7 @@ class core_course_category implements renderable, cacheable_object, IteratorAggr
$event = \core\event\course_category_deleted::create(array(
'objectid' => $this->id,
'context' => $context,
'other' => array('name' => $this->name)
'other' => array('name' => $this->name, 'contentmovedcategoryid' => $newparentid)
));
$event->set_coursecat($this);
$event->trigger();