static function CreateAttemptQuestions($ATTEMPT_ID)
{
global $APPLICATION, $DB;
$ATTEMPT_ID = intval($ATTEMPT_ID);
$attempt = CTestAttempt::GetByID($ATTEMPT_ID);
if (!$arAttempt = $attempt->Fetch())
{
$APPLICATION->ThrowException(GetMessage("LEARNING_BAD_ATTEMPT_ID_EX"), "ERROR_NO_ATTEMPT_ID");
return false;
}
$test = CTest::GetByID($arAttempt["TEST_ID"]);
if (!$arTest = $test->Fetch())
{
$APPLICATION->ThrowException(GetMessage("LEARNING_BAD_TEST_ID_EX"), "ERROR_NO_TEST_ID");
return false;
}
$strSql = "DELETE FROM b_learn_test_result WHERE ATTEMPT_ID = ".$ATTEMPT_ID;
if (!$DB->Query($strSql, false, "File: ".__FILE__."
Line: ".__LINE__))
return false;
/**
* QUESTIONS_FROM values:
* 'L' - X questions from every lesson in course
* 'C' - X questions from every lesson from every chapter in the course
* In this case questions taken from immediate lessons of all chapters (X per chapter) in the course.
* In new data model it means, get X questions from every lesson in the course, except
* 1) immediate lessons-childs of the course and
* 2) lessons, contains other lessons (because, in old data model chapters doesn't contains questions)
*
* 'H' - all questions from the selected chapter (recursive) in the course
* This case must be ignored, because converter to new data model updates 'H' to 'R', but in case
* when chapter is not exists updates didn't become. So QUESTIONS_FROM stayed in 'H' value. And it means,
* that there is no chapter exists with QUESTIONS_FROM_ID, so we can't do work. And we should just
* ignore, for backward compatibility (so, don't throw an error).
* 'S' - all questions from the selected lesson (unilesson_id in QUESTIONS_FROM_ID)
* 'A' - all questions of the course (nothing interesting in QUESTIONS_FROM_ID)
*
* new values:
* 'R' - all questions from the tree with root at selected lesson (include questions of selected lesson)
* in the course (unilesson_id in QUESTIONS_FROM_ID)
*/
if ($arTest["QUESTIONS_FROM"] == "C" || $arTest["QUESTIONS_FROM"] == "L")
{
$courseId = $arTest['COURSE_ID'] + 0;
$courseLessonId = CCourse::CourseGetLinkedLesson ($courseId);
if ($courseLessonId === false)
{
$APPLICATION->ThrowException(GetMessage("LEARNING_BAD_TEST_IS_EMPTY"), "ERROR_TEST_IS_EMPTY");
return false;
}
$clauseAllChildsLessons = CLearnHelper::SQLClauseForAllSubLessons ($courseLessonId);
if ($arTest["QUESTIONS_FROM"] == "C") // X questions from every lessons from every chapter in the course
{
$strSql =
"SELECT Q.ID as QUESTION_ID, TLEUP.SOURCE_NODE as FROM_ID
FROM b_learn_lesson L
INNER JOIN b_learn_question Q ON L.ID = Q.LESSON_ID
INNER JOIN b_learn_lesson_edges TLEUP ON L.ID = TLEUP.TARGET_NODE
LEFT OUTER JOIN b_learn_lesson_edges TLEDOWN ON L.ID = TLEDOWN.SOURCE_NODE "
. "WHERE L.ID IN (" . $clauseAllChildsLessons . ") n" // only lessons from COURSE_ID = $arTest['COURSE_ID']
. " AND TLEDOWN.SOURCE_NODE IS NULL n" // exclude lessons, contains other lessons ("chapters")
// include lessons in current course tree context only (and exclude immediate childs of course)
. " AND TLEUP.SOURCE_NODE IN (" . $clauseAllChildsLessons . ") n"
. " AND Q.ACTIVE = 'Y' " // active questions only
. ($arTest["INCLUDE_SELF_TEST"] != "Y" ? "AND Q.SELF = 'N' " : "")
. "ORDER BY ".($arTest["RANDOM_QUESTIONS"] == "Y" ? CTest::GetRandFunction() : "L.SORT, Q.SORT, L.ID");
}
else // 'L' X questions from every lesson in course
{
$strSql =
"SELECT Q.ID as QUESTION_ID, L.ID as FROM_ID ".
"FROM b_learn_lesson L ".
"INNER JOIN b_learn_question Q ON L.ID = Q.LESSON_ID ".
"WHERE L.ID IN (" . $clauseAllChildsLessons . ") AND Q.ACTIVE = 'Y' ".
($arTest["INCLUDE_SELF_TEST"] != "Y" ? "AND Q.SELF = 'N' " : "").
"ORDER BY ".($arTest["RANDOM_QUESTIONS"] == "Y" ? CTest::GetRandFunction() : "L.SORT, Q.SORT, L.ID");
}
if (!$res = $DB->Query($strSql, false, "File: ".__FILE__."
Line: ".__LINE__))
return false;
$Values = Array();
$tmp = Array();
while ($arRecord = $res->Fetch())
{
if (is_set($tmp, $arRecord["FROM_ID"]))
{
if ($tmp[$arRecord["FROM_ID"]] < $arTest["QUESTIONS_AMOUNT"])
$tmp[$arRecord["FROM_ID"]]++;
else
continue;
}
else
{
$tmp[$arRecord["FROM_ID"]] = 1;
}
$Values[]= $arRecord["QUESTION_ID"];
}
if (empty($Values))
{
$APPLICATION->ThrowException(GetMessage("LEARNING_BAD_TEST_IS_EMPTY"), "ERROR_TEST_IS_EMPTY");
return false;
}
$DB->StartTransaction();
foreach ($Values as $ID)
{
$strSql = "INSERT INTO b_learn_test_result (ATTEMPT_ID, QUESTION_ID) VALUES (".$ATTEMPT_ID.",".$ID.")";
if (!$DB->Query($strSql, false, "File: ".__FILE__."
Line: ".__LINE__))
{
$DB->Rollback();
return false;
}
}
$DB->Commit();
}
elseif (($arTest["QUESTIONS_FROM"] == "H" || $arTest["QUESTIONS_FROM"] == "S" || $arTest["QUESTIONS_FROM"] == "R") && $arTest["QUESTIONS_FROM_ID"])
{
$WHERE = '';
if ($arTest["QUESTIONS_FROM"] == "H")
{
/**
* 'H' - all questions from the selected chapter (recursive) in the course
* This case must be ignored, because converter to new data model updates 'H' to 'R', but in case
* when chapter is not exists updates didn't become. So QUESTIONS_FROM stayed in 'H' value. And it means,
* that there is no chapter exists with QUESTIONS_FROM_ID, so we can't do work. And we should just
* ignore, for backward compatibility (so, don't throw an error).
*/
$APPLICATION->ThrowException(GetMessage("LEARNING_BAD_TEST_IS_EMPTY"), "ERROR_TEST_IS_EMPTY");
return false;
}
elseif ($arTest["QUESTIONS_FROM"] == 'R') // all questions from the tree with root at selected lesson (include questions of selected lesson) in the course (unilesson_id in QUESTIONS_FROM_ID)
{
$clauseAllChildsLessons = CLearnHelper::SQLClauseForAllSubLessons ($arTest['QUESTIONS_FROM_ID']);
$WHERE = " (L.ID IN(" . $clauseAllChildsLessons . ") OR (L.ID = " . ($arTest['QUESTIONS_FROM_ID'] + 0) . ")) ";
}
elseif ($arTest["QUESTIONS_FROM"] == 'S') // 'S' - all questions from the selected lesson (unilesson_id in QUESTIONS_FROM_ID)
{
$clauseAllChildsLessons = $arTest["QUESTIONS_FROM_ID"] + 0;
$WHERE = " (L.ID IN(" . $clauseAllChildsLessons . ") OR (L.ID = " . ($arTest['QUESTIONS_FROM_ID'] + 0) . ")) ";
}
else
{
return (false);
}
$strSql =
"SELECT Q.ID AS QUESTION_ID ".
"FROM b_learn_lesson L ".
"INNER JOIN b_learn_question Q ON L.ID = Q.LESSON_ID ".
"WHERE " . $WHERE . " AND Q.ACTIVE = 'Y' ".
($arTest["INCLUDE_SELF_TEST"] != "Y" ? "AND Q.SELF = 'N' " : "").
"ORDER BY ".($arTest["RANDOM_QUESTIONS"] == "Y" ? CTest::GetRandFunction() : "L.SORT, Q.SORT, L.ID ").
($arTest["QUESTIONS_AMOUNT"] > 0 ? "LIMIT ".$arTest["QUESTIONS_AMOUNT"] :"");
$success = false;
$rsQuestions = $DB->Query($strSql, false, "File: ".__FILE__."
Line: ".__LINE__);
$strSql = '';
if ($rsQuestions)
{
$arSqlSubstrings = array();
while ($arQuestion = $rsQuestions->fetch())
$arSqlSubstrings[] = "(" . $ATTEMPT_ID . ", " . $arQuestion['QUESTION_ID'] . ")";
if ( ! empty($arSqlSubstrings) )
$strSql = "INSERT INTO b_learn_test_result (ATTEMPT_ID, QUESTION_ID) VALUES " . implode(",n", $arSqlSubstrings);
if ($strSql !== '')
{
$rc = $DB->Query($strSql, false, "File: ".__FILE__."
Line: ".__LINE__);
if ($rc && intval($rc->AffectedRowsCount()) > 0)
$success = true;
}
}
if ( ! $success )
{
$APPLICATION->ThrowException(GetMessage("LEARNING_BAD_TEST_IS_EMPTY"), "ERROR_TEST_IS_EMPTY");
return false;
}
}
elseif ($arTest["QUESTIONS_FROM"] == 'A')
{
$courseId = $arTest['COURSE_ID'] + 0;
$courseLessonId = CCourse::CourseGetLinkedLesson ($courseId);
if ($courseLessonId === false)
{
$APPLICATION->ThrowException(GetMessage("LEARNING_BAD_TEST_IS_EMPTY"), "ERROR_TEST_IS_EMPTY");
return false;
}
$clauseAllChildsLessons = CLearnHelper::SQLClauseForAllSubLessons ($courseLessonId);
$strSql =
"SELECT Q.ID AS QUESTION_ID
FROM b_learn_lesson L
INNER JOIN b_learn_question Q ON L.ID = Q.LESSON_ID
WHERE (L.ID IN (" . $clauseAllChildsLessons . ") OR (L.ID = " . ($courseLessonId + 0) . ") )
AND Q.ACTIVE = 'Y' "
. ($arTest["INCLUDE_SELF_TEST"] != "Y" ? "AND Q.SELF = 'N' " : "").
"ORDER BY " . ($arTest["RANDOM_QUESTIONS"] == "Y" ? CTest::GetRandFunction() : "L.SORT, Q.SORT, L.ID ").
($arTest["QUESTIONS_AMOUNT"] > 0 ? "LIMIT " . ($arTest["QUESTIONS_AMOUNT"] + 0) : "");
$success = false;
$rsQuestions = $DB->Query($strSql, false, "File: ".__FILE__."
Line: ".__LINE__);
$strSql = '';
if ($rsQuestions)
{
$arSqlSubstrings = array();
while ($arQuestion = $rsQuestions->fetch())
$arSqlSubstrings[] = "(" . $ATTEMPT_ID . ", " . $arQuestion['QUESTION_ID'] . ")";
if ( ! empty($arSqlSubstrings) )
$strSql = "INSERT INTO b_learn_test_result (ATTEMPT_ID, QUESTION_ID) VALUES " . implode(",n", $arSqlSubstrings);
if ($strSql !== '')
{
$rc = $DB->Query($strSql, false, "File: ".__FILE__."
Line: ".__LINE__);
if ($rc && intval($rc->AffectedRowsCount()) > 0)
$success = true;
}
}
if ( ! $success )
{
$APPLICATION->ThrowException(GetMessage("LEARNING_BAD_TEST_IS_EMPTY"), "ERROR_TEST_IS_EMPTY");
return false;
}
}
else
return (false);
$strSql = "UPDATE b_learn_attempt SET QUESTIONS = '".CTestResult::GetCount($ATTEMPT_ID)."' WHERE ID = ".$ATTEMPT_ID;
$DB->Query($strSql, false, "File: ".__FILE__."
Line: ".__LINE__);
return true;
}