/** * Removes all references to the question in executed tests in case the question has been changed. * If a question was changed it cannot be guaranteed that the content and the meaning of the question * is the same as before. So we have to delete all already started or completed tests using that question. * Therefore we have to delete all references to that question in tst_solutions and the tst_active * entries which were created for the user and test in the tst_solutions entry. */ public function removeAllTestEditings($question_id = "") { global $ilDB; // remove the question from tst_solutions if ($question_id) { $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE tst_solutions.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s) AND tst_solutions.question_fi = %s", array('integer', 'integer'), array($this->getTestId(), $question_id)); $affectedRows = $ilDB->manipulateF("DELETE FROM tst_qst_solved WHERE tst_qst_solved.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s) AND tst_qst_solved.question_fi = %s", array('integer', 'integer'), array($this->getTestId(), $question_id)); $affectedRows = $ilDB->manipulateF("DELETE FROM tst_test_result WHERE tst_test_result.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s) AND tst_test_result.question_fi = %s", array('integer', 'integer'), array($this->getTestId(), $question_id)); $affectedRows = $ilDB->manipulateF("DELETE FROM tst_pass_result WHERE tst_pass_result.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s)", array('integer'), array($this->getTestId())); require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php'; ilAssQuestionHintTracking::deleteRequestsByQuestionIds(array($question_id)); } else { $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE tst_solutions.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s)", array('integer'), array($this->getTestId())); $affectedRows = $ilDB->manipulateF("DELETE FROM tst_qst_solved WHERE tst_qst_solved.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s)", array('integer'), array($this->getTestId())); $affectedRows = $ilDB->manipulateF("DELETE FROM tst_test_result WHERE tst_test_result.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s)", array('integer'), array($this->getTestId())); $affectedRows = $ilDB->manipulateF("DELETE FROM tst_pass_result WHERE tst_pass_result.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s)", array('integer'), array($this->getTestId())); $query = "SELECT active_id FROM tst_active WHERE test_fi = %s"; $res = $ilDB->queryF($query, array('integer'), array($this->getTestId())); $activeIds = array(); while ($row = $ilDB->fetchAssoc($res)) { $activeIds[] = $row['active_id']; } require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php'; ilAssQuestionHintTracking::deleteRequestsByActiveIds($activeIds); include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php"; if (ilObjAssessmentFolder::_enabledAssessmentLogging()) { $this->logAction($this->lng->txtlng("assessment", "log_user_data_removed", ilObjAssessmentFolder::_getLogLanguage())); } } $affectedRows = $ilDB->manipulateF("DELETE FROM tst_sequence WHERE tst_sequence.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s)", array('integer'), array($this->getTestId())); if ($this->isRandomTest()) { $affectedRows = $ilDB->manipulateF("DELETE FROM tst_test_rnd_qst WHERE tst_test_rnd_qst.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s)", array('integer'), array($this->getTestId())); } // remove test_active entries, because test has changed $affectedRows = $ilDB->manipulateF("DELETE FROM tst_active WHERE test_fi = %s", array('integer'), array($this->getTestId())); // remove saved user passwords $affectedRows = $ilDB->manipulateF("DELETE FROM usr_pref WHERE keyword = %s", array('text'), array("tst_password_" . $this->getTestId())); // TODO: this shouldn't be here since it is question stuff and should be modular but there's no other solution yet // remove file uploads if (@is_dir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId())) { ilUtil::delDir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId()); } }
/** * Deletes a question and all materials from the database * * @param integer $question_id The database id of the question * @access private */ public function delete($question_id) { global $ilDB, $ilLog; if ($question_id < 1) { return true; } // nothing to do $result = $ilDB->queryF("SELECT obj_fi FROM qpl_questions WHERE question_id = %s", array('integer'), array($question_id)); if ($result->numRows() == 1) { $row = $ilDB->fetchAssoc($result); $obj_id = $row["obj_fi"]; } else { return true; // nothing to do } try { $this->deletePageOfQuestion($question_id); } catch (Exception $e) { $ilLog->write("EXCEPTION: Could not delete page of question {$question_id}: {$e}"); return false; } $affectedRows = $ilDB->manipulateF("DELETE FROM qpl_questions WHERE question_id = %s", array('integer'), array($question_id)); if ($affectedRows == 0) { return false; } try { $this->deleteAdditionalTableData($question_id); $this->deleteAnswers($question_id); $this->feedbackOBJ->deleteGenericFeedbacks($question_id, $this->isAdditionalContentEditingModePageObject()); $this->feedbackOBJ->deleteSpecificAnswerFeedbacks($question_id, $this->isAdditionalContentEditingModePageObject()); } catch (Exception $e) { $ilLog->write("EXCEPTION: Could not delete additional table data of question {$question_id}: {$e}"); return false; } try { // delete the question in the tst_test_question table (list of test questions) $affectedRows = $ilDB->manipulateF("DELETE FROM tst_test_question WHERE question_fi = %s", array('integer'), array($question_id)); } catch (Exception $e) { $ilLog->write("EXCEPTION: Could not delete delete question {$question_id} from a test: {$e}"); return false; } try { // delete suggested solutions contained in the question $affectedRows = $ilDB->manipulateF("DELETE FROM qpl_sol_sug WHERE question_fi = %s", array('integer'), array($question_id)); } catch (Exception $e) { $ilLog->write("EXCEPTION: Could not delete suggested solutions of question {$question_id}: {$e}"); return false; } try { $directory = CLIENT_WEB_DIR . "/assessment/" . $obj_id . "/{$question_id}"; if (preg_match("/\\d+/", $obj_id) and preg_match("/\\d+/", $question_id) and is_dir($directory)) { include_once "./Services/Utilities/classes/class.ilUtil.php"; ilUtil::delDir($directory); } } catch (Exception $e) { $ilLog->write("EXCEPTION: Could not delete question file directory {$directory} of question {$question_id}: {$e}"); return false; } try { include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php"; $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $question_id); // remaining usages are not in text anymore -> delete them // and media objects (note: delete method of ilObjMediaObject // checks whether object is used in another context; if yes, // the object is not deleted!) foreach ($mobs as $mob) { ilObjMediaObject::_removeUsage($mob, "qpl:html", $question_id); if (ilObjMediaObject::_exists($mob)) { $mob_obj =& new ilObjMediaObject($mob); $mob_obj->delete(); } } } catch (Exception $e) { $ilLog->write("EXCEPTION: Error deleting the media objects of question {$question_id}: {$e}"); return false; } require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php'; ilAssQuestionHintTracking::deleteRequestsByQuestionIds(array($question_id)); require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintList.php'; ilAssQuestionHintList::deleteHintsByQuestionIds(array($question_id)); require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionSkillAssignmentList.php'; $assignmentList = new ilAssQuestionSkillAssignmentList($ilDB); $assignmentList->setParentObjId($obj_id); $assignmentList->setQuestionIdFilter($question_id); $assignmentList->loadFromDb(); foreach ($assignmentList->getAssignmentsByQuestionId($question_id) as $assignment) { /* @var ilAssQuestionSkillAssignment $assignment */ $assignment->deleteFromDb(); } try { // update question count of question pool include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php"; ilObjQuestionPool::_updateQuestionCount($this->getObjId()); } catch (Exception $e) { $ilLog->write("EXCEPTION: Error updating the question pool question count of question pool " . $this->getObjId() . " when deleting question {$question_id}: {$e}"); return false; } $this->notifyQuestionDeleted($this); return true; }