mirror of
https://github.com/moodle/moodle.git
synced 2025-04-20 07:56:06 +02:00
MDL-61363 question: update tags on question context change
This commit is contained in:
parent
081eb156c5
commit
68beb75851
@ -537,6 +537,120 @@ function question_delete_activity($cm, $feedback=true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will handle moving all tag instances to a new context for a
|
||||
* given list of questions.
|
||||
*
|
||||
* Questions can be tagged in up to two contexts:
|
||||
* 1.) The context the question exists in.
|
||||
* 2.) The course context (if the question context is a higher context.
|
||||
* E.g. course category context or system context.
|
||||
*
|
||||
* This means a question that exists in a higher context (e.g. course cat or
|
||||
* system context) may have multiple groups of tags in any number of child
|
||||
* course contexts.
|
||||
*
|
||||
* Questions in the course category context can be move "down" a context level
|
||||
* into one of their child course contexts or activity contexts which affects the
|
||||
* availability of that question in other courses / activities.
|
||||
*
|
||||
* In this case it makes the questions no longer available in the other course or
|
||||
* activity contexts so we need to make sure that the tag instances in those other
|
||||
* contexts are removed.
|
||||
*
|
||||
* @param stdClass[] $questions The list of question being moved (must include
|
||||
* the id and contextid)
|
||||
* @param context $newcontext The Moodle context the questions are being moved to
|
||||
*/
|
||||
function question_move_question_tags_to_new_context(array $questions, context $newcontext) {
|
||||
// If the questions are moving to a new course/activity context then we need to
|
||||
// find any existing tag instances from any unavailable course contexts and
|
||||
// delete them because they will no longer be applicable (we don't support
|
||||
// tagging questions across courses).
|
||||
$instancestodelete = [];
|
||||
$instancesfornewcontext = [];
|
||||
$newcontextparentids = $newcontext->get_parent_context_ids();
|
||||
$questionids = array_map(function($question) {
|
||||
return $question->id;
|
||||
}, $questions);
|
||||
$questionstagobjects = core_tag_tag::get_items_tags('core_question', 'question', $questionids);
|
||||
|
||||
foreach ($questions as $question) {
|
||||
$tagobjects = $questionstagobjects[$question->id];
|
||||
|
||||
foreach ($tagobjects as $tagobject) {
|
||||
$tagid = $tagobject->taginstanceid;
|
||||
$tagcontextid = $tagobject->taginstancecontextid;
|
||||
$istaginnewcontext = $tagcontextid == $newcontext->id;
|
||||
$istaginquestioncontext = $tagcontextid == $question->contextid;
|
||||
|
||||
if ($istaginnewcontext) {
|
||||
// This tag instance is already in the correct context so we can
|
||||
// ignore it.
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($istaginquestioncontext) {
|
||||
// This tag instance is in the question context so it needs to be
|
||||
// updated.
|
||||
$instancesfornewcontext[] = $tagid;
|
||||
continue;
|
||||
}
|
||||
|
||||
// These tag instances are in neither the new context nor the
|
||||
// question context so we need to determine what to do based on
|
||||
// the context they are in and the new question context.
|
||||
$tagcontext = context::instance_by_id($tagcontextid);
|
||||
$tagcoursecontext = $tagcontext->get_course_context(false);
|
||||
// The tag is in a course context if get_course_context() returns
|
||||
// itself.
|
||||
$istaginstancecontextcourse = !empty($tagcoursecontext)
|
||||
&& $tagcontext->id == $tagcoursecontext->id;
|
||||
|
||||
if ($istaginstancecontextcourse) {
|
||||
// If the tag instance is in a course context we need to add some
|
||||
// special handling.
|
||||
$tagcontextparentids = $tagcontext->get_parent_context_ids();
|
||||
$isnewcontextaparent = in_array($newcontext->id, $tagcontextparentids);
|
||||
$isnewcontextachild = in_array($tagcontext->id, $newcontextparentids);
|
||||
|
||||
if ($isnewcontextaparent) {
|
||||
// If the tag instance is a course context tag and the new
|
||||
// context is still a parent context to the tag context then
|
||||
// we can leave this tag where it is.
|
||||
continue;
|
||||
} else if ($isnewcontextachild) {
|
||||
// If the new context is a child context (e.g. activity) of this
|
||||
// tag instance then we should move all of this tag instance
|
||||
// down into the activity context along with the question.
|
||||
$instancesfornewcontext[] = $tagid;
|
||||
} else {
|
||||
// If the tag is in a course context that is no longer a parent
|
||||
// or child of the new context then this tag instance should be
|
||||
// removed.
|
||||
$instancestodelete[] = $tagid;
|
||||
}
|
||||
} else {
|
||||
// This is a catch all for any tag instances not in the question
|
||||
// context or a course context. These tag instances should be
|
||||
// updated to the new context id. This will clean up old invalid
|
||||
// data.
|
||||
$instancesfornewcontext[] = $tagid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($instancestodelete)) {
|
||||
// Delete any course context tags that may no longer be valid.
|
||||
core_tag_tag::delete_instances_by_id($instancestodelete);
|
||||
}
|
||||
|
||||
if (!empty($instancesfornewcontext)) {
|
||||
// Update the tag instances to the new context id.
|
||||
core_tag_tag::change_instances_context($instancesfornewcontext, $newcontext);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function should be considered private to the question bank, it is called from
|
||||
* question/editlib.php question/contextmoveq.php and a few similar places to to the
|
||||
@ -573,8 +687,8 @@ function question_move_questions_to_category($questionids, $newcategoryid) {
|
||||
$DB->set_field_select('question', 'category', $newcategoryid,
|
||||
"parent $questionidcondition", $params);
|
||||
|
||||
// Update the contextid for any tag instances that may exist for these questions.
|
||||
core_tag_tag::change_items_context('core_question', 'question', $questionids, $newcontextid);
|
||||
$newcontext = context::instance_by_id($newcontextid);
|
||||
question_move_question_tags_to_new_context($questions, $newcontext);
|
||||
|
||||
// TODO Deal with datasets.
|
||||
|
||||
@ -597,6 +711,7 @@ function question_move_questions_to_category($questionids, $newcategoryid) {
|
||||
function question_move_category_to_context($categoryid, $oldcontextid, $newcontextid) {
|
||||
global $DB;
|
||||
|
||||
$questions = [];
|
||||
$questionids = $DB->get_records_menu('question',
|
||||
array('category' => $categoryid), '', 'id,qtype');
|
||||
foreach ($questionids as $questionid => $qtype) {
|
||||
@ -604,10 +719,15 @@ function question_move_category_to_context($categoryid, $oldcontextid, $newconte
|
||||
$questionid, $oldcontextid, $newcontextid);
|
||||
// Purge this question from the cache.
|
||||
question_bank::notify_question_edited($questionid);
|
||||
|
||||
$questions[] = (object) [
|
||||
'id' => $questionid,
|
||||
'contextid' => $oldcontextid
|
||||
];
|
||||
}
|
||||
|
||||
core_tag_tag::change_items_context('core_question', 'question',
|
||||
array_keys($questionids), $newcontextid);
|
||||
$newcontext = context::instance_by_id($newcontextid);
|
||||
question_move_question_tags_to_new_context($questions, $newcontext);
|
||||
|
||||
$subcatids = $DB->get_records_menu('question_categories',
|
||||
array('parent' => $categoryid), '', 'id,1');
|
||||
|
Loading…
x
Reference in New Issue
Block a user