In a perfect world, questions that have been part of a Quiz attempt would never be deleted.
But, it's possible, since there are currently no restrictions to prevent that from happening. Usually this happens in testing, but could happen in production.
The issues we have to deal with here are:
1. Users who answered a question in their attempt will no longer have that question, and can't view feedback for it
2. Reporting is affected because a Quiz's score cannot be recalculated
3. Admins may be locked out of certain areas of the site because the system expects an attempt to have all questions.
Issues pop up frequently, this should solve them all:
#2912759: HTTP 500 and "Undefined property: MultichoiceResponse::$result_answer_id" after editing question
#2884069: 500 ajax error path:/system/ajax
#2402535: Disabling a quiz question type module leaves quizes with an existing question of that type unusable
I believe the solution here is to prevent deletion of questions unless they are:
1. Not in any quiz, or quiz revision
2. Not in any attempt's layout
| Comment | File | Size | Author |
|---|---|---|---|
| #15 | quiz-2923829-15-2.patch | 1.02 KB | fox mulder |
| #15 | quiz-2923829-15-1.patch | 471 bytes | fox mulder |
Issue fork quiz-2923829
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
djdevinComment #3
webservant316 commentedAgreed.
Comment #4
moxwai commentedHi There, is there any work around for this issue?
Comment #5
snehalgaikwad commentedI am using Quiz with 6.0.0-alpha4 version, facing the same issue. Requirement is to prevent deletion of questions while being used in quiz. Updating version of this issue.
Comment #6
webservant316 commentedI am reminded of this issue because I am building a function to change the node authorship of a course node and all associated content which includes course object nodes, book child pages, and also Quiz question nodes. So while looping through the Questions in the quiz_node_relationship table I discovered numerous entries for Question nodes that no longer exist, yet the entry in the quiz_node_relationship remains. This is in Quiz 7.x-5.7, but I assume the same would be true in Quiz 7.x-6.x.
Above we suggest not allowing the deletion of Quiz Questions if they are in use. However, would it also be possible to instead remove the Question from all Quiz revisions and Quiz results? That would be cleaner.
Also in my case I have deleted Quiz Questions that I no longer need. I don't think there will be any problem observed by students or admin for current and future takes and results of the Quiz. However, if a Question is deleted from a previous revision of the Quiz will there usability breaking events? What would happen if a student tried to view the results of a old Quiz revision that has a deleted Question?
Comment #7
djdevinWhat other systems do:
https://docs.moodle.org/35/en/Building_Quiz
> If one or more students have taken the quiz, you will see a list of all the questions in the quiz and a notice saying that you cannot add or remove questions.
https://help.blackboard.com/Learn/Instructor/Tests_Pools_Surveys/Edit_Te...
> At the top of the page, you're alerted that you can't delete questions if a test or survey has attempts in progress.
"Delete and regrade" seems to be the only reasonable option here that we could implement: #3196826: How can I re-grade questions?
Comment #8
webservant316 commentedOh yeah. Regrading would be needed. Wow way complicated.
First thing would be to just prevent deleting Quiz Questions if they are in use, as previously mentioned.
Who knows if there will be time and patience to work out the removal of a Question from previous Quiz revisions and regrading. And in the case of Quizzes that provide students with certifications it is even more complicated. What if their score changed from pass to fail? A web admin might not notice the impacts.
Comment #9
smustgrave commentedComment #10
smustgrave commentedWhat if we just alter the options and if hasAttempts() is true don't include Remove button.
And we could update the help text at the bottom?
Comment #13
smustgrave commentedThat's what I ended up going with.
Comment #15
fox mulder commentedThe fix in this issue addresses two things: it hides the "Remove" button in the quiz questions UI when a quiz has attempts, and it adds a continue guard in QuizQuestionsForm.php to silently skip already-orphaned records when rendering the questions management form.
However, there is still a gap: questions can be deleted through their own entity delete form (/quiz-question/{id}/delete), which is an entirely separate code path that has no hasAttempts() check. This means the orphaned record scenario can still occur in 7.1.1 — it just requires going directly to the question's delete page instead of using the quiz questions management UI.
When that happens, the site will crash with a TypeError on the quiz view page (/quiz/{id}):
TypeError: QuizQuestionRelationship::getQuestion(): Return value must be of type RevisionableInterface, null returned in QuizQuestionRelationship.php:137
The backtrace goes through QuizViewBuilder::buildStatsComponent() -> Quiz::getNumberOfQuestions() -> QuizQuestionRelationship::getQuestion().
Unlike QuizQuestionsForm.php, QuizViewBuilder has no null guard for orphaned relationships — and the null guard in Quiz.php:722 (if ($quizQuestion = $relationship->getQuestion())) never gets a chance to run, because PHP throws the TypeError first due to the non-nullable return type declaration.
Two additional fixes are proposed:
Patch 1 — getQuestion() should return ?RevisionableInterface instead of RevisionableInterface, since loadRevision() can legitimately return null and callers already handle it.
Patch 2 — the question entity delete form should be blocked when the question is assigned to a quiz that already has attempts, by implementing hook_ENTITY_TYPE_access() in quiz.module.