function CheckFields(&$arFields, $ID = false) { global $DB, $APPLICATION; if ($ID === false && !is_set($arFields, "STUDENT_ID")) { $APPLICATION->ThrowException(GetMessage("LEARNING_BAD_USER_ID"), "EMPTY_STUDENT_ID"); return false; } elseif (is_set($arFields, "STUDENT_ID")) { $dbResult = CUser::GetByID($arFields["STUDENT_ID"]); if (!$dbResult->Fetch()) { $APPLICATION->ThrowException(GetMessage("LEARNING_BAD_USER_ID_EX"), "ERROR_NO_STUDENT_ID"); return false; } } if ($ID === false && !is_set($arFields, "TEST_ID")) { $APPLICATION->ThrowException(GetMessage("LEARNING_BAD_TEST_ID"), "EMPTY_TEST_ID"); return false; } elseif (is_set($arFields, "TEST_ID")) { $r = CTest::GetByID($arFields["TEST_ID"]); if (!$r->Fetch()) { $APPLICATION->ThrowException(GetMessage("LEARNING_BAD_TEST_ID_EX"), "ERROR_NO_TEST_ID"); return false; } } if (is_set($arFields, "STUDENT_ID") && is_set($arFields, "TEST_ID")) { $res = CGradeBook::GetList(array(), array("STUDENT_ID" => $arFields["STUDENT_ID"], "TEST_ID" => $arFields["TEST_ID"])); if ($res->Fetch()) { $APPLICATION->ThrowException(GetMessage("LEARNING_BAD_GRADEBOOK_DUPLICATE"), "ERROR_GRADEBOOK_DUPLICATE"); return false; } } if (is_set($arFields, "COMPLETED") && $arFields["COMPLETED"] != "Y") { $arFields["COMPLETED"] = "N"; } return true; }
public static function _CreateAttemptQuestionsSQLFormer($ATTEMPT_ID, $arTest, $clauseAllChildsLessons, $courseLessonId) { $strSql = "INSERT INTO b_learn_test_result (ATTEMPT_ID, QUESTION_ID) SELECT " . ($ATTEMPT_ID + 0) . " ,Q.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() : "Q.SORT "). ($arTest["QUESTIONS_AMOUNT"] > 0 ? "LIMIT " . ($arTest["QUESTIONS_AMOUNT"] + 0) : ""); return ($strSql); }
<?php if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) { die; } if (!CModule::IncludeModule("learning")) { return; } $arCourses = array(); $courses = CCourse::GetList(array("SORT" => "ASC")); while ($arRes = $courses->Fetch()) { $arCourses[$arRes["ID"]] = $arRes["NAME"]; } $arTests = array(); if ($arCurrentValues["COURSE_ID"] && intval($arCurrentValues["COURSE_ID"]) > 0) { $rsTest = CTest::GetList(array("SORT" => "ASC"), array("ACTIVE" => "Y", "COURSE_ID" => $arCurrentValues["COURSE_ID"])); while ($arTest = $rsTest->GetNext()) { $arTests[$arTest["ID"]] = "[" . $arTest["ID"] . "] " . $arTest["NAME"]; } } $arComponentParameters = array("PARAMETERS" => array("COURSE_ID" => array("NAME" => GetMessage("LEARNING_COURSE_ID"), "TYPE" => "LIST", "VALUES" => $arCourses, "PARENT" => "BASE", "ADDITIONAL_VALUES" => "Y", "REFRESH" => "Y", "DEFAULT" => '={$_REQUEST["COURSE_ID"]}'), "TEST_ID" => array("NAME" => GetMessage("T_LEARNING_DETAIL_ID"), "TYPE" => "LIST", "VALUES" => $arTests, "ADDITIONAL_VALUES" => "Y", "PARENT" => "BASE", "DEFAULT" => '={$_REQUEST["TEST_ID"]}'), "PAGE_NUMBER_VARIABLE" => array("NAME" => GetMessage("T_LEARNING_PAGE_NUMBER_VARIABLE"), "TYPE" => "STRING", "PARENT" => "ADDITIONAL_SETTINGS", "DEFAULT" => 'PAGE'), "GRADEBOOK_TEMPLATE" => array("NAME" => GetMessage("LEARNING_GRADEBOOK_TEMPLATE_NAME"), "TYPE" => "STRING", "PARENT" => "URL_TEMPLATES", "DEFAULT" => '../gradebook.php?TEST_ID=#TEST_ID#', "COLS" => 45), "PAGE_WINDOW" => array("NAME" => GetMessage("LEARNING_PAGE_WINDOW_NAME"), "TYPE" => "STRING", "PARENT" => "ADDITIONAL_SETTINGS", "DEFAULT" => '10'), "SHOW_TIME_LIMIT" => array("NAME" => GetMessage("LEARNING_SHOW_TIME_LIMIT"), "TYPE" => "CHECKBOX", "PARENT" => "ADDITIONAL_SETTINGS", "DEFAULT" => "Y"), "SET_TITLE" => array()));
public function BuildList() { global $USER; $filterParams = GetFilterParams('filter_'); // list's footer $this->oList->AddFooter(array(array('title' => GetMessage('MAIN_ADMIN_LIST_SELECTED'), 'value' => $this->rsData->SelectedRowsCount()), array('counter' => true, 'title' => GetMessage('MAIN_ADMIN_LIST_CHECKED'), 'value' => '0'))); $oParentPath = new CLearnPath(); if (isset($_GET['LESSON_PATH'])) { $oParentPath->ImportUrlencoded($_GET['LESSON_PATH']); } $arParentPath = $oParentPath->GetPathAsArray(); // building list while ($arRes = $this->rsData->NavNext(false)) { $oCurPath = new CLearnPath(); $oCurPath->SetPathFromArray(array_merge($arParentPath, array($arRes['LESSON_ID']))); $urlCurPath = $oCurPath->ExportUrlencoded(); unset($oCurPath); // PUBLISH_PROHIBITED available in context of most parent course only if ($this->contextCourseLessonId !== false) { $arRes['PUBLISH_PROHIBITED'] = 'N'; if (CLearnLesson::IsPublishProhibited($arRes['LESSON_ID'], $this->contextCourseLessonId)) { $arRes['PUBLISH_PROHIBITED'] = 'Y'; } } $arRes['SITE_ID'] = ''; $courseId = CLearnLesson::GetLinkedCourse($arRes['LESSON_ID']); if ($courseId !== false) { $hrefPrefix = 'learn_course_edit.php?COURSE_ID=' . $courseId; $resCourseSites = CCourse::GetSite($courseId); while ($arCourseSites = $resCourseSites->Fetch()) { if ($arRes['SITE_ID'] != '') { $arRes['SITE_ID'] .= ' / '; } $arRes['SITE_ID'] .= htmlspecialcharsbx($arCourseSites['LID']); } } else { $hrefPrefix = 'learn_unilesson_edit.php?LESSON_ID=' . $arRes['LESSON_ID'] . '&LESSON_PATH=' . urlencode($urlCurPath); } $actionEditLesson = $hrefPrefix . '&lang=' . LANG . $filterParams; $rowAction = false; $rowTitle = ''; if (!$this->IsSearchMode()) { $rowAction = 'learn_unilesson_admin.php?lang=' . LANG . '&set_filter=Y' . '&PARENT_LESSON_ID=' . ($arRes['LESSON_ID'] + 0) . '&LESSON_PATH=' . $urlCurPath . '&' . $this->hrefSearchRetPoint; $rowTitle = GetMessage('LEARNING_TRAVERSE'); // "Traverse list of immediate childs" if (!$arRes['IS_CHILDS']) { $rowAction = $actionEditLesson; $rowTitle = GetMessage('LEARNING_EDIT_TITLE'); } } $row =& $this->oList->AddRow($arRes['LESSON_ID'], $arRes, $rowAction, $rowTitle); $arParents = $arChilds = array(); $htmlParents = $htmlChilds = ''; $rsParents = CLearnLesson::GetListOfImmediateParents($arRes['LESSON_ID'], array(), array('CHECK_PERMISSIONS' => 'N')); while ($arParent = $rsParents->Fetch()) { $arParents[] = $arParent['NAME']; } $arParents = array_map('htmlspecialcharsbx', $arParents); if (count($arParents) > 0) { $htmlParents = implode('<hr width="100%" size="1">', $arParents); } else { $htmlParents = ' '; } $rsChilds = CLearnLesson::GetListOfImmediateChilds($arRes['LESSON_ID'], array(), array('CHECK_PERMISSIONS' => 'N')); while ($arChild = $rsChilds->Fetch()) { $arChilds[] = $arChild['NAME']; } $arChilds = array_map('htmlspecialcharsbx', $arChilds); if (count($arChilds) > 0) { $htmlChilds = implode('<hr width="100%" size="1">', $arChilds); } else { $htmlChilds = ' '; } if (isset($arRes['LINKED_LESSON_ID']) && $arRes['LINKED_LESSON_ID'] > 0) { $icon = 'learning_icon_courses'; } elseif (count($arChilds) > 0) { $icon = 'learning_icon_chapters'; } else { $icon = 'learning_icon_lessons'; } if (!$this->IsSearchMode()) { $row->AddViewField('NAME', '<span class="adm-list-table-icon-link"><span class="adm-submenu-item-link-icon adm-list-table-icon ' . $icon . '"></span>' . ($rowAction === false ? '<span class="adm-list-table-link">' . htmlspecialcharsbx($arRes['NAME']) . '</span>' : '<a href="' . $rowAction . '" class="adm-list-table-link">' . htmlspecialcharsbx($arRes['NAME']) . '</a>') . '</span>'); } else { $actionUseLesson = "(function()\n\t\t\t\t\t{\n\t\t\t\t\t\tvar fnName = '" . str_replace(array("'", ';', ',', "\n", "\r"), '', htmlspecialcharsbx($this->search_retpoint)) . "';\n\t\t\t\t\t\tif ( ! (window.opener && window.opener[fnName]) )\n\t\t\t\t\t\t\treturn;\n\n\t\t\t\t\t\twindow.opener[fnName]('" . (int) $arRes['LESSON_ID'] . "', '" . CUtil::JSEscape(htmlspecialcharsbx($arRes['NAME'])) . "');\n\t\t\t\t\t\twindow.close();\n\t\t\t\t\t})();\n\t\t\t\t\t"; $row->AddViewField('NAME', '<a href="javascript:void(0);" class="adm-list-table-icon-link" onclick="' . $actionUseLesson . '"><span class="adm-submenu-item-link-icon adm-list-table-icon ' . $icon . '"></span><span class="adm-list-table-link">' . htmlspecialcharsbx($arRes['NAME']) . '</span></a>'); } $row->AddViewField('PARENTS', $htmlParents); $row->AddEditField('PARENTS', ' '); $row->AddViewField('CHILDS', $htmlChilds); $row->AddEditField('CHILDS', ' '); // this is very heavy statistic, so will be a good idea to add settings to the module, which turn off this statistics $oLearnTree = CLearnLesson::GetTree($arRes['LESSON_ID']); $arTree = $oLearnTree->GetTreeAsList(); $depth = -1; $chapterCount = 0; $lessonsCount = 0; $questionsCount = CLQuestion::GetCount(array('LESSON_ID' => (int) $arRes['LESSON_ID'])); foreach ($arTree as $arLessonData) { if ($arLessonData['IS_CHILDS']) { ++$chapterCount; } else { ++$lessonsCount; } if ((int) $arLessonData['#DEPTH_IN_TREE'] > $depth) { $depth = (int) $arLessonData['#DEPTH_IN_TREE']; } $questionsCount += CLQuestion::GetCount(array('LESSON_ID' => (int) $arLessonData['LESSON_ID'])); } // PUBLISH_PROHIBITED available in context of most parent course only if ($this->contextCourseLessonId !== false) { if ($this->IsLessonUpdateAccess($arRes['LESSON_ID']) === true) { $row->AddInputField('PUBLISH_PROHIBITED', array('size' => '35')); $row->AddCheckField('PUBLISH_PROHIBITED'); } else { $row->AddCheckField('PUBLISH_PROHIBITED', true); } } // Render CARDINALITY fields $htmlDepth = (int) ($depth + 1); $htmlChapters = (string) (int) $chapterCount . ' [<a href="learn_unilesson_edit.php?lang=' . LANG . '&PROPOSE_RETURN_LESSON_PATH=' . $urlCurPath . '" title="' . GetMessage('LEARNING_UNILESSON_ADD') . '"' . '>+</a>]'; $htmlLessons = (string) (int) $lessonsCount . ' [<a href="learn_unilesson_edit.php?lang=' . LANG . '&PROPOSE_RETURN_LESSON_PATH=' . $urlCurPath . '" title="' . GetMessage('LEARNING_UNILESSON_ADD') . '"' . '>+</a>]'; $htmlQuestions = '<a href="learn_question_admin.php?lang=' . LANG . '&filter=Y&set_filter=Y' . '&PARENT_LESSON_ID=' . ($arRes['LESSON_ID'] + 0) . '&LESSON_PATH=' . $urlCurPath . '" title="' . GetMessage('LEARNING_QUESTION_ALT') . '">' . (int) $questionsCount . '</a>' . ' [' . '<a href="learn_question_edit.php?lang=' . LANG . '&LESSON_PATH=' . $urlCurPath . '&QUESTION_TYPE=S' . '&filter=Y&set_filter=Y' . '&from=learn_menu"' . ' title="' . GetMessage('LEARNING_QUESTION_ADD') . '">+</a>' . ']'; $row->AddViewField('CARDINALITY_DEPTH', $htmlDepth); $row->AddViewField('CARDINALITY_CHAPTERS', $htmlChapters); $row->AddViewField('CARDINALITY_LESSONS', $htmlLessons); $row->AddViewField('CARDINALITY_QUESTIONS', $htmlQuestions); if ($courseId !== false) { $testsCount = (int) CTest::GetCount(array('COURSE_ID' => $courseId)); $htmlTests = '<a href="learn_test_admin.php?lang=' . LANG . '&COURSE_ID=' . $courseId . '&PARENT_LESSON_ID=' . (int) $arRes['LESSON_ID'] . '&LESSON_PATH=' . $urlCurPath . '&filter=Y&set_filter=Y"' . '>' . $testsCount . '</a>' . ' [<a href="learn_test_edit.php?lang=' . LANG . '&COURSE_ID=' . $courseId . '&PARENT_LESSON_ID=' . (int) $arRes['LESSON_ID'] . '&LESSON_PATH=' . $urlCurPath . '&filter=Y&set_filter=Y" title="' . GetMessage('LEARNING_QUESTION_ADD') . '"' . '>+</a>]'; $row->AddViewField('CARDINALITY_TESTS', $htmlTests); } if (!$this->IsSearchMode() && $this->IsLessonUpdateAccess($arRes['LESSON_ID']) === true) { $row->AddInputField('NAME', array('size' => '35')); // SORT field editing possibly only for courses and for lessons in relation to parent lesson if ($this->IsListChildLessonsMode() || $this->IsListAnyCoursesMode()) { $row->AddInputField('SORT', array('size' => '3')); } $row->AddCheckField('ACTIVE'); $row->AddInputField('CODE'); } else { $row->AddCheckField('ACTIVE', false); } $row->AddViewField('CREATED_USER_NAME', $arRes['CREATED_USER_NAME']); $arActions = array(); if (!$this->IsSearchMode()) { if ($this->IsLessonUpdateAccess($arRes['LESSON_ID']) === true) { $editTxt = GetMessage('MAIN_ADMIN_MENU_EDIT'); } else { $editTxt = GetMessage('MAIN_ADMIN_MENU_OPEN'); } // Actions $arActions[] = array('ICON' => 'edit', 'TEXT' => $editTxt, 'ACTION' => $this->oList->ActionRedirect($actionEditLesson)); $arActions[] = array("SEPARATOR" => true); $arActions[] = array('ICON' => 'list', 'TEXT' => GetMessage('LEARNING_QUESTION_ALT') . ' (' . ($questionsCount + 0) . ')', 'ACTION' => $this->oList->ActionRedirect('learn_question_admin.php?lang=' . LANG . '&filter=Y&set_filter=Y' . '&PARENT_LESSON_ID=' . ($arRes['LESSON_ID'] + 0) . '&LESSON_PATH=' . urlencode($urlCurPath))); /* $arActions[] = array( "ICON"=>"copy", "TEXT"=>GetMessage("MAIN_ADMIN_ADD_COPY"), "ACTION"=>$this->oList->ActionRedirect("learn_course_edit.php?COPY_ID=".$f_ID)); */ $isDeleteCmdDisabled = true; $isDisbandCmdDisabled = true; $deleteMSG = ''; $disbandMSG = ''; $actionDisband = ''; $action = ''; if ($arRes['CHILDS_CNT'] > 0) { $deleteMSG = GetMessage('LEARNING_ADMIN_MENU_DELETE_RECURSIVE') . ' (' . (string) (int) $arRes['CHILDS_CNT'] . ')'; } else { $deleteMSG = GetMessage("MAIN_ADMIN_MENU_DELETE"); } $disbandMSG = GetMessage('LEARNING_ADMIN_MENU_DISBAND'); $isEnoughRightsForDisbandLesson = false; try { $this->EnsureLessonDisbandAccess($arRes['LESSON_ID']); $isEnoughRightsForDisbandLesson = true; } catch (CLearnRenderAdminUnilessonListException $e) { if ($e->GetCode() & CLearnRenderAdminUnilessonListException::C_ACCESS_DENIED) { } else { // bubble exception throw new CLearnRenderAdminUnilessonListException($e->GetMessage(), $e->GetCode()); } } // If we can unlink all neighbours and remove lesson if ($isEnoughRightsForDisbandLesson) { $arOPathes = CLearnLesson::GetListOfParentPathes($arRes['LESSON_ID']); $parentPathesCnt = count($arOPathes); // prepare "Disband" command $isDisbandCmdDisabled = false; $actionDisband = $this->oList->ActionDoGroup($arRes['LESSON_ID'], 'disband', 'PARENT_LESSON_ID=' . ($this->requestedParentLessonId + 0)); if ($parentPathesCnt >= 1) { $actionDisband = "if(confirm('" . str_replace('#CNT#', $parentPathesCnt, GetMessageJS('LEARNING_CONFIRM_DISBAND_LESSON_WITH_PARENT_PATHES')) . "')) " . '{ ' . $actionDisband . ' }'; } $actionDisband = "if(confirm('" . GetMessageJS('LEARNING_ADMIN_MENU_DISBAND_QUESTION') . "')) " . '{ ' . $actionDisband . ' }'; // prepare "Remove" command $isDeleteCmdDisabled = false; if ($arRes['CHILDS_CNT'] > 0) { $action = $this->oList->ActionDoGroup($arRes['LESSON_ID'], 'recursive_delete', 'PARENT_LESSON_ID=' . ($this->requestedParentLessonId + 0)); } else { // If no childs => "delete" is equal to "disband" $action = $this->oList->ActionDoGroup($arRes['LESSON_ID'], 'disband', 'PARENT_LESSON_ID=' . ($this->requestedParentLessonId + 0)); } if ($parentPathesCnt >= 1) { $deleteMSG .= ' [' . $parentPathesCnt . ']'; $action = "if(confirm('" . str_replace('#CNT#', $parentPathesCnt, GetMessageJS("LEARNING_CONFIRM_DEL_LESSON_WITH_PARENT_PATHES")) . "')) " . $action; } else { $action = "if(confirm('" . GetMessageJS('LEARNING_CONFIRM_DEL_MESSAGE') . "')) " . $action; } } // We can "disband" only lessons, that contains childs $arActions[] = array("SEPARATOR" => true); if ($arRes['CHILDS_CNT'] > 0) { $arActions[] = array('ICON' => 'delete', 'TEXT' => $disbandMSG, 'ACTION' => $actionDisband, 'DISABLED' => $isDisbandCmdDisabled, 'TITLE' => GetMessage('LEARNING_ADMIN_MENU_DISBAND_TITLE')); } $arActions[] = array('ICON' => 'delete', 'TEXT' => $deleteMSG, 'ACTION' => $action, 'DISABLED' => $isDeleteCmdDisabled); } else { $arActions[] = array('ICON' => 'list', 'TEXT' => GetMessage('LEARNING_SELECT'), 'ACTION' => $actionUseLesson); } $row->AddActions($arActions); } return $this; }
protected static function _CreateAttemptQuestions($arCallbackSqlFormer, $ATTEMPT_ID) { global $APPLICATION, $DB, $DBType; $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__ . "<br>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") { $strSql = "SELECT Q.ID as QUESTION_ID, TLEUP.SOURCE_NODE as FROM_ID\n\t\t\t\tFROM b_learn_lesson L\n\t\t\t\tINNER JOIN b_learn_question Q ON L.ID = Q.LESSON_ID\n\t\t\t\tINNER JOIN b_learn_lesson_edges TLEUP ON L.ID = TLEUP.TARGET_NODE\n\t\t\t\tLEFT OUTER JOIN b_learn_lesson_edges TLEDOWN ON L.ID = TLEDOWN.SOURCE_NODE " . "WHERE L.ID IN (" . $clauseAllChildsLessons . ") \n" . " AND TLEDOWN.SOURCE_NODE IS NULL \n" . " AND TLEUP.SOURCE_NODE IN (" . $clauseAllChildsLessons . ") \n" . " 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"); } else { $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"); } if (!($res = $DB->Query($strSql, false, "File: " . __FILE__ . "<br>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__ . "<br>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') { $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') { $clauseAllChildsLessons = $arTest["QUESTIONS_FROM_ID"] + 0; $WHERE = " (L.ID IN(" . $clauseAllChildsLessons . ") OR (L.ID = " . ($arTest['QUESTIONS_FROM_ID'] + 0) . ")) "; } else { return false; } $strSql = "INSERT INTO b_learn_test_result (ATTEMPT_ID, QUESTION_ID) " . "SELECT " . $ATTEMPT_ID . " ,Q.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() : "Q.SORT ") . ($arTest["QUESTIONS_AMOUNT"] > 0 ? "LIMIT " . $arTest["QUESTIONS_AMOUNT"] : ""); //echo $strSql;exit; $q = $DB->Query($strSql, false, "File: " . __FILE__ . "<br>Line: " . __LINE__); if (!$q || intval($q->AffectedRowsCount()) <= 0) { $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 = call_user_func($arCallbackSqlFormer, $ATTEMPT_ID, $arTest, $clauseAllChildsLessons, $courseLessonId); //echo $strSql; exit; $q = $DB->Query($strSql, false, "File: " . __FILE__ . "<br>Line: " . __LINE__); if (!$q || intval($q->AffectedRowsCount()) <= 0) { $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__ . "<br>Line: " . __LINE__); return true; }
function GetList($arOrder = array(), $arFilter = array()) { global $DB, $USER; if (!is_array($arFilter)) { $arFilter = array(); } $oPermParser = new CLearnParsePermissionsFromFilter($arFilter); $arSqlSearch = CTest::GetFilter($arFilter); $strSqlSearch = ""; for ($i = 0; $i < count($arSqlSearch); $i++) { if (strlen($arSqlSearch[$i]) > 0) { $strSqlSearch .= " AND " . $arSqlSearch[$i] . " "; } } $strSql = "SELECT DISTINCT T.*, " . $DB->DateToCharFunction("T.TIMESTAMP_X") . " as TIMESTAMP_X " . "FROM b_learn_test T " . "INNER JOIN b_learn_course C ON T.COURSE_ID = C.ID " . "WHERE 1=1 "; if ($oPermParser->IsNeedCheckPerm()) { $strSql .= " AND C.LINKED_LESSON_ID IN (" . $oPermParser->SQLForAccessibleLessons() . ") "; } $strSql .= $strSqlSearch; /* was: $bCheckPerm = ($APPLICATION->GetUserRight("learning") < "W" && !$USER->IsAdmin() && $arFilter["CHECK_PERMISSIONS"] != "N"); $userID = $USER->GetID() ? $USER->GetID() : 0; $strSql = "SELECT DISTINCT T.*, ". $DB->DateToCharFunction("T.TIMESTAMP_X")." as TIMESTAMP_X ". "FROM b_learn_test T ". "INNER JOIN b_learn_course C ON T.COURSE_ID = C.ID ". ($bCheckPerm ? "LEFT JOIN b_learn_course_permission CP ON CP.COURSE_ID = C.ID " : ""). "WHERE 1=1 ". ($bCheckPerm ? "AND CP.USER_GROUP_ID IN (".$USER->GetGroups().") ". "AND CP.PERMISSION >= '".(strlen($arFilter["MIN_PERMISSION"])==1 ? $arFilter["MIN_PERMISSION"] : "R")."' ". "AND (CP.PERMISSION='X' OR C.ACTIVE='Y') " :""). $strSqlSearch; */ if (!is_array($arOrder)) { $arOrder = array(); } foreach ($arOrder as $by => $order) { $by = strtolower($by); $order = strtolower($order); if ($order != "asc") { $order = "desc"; } if ($by == "id") { $arSqlOrder[] = " T.ID " . $order . " "; } elseif ($by == "name") { $arSqlOrder[] = " T.NAME " . $order . " "; } elseif ($by == "active") { $arSqlOrder[] = " T.ACTIVE " . $order . " "; } elseif ($by == "sort") { $arSqlOrder[] = " T.SORT " . $order . " "; } else { $arSqlOrder[] = " T.TIMESTAMP_X " . $order . " "; $by = "timestamp_x"; } } $strSqlOrder = ""; DelDuplicateSort($arSqlOrder); for ($i = 0; $i < count($arSqlOrder); $i++) { if ($i == 0) { $strSqlOrder = " ORDER BY "; } else { $strSqlOrder .= ","; } $strSqlOrder .= $arSqlOrder[$i]; } $strSql .= $strSqlOrder; //echo $strSql; return $DB->Query($strSql, false, "File: " . __FILE__ . "<br>Line: " . __LINE__); }
$arContent["SELECTED"] = _IsItemSelected(array($itemURL, $selftestURL)); $lessonCount++; } if ($arContent["SELECTED"]) { $lessonCurrent = $lessonCount; } $arResult["ITEMS"][] = $arContent; } //Page Properties $APPLICATION->SetPageProperty("learning_course_name", $arResult["COURSE"]["NAME"]); $APPLICATION->SetPageProperty("learning_lesson_count", $lessonCount); $APPLICATION->SetPageProperty("learning_lesson_current", $lessonCurrent); //Test list item $url = CComponentEngine::MakePathFromTemplate($arParams["TESTS_LIST_TEMPLATE"], array("COURSE_ID" => $arParams["COURSE_ID"])); $arSelectedItems = array($url); $rsTest = CTest::GetList(array(), array("COURSE_ID" => $arParams["COURSE_ID"], "ACTIVE" => "Y")); $rsTest->NavStart(100); while ($arTest = $rsTest->Fetch()) { $arSelectedItems[] = CComponentEngine::MakePathFromTemplate($arParams["TEST_DETAIL_TEMPLATE"], array("TEST_ID" => $arTest["ID"], "COURSE_ID" => $arParams["COURSE_ID"])); } $arResult["ITEMS"][] = array("NAME" => GetMessage('LEARNING_TEST_LIST') . " (" . $rsTest->SelectedRowsCount() . ")", "URL" => $url, "TYPE" => "TL", "SELECTED" => _IsItemSelected($arSelectedItems), "DEPTH_LEVEL" => 1); unset($arContent); unset($rsContent); //Open chapters from Cookies $arOpenChapters = array(); if (array_key_exists("LEARN_MENU_" . $arParams["COURSE_ID"], $_COOKIE)) { $arOpenChapters = split(",", $_COOKIE["LEARN_MENU_" . $arParams["COURSE_ID"]]); } //Chapter open if child selected for ($itemIndex = 0, $size = count($arResult["ITEMS"]); $itemIndex < $size; $itemIndex++) { if ($arResult["ITEMS"][$itemIndex]["TYPE"] != "CH" || $arResult["ITEMS"][$itemIndex]["SELECTED"] === true) {
/** * <p>Возвращает количество тестов по заданному фильтру.</p> * * * * * @param array $arrayarFilter = Array() Массив вида <i> array("фильтруемое поле"=>"значение фильтра" [, ...])</i>. * Описание фильтра см. в <a * href="http://dev.1c-bitrix.ru/api_help/learning/classes/ctest/getlist.php">CTest::GetList</a>.<br> По * умолчанию тесты не фильтруются. * * * * @return int <p>Число - количество тестов.</p> * * * <h4>Example</h4> * <pre> * <? * if (CModule::IncludeModule("learning")) * { * $COURSE_ID = 97; * * $cnt = CTest::GetCount(Array("ACTIVE" => "Y", "COURSE_ID" => $COURSE_ID)); * * echo "Number of tests: ".$cnt; * } * * ?> * * <? * if (CModule::IncludeModule("learning")) * { * $COURSE_ID = 97; * * $cnt = CTest::GetCount(Array("CHECK_PERMISSIONS" => "N", "COURSE_ID" => $COURSE_ID)); * * echo "Number of tests: ".$cnt; * } * * ?> * </pre> * * * * <h4>See Also</h4> * <ul> <li> <a href="http://dev.1c-bitrix.ru/api_help/learning/classes/ctest/index.php">CTest</a>::<a * href="http://dev.1c-bitrix.ru/api_help/learning/classes/ctest/getlist.php">GetList</a> </li> </ul><a * name="examples"></a> * * * @static * @link http://dev.1c-bitrix.ru/api_help/learning/classes/ctest/getcount.php * @author Bitrix */ public static function GetCount($arFilter = Array()) { global $DB, $USER, $APPLICATION; if (!is_array($arFilter)) $arFilter = Array(); $oPermParser = new CLearnParsePermissionsFromFilter ($arFilter); $arSqlSearch = CTest::GetFilter($arFilter); $strSqlSearch = ""; for($i=0; $i<count($arSqlSearch); $i++) if(strlen($arSqlSearch[$i])>0) $strSqlSearch .= " AND ".$arSqlSearch[$i]." "; $strSql = "SELECT COUNT(*) as CNT FROM b_learn_test T INNER JOIN b_learn_course C ON T.COURSE_ID = C.ID WHERE 1=1"; if ($oPermParser->IsNeedCheckPerm()) $strSql .= " AND C.LINKED_LESSON_ID IN (" . $oPermParser->SQLForAccessibleLessons() . ") "; $strSql .= $strSqlSearch; /* was: $strSql = "SELECT COUNT(*) as CNT ". "FROM b_learn_test T ". "INNER JOIN b_learn_course C ON T.COURSE_ID = C.ID ". ($bCheckPerm ? "LEFT JOIN b_learn_course_permission CP ON CP.COURSE_ID = C.ID " : ""). "WHERE 1=1 ". ($bCheckPerm ? "AND CP.USER_GROUP_ID IN (".$USER->GetGroups().") ". "AND CP.PERMISSION >= '".(strlen($arFilter["MIN_PERMISSION"])==1 ? $arFilter["MIN_PERMISSION"] : "R")."' ". "AND (CP.PERMISSION='X' OR C.ACTIVE='Y')" :""). $strSqlSearch; */ $res = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__); if ($ar = $res->Fetch()) return intval($ar["CNT"]); else return 0; }
if (!CModule::IncludeModule("learning")) { ShowError(GetMessage("LEARNING_MODULE_NOT_FOUND")); return; } $arParams["COURSE_ID"] = isset($arParams["COURSE_ID"]) && intval($arParams["COURSE_ID"]) > 0 ? intval($arParams["COURSE_ID"]) : intval($_REQUEST["COURSE_ID"]); $arParams["TEST_DETAIL_TEMPLATE"] = strlen($arParams["TEST_DETAIL_TEMPLATE"]) > 0 ? htmlspecialchars($arParams["TEST_DETAIL_TEMPLATE"]) : 'test.php?TEST_ID=#TEST#'; $arParams["CHECK_PERMISSIONS"] = isset($arParams["CHECK_PERMISSIONS"]) && $arParams["CHECK_PERMISSIONS"] == "N" ? "N" : "Y"; $arParams["TESTS_PER_PAGE"] = intval($arParams["TESTS_PER_PAGE"]) > 0 ? intval($arParams["TESTS_PER_PAGE"]) : 20; //Title $arParams["SET_TITLE"] = $arParams["SET_TITLE"] == "N" ? "N" : "Y"; if ($arParams["SET_TITLE"] == "Y") { $APPLICATION->SetTitle(GetMessage("LEARNING_TESTS_LIST")); } //arResult $arResult = array("TESTS" => array(), "TESTS_COUNT" => 0, "ERROR_MESSAGE" => "", "NAV_SRTING" => "", "NAV_RESULT" => null); $rsTest = CTest::GetList(array("SORT" => "ASC"), array("COURSE_ID" => $arParams["COURSE_ID"], "ACTIVE" => "Y", "CHECK_PERMISSIONS" => $arParams["CHECK_PERMISSIONS"])); CPageOption::SetOptionString("main", "nav_page_in_session", "N"); $rsTest->NavStart($arParams["TESTS_PER_PAGE"]); $arResult["NAV_STRING"] = $rsTest->GetPageNavString(GetMessage("LEARNING_TESTS_NAV")); $arResult["NAV_RESULT"] = $rsTest; while ($arTest = $rsTest->GetNext()) { //Test URL $arTest["TEST_DETAIL_URL"] = CComponentEngine::MakePathFromTemplate($arParams["TEST_DETAIL_TEMPLATE"], array("TEST_ID" => $arTest["ID"], "COURSE_ID" => $arTest["COURSE_ID"])); if ($_SERVER['REDIRECT_STATUS'] == '404' || isset($_REQUEST["SEF_APPLICATION_CUR_PAGE_URL"])) { $arTest["TEST_DETAIL_URL"] = "/bitrix/urlrewrite.php?SEF_APPLICATION_CUR_PAGE_URL=" . urlencode($arTest["TEST_DETAIL_URL"]); } //Unfinished attempt exists? $arTest["ATTEMPT"] = false; if ($USER->IsAuthorized()) { $rsAttempt = CTestAttempt::GetList(array(), array("TEST_ID" => $arTest["ID"], "STATUS" => "B", "STUDENT_ID" => intval($USER->GetID()))); $arTest["ATTEMPT"] = $rsAttempt->GetNext();
protected function _MakeItems($TITLE, $TYPE, $RES_ID, $PARENT_ID) { global $APPLICATION; if ($PARENT_ID === 0) { $linkToParentLessonId = CCourse::CourseGetLinkedLesson($this->COURSE_ID); } else { $linkToParentLessonId = (int) $PARENT_ID; } $createUnilesson = false; if ($TYPE == "LES") { $arFields = array('NAME' => $TITLE); $createUnilesson = true; } elseif ($TYPE == "CHA") { $arFields = array('NAME' => $TITLE); $createUnilesson = true; } elseif ($TYPE == "QUE") { $arFields = array("NAME" => $TITLE, "LESSON_ID" => $linkToParentLessonId); $cl = new CLQuestion(); } elseif ($TYPE == "TES") { $arFields = array("NAME" => $TITLE, "COURSE_ID" => $this->COURSE_ID); $cl = new CTest(); } elseif ($TYPE === 'TMK') { $arFields = array(); $cl = new CLTestMark(); } else { return $PARENT_ID; } $r = new CDataXML(); if (!$r->Load($this->package_dir . "/" . strtolower($RES_ID) . ".xml")) { $r = false; } if ($r !== false) { if ($TYPE == "QUE") { if (($data = $r->SelectNodes("/questestinterop/item/presentation/")) && ($resp = $r->SelectNodes("/questestinterop/item/resprocessing/"))) { $arQ = array(); $arData = $data->__toArray(); $arResp = $resp->__toArray(); if (is_set($arData["#"]["material"][0]["#"], "mattext")) { $arQ["NAME"] = $arData["#"]["material"][0]["#"]["mattext"][0]["#"]; } if (is_set($arData["#"]["material"][0]["#"], "matimage")) { $imageDescription = ''; if (is_set($arData["#"]["material"][0]["#"], 'image_description')) { $imageDescription = $arData["#"]["material"][0]["#"]['image_description'][0]['#']; } $arQ["FILE_ID"] = array("MODULE_ID" => "learning", "name" => basename($arData["#"]["material"][0]["#"]["matimage"][0]["@"]["uri"]), "tmp_name" => $this->package_dir . "/" . $arData["#"]["material"][0]["#"]["matimage"][0]["@"]["uri"], "size" => @filesize($this->package_dir . "/" . $arData["#"]["material"][0]["#"]["matimage"][0]["@"]["uri"]), "type" => $arData["#"]["material"][0]["#"]["matimage"][0]["@"]["imagtype"], 'description' => $imageDescription); } if (is_set($arData["#"]["response_lid"][0]["@"], "rcardinality")) { switch ($arData["#"]["response_lid"][0]["@"]["rcardinality"]) { case "Multiple": $arQ["QUESTION_TYPE"] = 'M'; break; case "Text": $arQ["QUESTION_TYPE"] = 'T'; break; case "Sort": $arQ["QUESTION_TYPE"] = 'R'; break; default: $arQ["QUESTION_TYPE"] = 'S'; break; } } if (is_set($arResp["#"]["respcondition"][0]["#"], "setvar")) { $arQ["POINT"] = $arResp["#"]["respcondition"][0]["#"]["setvar"][0]['#']; } //Additional if ($bx = $r->SelectNodes("/questestinterop/item/bitrix/")) { $arQ = array_merge($arQ, $this->_MakeFields($bx->__toArray(), $TYPE)); unset($bx); } $arFields = array_merge($arFields, $arQ); $cl = new CLQuestion(); $ID = $cl->Add($arFields); if ($ID > 0) { $PARENT_ID = $ID; $arCorrect = array(); if (is_set($arResp["#"]["respcondition"][0]["#"], "conditionvar") && is_set($arResp["#"]["respcondition"][0]["#"]["conditionvar"][0]["#"], "varequal")) { foreach ($arResp["#"]["respcondition"][0]["#"]["conditionvar"][0]["#"]["varequal"] as $ar) { $arCorrect[] = $ar["#"]; } } if (is_set($arData["#"]["response_lid"][0]["#"], "render_choice") && is_set($arData["#"]["response_lid"][0]["#"]["render_choice"][0]["#"], "response_label")) { $i = 0; foreach ($arData["#"]["response_lid"][0]["#"]["render_choice"][0]["#"]["response_label"] as $ar) { $i += 10; $cl = new CLAnswer(); $arFields = array("QUESTION_ID" => $PARENT_ID, "SORT" => $i, "CORRECT" => in_array($ar["@"]["ident"], $arCorrect) ? "Y" : "N", "ANSWER" => $ar["#"]["material"][0]["#"]["mattext"][0]["#"]); $AswerID = $cl->Add($arFields); $res = $AswerID > 0; if (!$res) { if ($e = $APPLICATION->GetException()) { $this->arWarnings[$TYPE][] = array("TITLE" => $TITLE, "TEXT" => $e->GetString()); } } } } } else { if ($e = $APPLICATION->GetException()) { $this->arWarnings[$TYPE][] = array("TITLE" => $TITLE, "TEXT" => $e->GetString()); } } unset($cl); unset($data); unset($arQ); unset($resp); unset($arData); unset($arResp); return $PARENT_ID; } } else { if ($data = $r->SelectNodes("/content/")) { $ar = $data->__toArray(); $arFields = array_merge($arFields, $this->_MakeFields($ar, $TYPE)); if ($TYPE === 'TMK') { $arFields['TEST_ID'] = (int) $PARENT_ID; } if (is_set($arFields, "COMPLETED_SCORE") && intval($arFields["COMPLETED_SCORE"]) <= 0) { unset($arFields["COMPLETED_SCORE"]); } if (is_set($arFields, "PREVIOUS_TEST_ID") && intval($arFields["PREVIOUS_TEST_ID"]) <= 0 || !CTest::GetByID($arFields["PREVIOUS_TEST_ID"])->Fetch()) { unset($arFields["PREVIOUS_TEST_ID"], $arFields["PREVIOUS_TEST_SCORE"]); } } } } if ($createUnilesson === false) { $ID = $cl->Add($arFields); unset($cl); } else { $bProhibitPublish = false; // properties (in context of parent) by default $arProperties = array('SORT' => 500); // Lesson's sort order in context of parent if (isset($arFields['EDGE_SORT'])) { $arFields['SORT'] = (int) $arFields['EDGE_SORT']; unset($arFields['EDGE_SORT']); } if (isset($arFields['SORT'])) { $arProperties['SORT'] = (int) $arFields['SORT']; // Lessons doesn't have more SORT field unset($arFields['SORT']); } if (isset($arFields['META_PUBLISH_PROHIBITED'])) { if ($arFields['META_PUBLISH_PROHIBITED'] === 'Y') { $bProhibitPublish = true; } unset($arFields['META_PUBLISH_PROHIBITED']); } // unset fields, that are absent in unilesson $arUnilessonFields = $arFields; $arFieldsNames = array_keys($arUnilessonFields); foreach ($arFieldsNames as $fieldName) { if (!in_array(strtoupper($fieldName), $this->arLessonWritableFields)) { unset($arUnilessonFields[$fieldName]); } } $ID = CLearnLesson::Add($arUnilessonFields, false, $linkToParentLessonId, $arProperties); if ($bProhibitPublish && $ID > 0) { CLearnLesson::PublishProhibitionSetTo($ID, $linkToParentLessonId, $bProhibitPublish); } } if ($ID > 0) { return $ID; } else { if ($e = $APPLICATION->GetException()) { $this->arWarnings[$TYPE][] = array("TITLE" => $TITLE, "TEXT" => $e->GetString()); } } }
function GetList($arOrder = array(), $arFilter = array()) { global $DB, $USER; $arSqlSearch = CLTestMark::GetFilter($arFilter); $strSqlSearch = ""; for ($i = 0; $i < count($arSqlSearch); $i++) { if (strlen($arSqlSearch[$i]) > 0) { $strSqlSearch .= " AND " . $arSqlSearch[$i] . " "; } } $strSql = "SELECT TM.* " . "FROM b_learn_test_mark TM " . "WHERE 1=1 " . $strSqlSearch; if (!is_array($arOrder)) { $arOrder = array(); } foreach ($arOrder as $by => $order) { $by = strtolower($by); $order = strtolower($order); if ($order != "asc") { $order = "desc"; } if ($by == "id") { $arSqlOrder[] = " TM.ID " . $order . " "; } elseif ($by == "mark") { $arSqlOrder[] = " TM.MARK " . $order . " "; } elseif ($by == "score") { $arSqlOrder[] = " TM.SCORE " . $order . " "; } elseif ($by == "rand") { $arSqlOrder[] = CTest::GetRandFunction(); } else { $arSqlOrder[] = " TM.ID " . $order . " "; $by = "id"; } } $strSqlOrder = ""; DelDuplicateSort($arSqlOrder); for ($i = 0; $i < count($arSqlOrder); $i++) { if ($i == 0) { $strSqlOrder = " ORDER BY "; } else { $strSqlOrder .= ","; } $strSqlOrder .= $arSqlOrder[$i]; } $strSql .= $strSqlOrder; //echo $strSql; return $DB->Query($strSql, false, "File: " . __FILE__ . "<br>Line: " . __LINE__); }
/** * <p>Возвращает список вопросов плана тестирования по фильтру <b>arFilter</b>, отсортированный в порядке <b>arOrder</b>.</p> * * * @param array $arrayarOrder = Array("ID"=>"DESC") Массив для сортировки результата. Массив вида <i>array("поле * сортировки"=>"направление сортировки" [, ...])</i>.<br>Поле для * сортировки может принимать значения: <ul> <li> <b>ID</b> - идентификатор * вопроса в плане тестирования; </li> <li> <b>ATTEMPT_ID</b> - идентификатор * попытки; </li> <li> <b>QUESTION_ID</b> - идентификатор вопроса; </li> <li> <b>POINT</b> - * количество баллов; </li> <li> <b>ANSWERED</b> - вопрос отвечен (Y|N); </li> <li> * <b>CORRECT</b> - вопрос правильно отвечен (Y|N); </li> <li> <b>QUESTION_NAME</b> - * название вопроса; </li> <li> <b>RAND</b> - случайный порядок. </li> * </ul>Направление сортировки может принимать значения: <ul> <li> <b>asc</b> - * по возрастанию; </li> <li> <b>desc</b> - по убыванию; </li> </ul>Необязательный. * По умолчанию сортируется по убыванию идентификатора вопроса в * плане тестирования. * * @param array $arrayarFilter = Array() Массив вида <i>array("фильтруемое поле"=>"значение фильтра" [, ...])</i>. * Фильтруемое поле может принимать значения: <ul> <li> <b>ID</b> - * идентификатор вопроса в плане тестирования; </li> <li> <b>ATTEMPT_ID</b> - * идентификатор попытки; </li> <li> <b>QUESTION_ID</b> - идентификатор вопроса; * </li> <li> <b>POINT</b> - количество баллов; </li> <li> <b>RESPONSE</b> - ответ учащегося * (можно искать по шаблону [%_]); </li> <li> <b>QUESTION_NAME</b> - название вопроса * (можно искать по шаблону [%_]); </li> <li> <b>ANSWERED</b> - вопрос отвечен (Y|N); * </li> <li> <b>CORRECT</b> - вопрос правильно отвечен (Y|N). </li> </ul>Перед * названием фильтруемого поля может указать тип фильтрации: <ul> <li>"!" * - не равно </li> <li>"<" - меньше </li> <li>"<=" - меньше либо равно </li> <li>">" * - больше </li> <li>">=" - больше либо равно </li> </ul> <br>"<i>значения * фильтра</i>" - одиночное значение или массив.<br><br>Необязательный. По * умолчанию записи не фильтруются. * * @return CDBResult <p>Возвращается объект <a * href="http://dev.1c-bitrix.ru/api_help/main/reference/cdbresult/index.php">CDBResult</a>.</p> </h * * <h4>Example</h4> * <pre> * <? * if (CModule::IncludeModule("learning")) * { * $ATTEMPT_ID = 590; * $res = CTestResult::GetList( * Array("ID" => "ASC"), * Array("ANSWERED" => "N", "ATTEMPT_ID" => $ATTEMPT_ID) * ); * * while ($arQuestionPlan = $res->GetNext()) * { * echo "Question ID: ".$arQuestionPlan["QUESTION_ID"].<br> "; Correct answer: ".$arQuestionPlan["CORRECT"].<br> "; Question name:".$arQuestionPlan["QUESTION_NAME"]."<b * </pre> * * * <h4>See Also</h4> * <ul> <li> <a href="http://dev.1c-bitrix.ru/api_help/main/reference/cdbresult/index.php">CDBResult</a> </li> <li> <a * href="index.php">CTestResult</a>::<a href="getbyid.php">GetByID</a> </li> <li><a * href="../../fields.php#test_result">Поля плана тестирования</a></li> </ul> <a name="examples"></a> * * * @static * @link http://dev.1c-bitrix.ru/api_help/learning/classes/ctestresult/getlist.php * @author Bitrix */ public static function GetList($arOrder = array(), $arFilter = array(), $arNavParams = array()) { global $DB, $USER, $APPLICATION; if (!is_array($arFilter)) { $arFilter = array(); } $oPermParser = new CLearnParsePermissionsFromFilter($arFilter); $arSqlSearch = CTestResult::GetFilter($arFilter); // Remove empty strings from array $arSqlSearch = array_filter($arSqlSearch); if ($oPermParser->IsNeedCheckPerm()) { $arSqlSearch[] = " L.ID IN (" . $oPermParser->SQLForAccessibleLessons() . ") "; } $strSqlSearch = ' '; if (!empty($arSqlSearch)) { $strSqlSearch = ' WHERE '; $strSqlSearch .= implode(' AND ', $arSqlSearch); } $strSqlFrom = "FROM b_learn_test_result TR \n\t\t\tINNER JOIN b_learn_question Q ON TR.QUESTION_ID = Q.ID \n\t\t\tINNER JOIN b_learn_lesson L ON Q.LESSON_ID = L.ID " . $strSqlSearch; $strSql = "SELECT TR.*, Q.QUESTION_TYPE, Q.NAME as QUESTION_NAME, \n\t\t\tQ.POINT as QUESTION_POINT, Q.LESSON_ID " . $strSqlFrom; if (!is_array($arOrder)) { $arOrder = array(); } foreach ($arOrder as $by => $order) { $by = strtolower($by); $order = strtolower($order); if ($order != "asc") { $order = "desc"; } if ($by == "id") { $arSqlOrder[] = " TR.ID " . $order . " "; } elseif ($by == "attempt_id") { $arSqlOrder[] = " TR.ATTEMPT_ID " . $order . " "; } elseif ($by == "question_id") { $arSqlOrder[] = " TR.QUESTION_ID " . $order . " "; } elseif ($by == "point") { $arSqlOrder[] = " TR.POINT " . $order . " "; } elseif ($by == "correct") { $arSqlOrder[] = " TR.CORRECT " . $order . " "; } elseif ($by == "answered") { $arSqlOrder[] = " TR.ANSWERED " . $order . " "; } elseif ($by == "question_name") { $arSqlOrder[] = " QUESTION_NAME " . $order . " "; } elseif ($by == "rand") { $arSqlOrder[] = CTest::GetRandFunction(); } else { $arSqlOrder[] = " TR.ID " . $order . " "; $by = "id"; } } $strSqlOrder = ""; DelDuplicateSort($arSqlOrder); $arSqlOrderCnt = count($arSqlOrder); for ($i = 0; $i < $arSqlOrderCnt; $i++) { if ($i == 0) { $strSqlOrder = " ORDER BY "; } else { $strSqlOrder .= ","; } $strSqlOrder .= $arSqlOrder[$i]; } $strSql .= $strSqlOrder; if (is_array($arNavParams) && !empty($arNavParams)) { if (isset($arNavParams['nTopCount']) && (int) $arNavParams['nTopCount'] > 0) { $strSql = $DB->TopSql($strSql, (int) $arNavParams['nTopCount']); $res = $DB->Query($strSql, false, "File: " . __FILE__ . "<br>Line: " . __LINE__); } else { $res_cnt = $DB->Query("SELECT COUNT(TR.ID) as C " . $strSqlFrom); $res_cnt = $res_cnt->fetch(); $res = new CDBResult(); $res->NavQuery($strSql, $res_cnt['C'], $arNavParams); } } else { $res = $DB->Query($strSql, false, "File: " . __FILE__ . "<br>Line: " . __LINE__); } return $res; }
$rsPrevTest = CTest::GetList(array(), array("ID" => $arTest["PREVIOUS_TEST_ID"], 'CHECK_PERMISSIONS' => 'N')); if ($arPrevTest = $rsPrevTest->GetNext()) { if ($parent = $this->GetParent()) { $testUrlTemplate = CComponentEngine::MakePathFromTemplate($parent->arResult["URL_TEMPLATES"]["test"], array("TEST_ID" => $arPrevTest["ID"], "COURSE_ID" => $arPrevTest["COURSE_ID"])); $arTest["PREVIOUS_TEST_LINK"] = "<a href=\"" . $testUrlTemplate . "\">" . $arPrevTest["NAME"] . "</a>"; } } } } if ($USER->GetID()) { $arTest["ATTEMPT_LIMIT"] += CGradeBook::GetExtraAttempts($USER->GetID(), $arParams["TEST_ID"]); } $oAccess = CLearnAccess::GetInstance($USER->GetID()); $isRelativelyHighAccessLevel = $oAccess->IsBaseAccess(CLearnAccess::OP_LESSON_CREATE | CLearnAccess::OP_LESSON_READ | CLearnAccess::OP_LESSON_WRITE | CLearnAccess::OP_LESSON_REMOVE); $bCheckPerm = !$isRelativelyHighAccessLevel && !$USER->IsAdmin(); if ($bCheckPerm && $arTest["PREVIOUS_TEST_ID"] > 0 && $arTest["PREVIOUS_TEST_SCORE"] > 0 && !CTest::isPrevPassed($arTest["PREVIOUS_TEST_ID"], $arTest["PREVIOUS_TEST_SCORE"])) { if ($arTest["PREVIOUS_TEST_LINK"]) { $errors[] = str_replace("#TEST_LINK#", "\"" . $arTest["PREVIOUS_TEST_LINK"] . "\"", GetMessage("LEARNING_TEST_DENIED_PREVIOUS")); } } //Session variables $userID = $USER->GetID() ? $USER->GetID() : 0; $sessAttemptID =& $_SESSION["LEARN_" . $arParams["TEST_ID"] . "_ATTEMPT_ID_" . $userID]; $sessAttemptFinished =& $_SESSION["LEARN_" . $arParams["TEST_ID"] . "_FINISHED_" . $userID]; $sessAttemptError =& $_SESSION["LEARN_" . $arParams["TEST_ID"] . "_ERROR_" . $userID]; $sessAttempt =& $_SESSION["LEARN_" . $arParams["TEST_ID"] . "_COMPLETED_" . $userID]; $sessIncorrectMessage =& $_SESSION["LEARN_" . $arParams["TEST_ID"] . "_INCORRECT_MESSAGE_" . $userID]; //Page url template $currentPage = GetPagePath(false, false); $queryString = htmlspecialcharsbx(DeleteParam(array($arParams["PAGE_NUMBER_VARIABLE"], "SEF_APPLICATION_CUR_PAGE_URL"))); $pageTemplate = $queryString == "" ? $currentPage . "?" . $arParams["PAGE_NUMBER_VARIABLE"] . "=#PAGE_ID#" : $currentPage . "?" . $queryString . "&" . $arParams["PAGE_NUMBER_VARIABLE"] . "=#PAGE_ID#";
//Set Title $arParams["SET_TITLE"] = $arParams["SET_TITLE"] == "N" ? "N" : "Y"; if ($arParams["SET_TITLE"] == "Y") { $APPLICATION->SetTitle(GetMessage("LEARNING_PROFILE_TITLE")); } $currentPage = GetPagePath(false, false); $queryString = htmlspecialcharsbx(DeleteParam(array($arParams["TEST_ID_VARIABLE"]))); $arResult = array("RECORDS" => array(), "ATTEMPTS" => array(), "CURRENT_PAGE" => $currentPage . ($queryString == "" ? "" : "?") . $queryString); //GradeBook $rsGradebook = CGradeBook::GetList(array("ID" => "DESC"), array("STUDENT_ID" => intval($USER->GetID()), "SITE_ID" => LANG, "TEST_ID" => array_key_exists($arParams["TEST_ID_VARIABLE"], $_REQUEST) ? intval($_REQUEST[$arParams["TEST_ID_VARIABLE"]]) : "")); // Collection of tests' ids $arTestsIds = array(); while ($arGradebook = $rsGradebook->GetNext()) { //Test Url $arGradebook["TEST_DETAIL_URL"] = CComponentEngine::MakePathFromTemplate($arParams["TEST_DETAIL_TEMPLATE"], array("TEST_ID" => $arGradebook["TEST_ID"], "COURSE_ID" => $arGradebook["COURSE_ID"])); $rsTest = CTest::GetByID($arGradebook["TEST_ID"]); $arTest = $rsTest->Fetch(); $arGradebook['APPROVED'] = $arTest['APPROVED']; //Course Url $arGradebook["COURSE_DETAIL_URL"] = CComponentEngine::MakePathFromTemplate($arParams["COURSE_DETAIL_TEMPLATE"], array("COURSE_ID" => $arGradebook["COURSE_ID"])); $arGradebook["ATTEMPT_DETAIL_URL"] = $arResult["CURRENT_PAGE"] . ($queryString == "" ? "?" : "&") . $arParams["TEST_ID_VARIABLE"] . "=" . $arGradebook["TEST_ID"]; $arResult["RECORDS"][] = $arGradebook; // collect tests' ids if (!in_array($arGradebook['TEST_ID'], $arTestsIds)) { $arTestsIds[] = $arGradebook['TEST_ID']; } } // Add info about last tests' attempts for each test $arResult['LAST_TEST_INFO'] = array(); foreach ($arTestsIds as $key => $testId) { $arAttempt = false;
if (isset($arTest['DESCRIPTION'])) { $arTest['DESCRIPTION'] = CLearnHelper::PatchLessonContentLinks($arTest['DESCRIPTION'], $arParams['COURSE_ID']); } //Test URL $arTest["TEST_DETAIL_URL"] = CComponentEngine::MakePathFromTemplate($arParams["TEST_DETAIL_TEMPLATE"], array("TEST_ID" => $arTest["ID"], "COURSE_ID" => $arTest["COURSE_ID"])); if ($_SERVER['REDIRECT_STATUS'] == '404' || isset($_REQUEST["SEF_APPLICATION_CUR_PAGE_URL"])) { $arTest["TEST_DETAIL_URL"] = "/bitrix/urlrewrite.php?SEF_APPLICATION_CUR_PAGE_URL=" . urlencode($arTest["TEST_DETAIL_URL"]); } //Unfinished attempt exists? $arTest["ATTEMPT"] = false; if ($USER->IsAuthorized()) { $rsAttempt = CTestAttempt::GetList(array(), array("TEST_ID" => $arTest["ID"], "STATUS" => "B", "STUDENT_ID" => intval($USER->GetID()), "CHECK_PERMISSIONS" => $arParams["CHECK_PERMISSIONS"])); $arTest["ATTEMPT"] = $rsAttempt->GetNext(); } if ($arTest["PREVIOUS_TEST_ID"] > 0 && $arTest["PREVIOUS_TEST_SCORE"] > 0) { $rsPrevTest = CTest::GetList(array(), array("ID" => $arTest["PREVIOUS_TEST_ID"], 'CHECK_PERMISSIONS' => 'N')); if ($arPrevTest = $rsPrevTest->GetNext()) { if ($parent = $this->GetParent()) { $testUrlTemplate = CComponentEngine::MakePathFromTemplate($parent->arResult["URL_TEMPLATES"]["test"], array("TEST_ID" => $arPrevTest["ID"], "COURSE_ID" => $arPrevTest["COURSE_ID"])); $arTest["PREVIOUS_TEST_LINK"] = "<a href=\"" . $testUrlTemplate . "\">" . $arPrevTest["NAME"] . "</a>"; } } } $arResult["TESTS"][] = $arTest; } $arResult["TESTS_COUNT"] = count($arResult["TESTS"]); if ($arResult["TESTS_COUNT"] <= 0) { $arResult["ERROR_MESSAGE"] = GetMessage("LEARNING_BAD_TEST_LIST"); } unset($rsTest); unset($arTest);
public static function GetList($arOrder = array(), $arFilter = array(), $arNavParams = array()) { global $DB, $USER; if (!is_array($arFilter)) { $arFilter = array(); } $oPermParser = new CLearnParsePermissionsFromFilter($arFilter); $arSqlSearch = CTest::GetFilter($arFilter); // Remove empty strings from array $arSqlSearch = array_filter($arSqlSearch); if ($oPermParser->IsNeedCheckPerm()) { $arSqlSearch[] = " C.LINKED_LESSON_ID IN (" . $oPermParser->SQLForAccessibleLessons() . ") "; } $strSqlSearch = ' '; if (!empty($arSqlSearch)) { $strSqlSearch = ' WHERE '; $strSqlSearch .= implode(' AND ', $arSqlSearch); } $strSqlFrom = "FROM b_learn_test LT " . "INNER JOIN b_learn_course C ON LT.COURSE_ID = C.ID " . $strSqlSearch; $strSql = "SELECT LT.ID, LT.COURSE_ID, LT.SORT, LT.ACTIVE, LT.NAME, \n\t\t\t\tLT.DESCRIPTION, LT.DESCRIPTION_TYPE, LT.ATTEMPT_LIMIT, \n\t\t\t\tLT.TIME_LIMIT, LT.COMPLETED_SCORE, LT.QUESTIONS_FROM, \n\t\t\t\tLT.QUESTIONS_FROM_ID, LT.QUESTIONS_AMOUNT, LT.RANDOM_QUESTIONS, \n\t\t\t\tLT.RANDOM_ANSWERS, LT.APPROVED, LT.INCLUDE_SELF_TEST, \n\t\t\t\tLT.PASSAGE_TYPE, LT.PREVIOUS_TEST_ID, LT.PREVIOUS_TEST_SCORE, \n\t\t\t\tLT.INCORRECT_CONTROL, LT.CURRENT_INDICATION, \n\t\t\t\tLT.FINAL_INDICATION, LT.MIN_TIME_BETWEEN_ATTEMPTS, \n\t\t\t\tLT.SHOW_ERRORS, LT.NEXT_QUESTION_ON_ERROR, " . $DB->DateToCharFunction("LT.TIMESTAMP_X") . " as TIMESTAMP_X " . $strSqlFrom; if (!is_array($arOrder)) { $arOrder = array(); } foreach ($arOrder as $by => $order) { $by = strtolower($by); $order = strtolower($order); if ($order != "asc") { $order = "desc"; } if ($by == "id") { $arSqlOrder[] = " LT.ID " . $order . " "; } elseif ($by == "name") { $arSqlOrder[] = " LT.NAME " . $order . " "; } elseif ($by == "active") { $arSqlOrder[] = " LT.ACTIVE " . $order . " "; } elseif ($by == "sort") { $arSqlOrder[] = " LT.SORT " . $order . " "; } else { $arSqlOrder[] = " LT.TIMESTAMP_X " . $order . " "; $by = "timestamp_x"; } } $strSqlOrder = ""; DelDuplicateSort($arSqlOrder); if (!empty($arSqlOrder)) { $strSqlOrder .= ' ORDER BY ' . implode(', ', $arSqlOrder) . ' '; } $strSql .= $strSqlOrder; if (is_array($arNavParams) && !empty($arNavParams)) { if (isset($arNavParams['nTopCount']) && (int) $arNavParams['nTopCount'] > 0) { $strSql = $DB->TopSql($strSql, (int) $arNavParams['nTopCount']); $res = $DB->Query($strSql, false, "File: " . __FILE__ . "<br>Line: " . __LINE__); } else { $res_cnt = $DB->Query("SELECT COUNT(LT.ID) as C " . $strSqlFrom); $res_cnt = $res_cnt->fetch(); $res = new CDBResult(); $res->NavQuery($strSql, $res_cnt['C'], $arNavParams); } } else { $res = $DB->Query($strSql, false, "File: " . __FILE__ . "<br>Line: " . __LINE__); } return $res; }
} $itemURL .= 'LESSON_PATH=' . $arContent['~#LESSON_PATH']; } $arContent["URL"] = htmlspecialcharsbx($itemURL); if ($arContent["SELECTED"]) { $lessonCurrent = $lessonCount; } $arResult["ITEMS"][] = $arContent; } //Page Properties $APPLICATION->SetPageProperty("learning_course_name", $arResult["COURSE"]["NAME"]); $APPLICATION->SetPageProperty("learning_lesson_count", $lessonCount); $APPLICATION->SetPageProperty("learning_lesson_current", $lessonCurrent); //Test list item $url = CComponentEngine::MakePathFromTemplate($arParams["TESTS_LIST_TEMPLATE"], array("COURSE_ID" => $arParams["COURSE_ID"])); $testsCount = CTest::GetCount(array("COURSE_ID" => $arParams["COURSE_ID"], "ACTIVE" => "Y", 'CHECK_PERMISSIONS' => 'N')); if ($testsCount > 0) { $arResult['ITEMS'][] = array('NAME' => GetMessage('LEARNING_TEST_LIST') . ' (' . $testsCount . ')', 'URL' => $url, 'TYPE' => 'TL', 'SELECTED' => $parent->arResult['VARIABLES']['TEST_LIST'] == 'Y', 'DEPTH_LEVEL' => 1); } unset($arContent); unset($rsContent); //Open chapters from Cookies $arOpenChapters = array(); if (array_key_exists("LEARN_MENU_" . $arParams["COURSE_ID"], $_COOKIE)) { $arOpenChapters = explode(",", $_COOKIE["LEARN_MENU_" . $arParams["COURSE_ID"]]); } //Chapter open if child selected for ($itemIndex = 0, $size = count($arResult["ITEMS"]); $itemIndex < $size; $itemIndex++) { if ($arResult["ITEMS"][$itemIndex]["TYPE"] != "CH" || $arResult["ITEMS"][$itemIndex]["SELECTED"] === true) { continue; }
$itemURL .= 'LESSON_PATH=' . $arContent['~#LESSON_PATH']; } $arContent["URL"] = htmlspecialcharsbx($itemURL); if ($arContent["SELECTED"]) { $lessonCurrent = $lessonCount; } $arResult["ITEMS"][] = $arContent; } //Page Properties $APPLICATION->SetPageProperty("learning_course_name", $arResult["COURSE"]["NAME"]); $APPLICATION->SetPageProperty("learning_lesson_count", $lessonCount); $APPLICATION->SetPageProperty("learning_lesson_current", $lessonCurrent); //Test list item $url = CComponentEngine::MakePathFromTemplate($arParams["TESTS_LIST_TEMPLATE"], array("COURSE_ID" => $arParams["COURSE_ID"])); $arSelectedItems = array($url); $rsTest = CTest::GetList(array(), array("COURSE_ID" => $arParams["COURSE_ID"], "ACTIVE" => "Y", 'CHECK_PERMISSIONS' => 'N')); $rsTest->NavStart(100); while ($arTest = $rsTest->Fetch()) { $arSelectedItems[] = CComponentEngine::MakePathFromTemplate($arParams["TEST_DETAIL_TEMPLATE"], array("TEST_ID" => $arTest["ID"], "COURSE_ID" => $arParams["COURSE_ID"])); } if ($rsTest->SelectedRowsCount() > 0) { $arResult["ITEMS"][] = array("NAME" => GetMessage('LEARNING_TEST_LIST') . " (" . $rsTest->SelectedRowsCount() . ")", "URL" => $url, "TYPE" => "TL", "SELECTED" => $parent->arResult["VARIABLES"]["TEST_LIST"] == "Y", "DEPTH_LEVEL" => 1); } unset($arContent); unset($rsContent); //Open chapters from Cookies $arOpenChapters = array(); if (array_key_exists("LEARN_MENU_" . $arParams["COURSE_ID"], $_COOKIE)) { $arOpenChapters = explode(",", $_COOKIE["LEARN_MENU_" . $arParams["COURSE_ID"]]); } //Chapter open if child selected
$str_FINAL_RESPONSE = "Y"; $str_PASSAGE_TYPE = "0"; $str_PREVIOUS_TEST_ID = "0"; $str_PREVIOUS_TEST_SCORE = "95"; $str_INCORRECT_CONTROL = "N"; $str_CURRENT_INDICATION_PERCENT = "N"; $str_CURRENT_INDICATION_MARK = "N"; $str_CURRENT_INDICATION = "N"; $str_FINAL_INDICATION_CORRECT_COUNT = "N"; $str_FINAL_INDICATION_SCORE = "N"; $str_FINAL_INDICATION_MARK = "N"; $str_FINAL_INDICATION_MESSAGE = "N"; $str_FINAL_INDICATION = "N"; $str_SHOW_ERRORS = "N"; $str_NEXT_QUESTION_ON_ERROR = "Y"; $test = new CTest(); $res = $test->GetByID($ID); if (!$res->ExtractFields("str_")) { $ID = 0; } else { if ($str_CURRENT_INDICATION > 0) { $str_CURRENT_INDICATION_PERCENT = $str_CURRENT_INDICATION & 1 ? "Y" : "N"; $str_CURRENT_INDICATION_MARK = ($str_CURRENT_INDICATION & 2) >> 1 ? "Y" : "N"; $str_CURRENT_INDICATION = "Y"; } if ($str_FINAL_INDICATION > 0) { $str_FINAL_INDICATION_CORRECT_COUNT = $str_FINAL_INDICATION & 1 ? "Y" : "N"; $str_FINAL_INDICATION_SCORE = ($str_FINAL_INDICATION & 2) >> 1 ? "Y" : "N"; $str_FINAL_INDICATION_MARK = ($str_FINAL_INDICATION & 4) >> 2 ? "Y" : "N"; $str_FINAL_INDICATION_MESSAGE = ($str_FINAL_INDICATION & 8) >> 3 ? "Y" : "N"; $str_FINAL_INDICATION = "Y";
/** * <p>Возвращает список вопросов плана тестирования по фильтру <b>arFilter</b>, отсортированный в порядке <b>arOrder</b>.</p> * * * * * @param array $arrayarOrder = Array("ID"=>"DESC") Массив для сортировки результата. Массив вида <i>array("поле * сортировки"=>"направление сортировки" [, ...])</i>.<br>Поле для * сортировки может принимать значения: <ul> <li> <b>ID</b> - идентификатор * вопроса в плане тестирования; </li> <li> <b>ATTEMPT_ID</b> - идентификатор * попытки; </li> <li> <b>QUESTION_ID</b> - идентификатор вопроса; </li> <li> <b>POINT</b> - * количество баллов; </li> <li> <b>ANSWERED</b> - вопрос отвечен (Y|N); </li> <li> * <b>CORRECT</b> - вопрос правильно отвечен (Y|N); </li> <li> <b>QUESTION_NAME</b> - * название вопроса; </li> <li> <b>RAND</b> - случайный порядок. </li> * </ul>Направление сортировки может принимать значения: <ul> <li> <b>asc</b> - * по возрастанию; </li> <li> <b>desc</b> - по убыванию; </li> </ul>Необязательный. * По умолчанию фильтруется по убыванию идентификатора вопроса в * плане тестирования. * * * * @param array $arrayarFilter = Array() Массив вида <i>array("фильтруемое поле"=>"значение фильтра" [, ...])</i>. * Фильтруемое поле может принимать значения: <ul> <li> <b>ID</b> - * идентификатор вопроса в плане тестирования; </li> <li> <b>ATTEMPT_ID</b> - * идентификатор попытки; </li> <li> <b>QUESTION_ID</b> - идентификатор вопроса; * </li> <li> <b>POINT</b> - количество баллов; </li> <li> <b>RESPONSE</b> - ответ учащегося * (можно искать по шаблону [%_]); </li> <li> <b>QUESTION_NAME</b> - название вопроса * (можно искать по шаблону [%_]); </li> <li> <b>ANSWERED</b> - вопрос отвечен (Y|N); * </li> <li> <b>CORRECT</b> - вопрос правильно отвечен (Y|N). </li> </ul>Перед * названием фильтруемого поля может указать тип фильтрации: <ul> <li>"!" * - не равно </li> <li>"<" - меньше </li> <li>"<=" - меньше либо равно </li> <li>">" * - больше </li> <li>">=" - больше либо равно </li> </ul> <br>"<i>значения * фильтра</i>" - одиночное значение или массив.<br><br>Необязательный. По * умолчанию записи не фильтруются. * * * * @return CDBResult <p>Возвращается объект <a * href="http://dev.1c-bitrix.ru/api_help/main/reference/cdbresult/index.php">CDBResult</a>.</p> * * * <h4>Example</h4> * <pre> * <? * if (CModule::IncludeModule("learning")) * { * $ATTEMPT_ID = 590; * $res = CTestResult::GetList( * Array("ID" => "ASC"), * Array("ANSWERED" => "N", "ATTEMPT_ID" => $ATTEMPT_ID) * ); * * while ($arQuestionPlan = $res->GetNext()) * { * echo "Question ID: ".$arQuestionPlan["QUESTION_ID"].<br> "; Correct answer: ".$arQuestionPlan["CORRECT"].<br> "; Question name:".$arQuestionPlan["QUESTION_NAME"]."<br>"; * } * } * ?> * </pre> * * * * <h4>See Also</h4> * <ul> <li> <a href="http://dev.1c-bitrix.ru/api_help/main/reference/cdbresult/index.php">CDBResult</a> </li> <li> <a * href="index.php">CTestResult</a>::<a href="getbyid.php">GetByID</a> </li> <li><a * href="../../fields.php#test_result">Поля плана тестирования</a></li> </ul><a name="examples"></a> * * * @static * @link http://dev.1c-bitrix.ru/api_help/learning/classes/ctestresult/getlist.php * @author Bitrix */ public static function GetList($arOrder=array(), $arFilter=array()) { global $DB, $USER, $APPLICATION; if (!is_array($arFilter)) $arFilter = Array(); $oPermParser = new CLearnParsePermissionsFromFilter ($arFilter); $arSqlSearch = CTestResult::GetFilter($arFilter); $strSqlSearch = ""; $arSqlSearchCnt = count($arSqlSearch); for($i=0; $i<$arSqlSearchCnt; $i++) if(strlen($arSqlSearch[$i])>0) $strSqlSearch .= " AND ".$arSqlSearch[$i]." "; $strSql = "SELECT TR.*, Q.QUESTION_TYPE, Q.NAME as QUESTION_NAME, Q.POINT as QUESTION_POINT, Q.LESSON_ID FROM b_learn_test_result TR INNER JOIN b_learn_question Q ON TR.QUESTION_ID = Q.ID INNER JOIN b_learn_lesson L ON Q.LESSON_ID = L.ID WHERE 1=1 "; if ($oPermParser->IsNeedCheckPerm()) $strSql .= " AND L.ID IN (" . $oPermParser->SQLForAccessibleLessons() . ") "; $strSql .= $strSqlSearch; /* was: $bCheckPerm = ($APPLICATION->GetUserRight("learning") < "W" && !$USER->IsAdmin() && $arFilter["CHECK_PERMISSIONS"] != "N"); $strSql = "SELECT TR.*, Q.QUESTION_TYPE, Q.NAME as QUESTION_NAME, Q.POINT as QUESTION_POINT, Q.LESSON_ID FROM b_learn_test_result TR INNER JOIN b_learn_question Q ON TR.QUESTION_ID = Q.ID INNER JOIN b_learn_lesson L ON Q.LESSON_ID = L.ID " "INNER JOIN b_learn_course C ON L.COURSE_ID = C.ID ". . "WHERE 1=1 " . ($bCheckPerm ? "AND EXISTS (SELECT * FROM b_learn_course_permission CP WHERE ". "CP.USER_GROUP_ID IN (".$USER->GetGroups().") ". "AND CP.PERMISSION >= '".(strlen($arFilter["MIN_PERMISSION"])==1 ? $arFilter["MIN_PERMISSION"] : "R")."' ". "AND (CP.PERMISSION='X' OR C.ACTIVE='Y'))" :"") . $strSqlSearch; */ if (!is_array($arOrder)) $arOrder = Array(); foreach($arOrder as $by=>$order) { $by = strtolower($by); $order = strtolower($order); if ($order!="asc") $order = "desc"; if ($by == "id") $arSqlOrder[] = " TR.ID ".$order." "; elseif ($by == "attempt_id") $arSqlOrder[] = " TR.ATTEMPT_ID ".$order." "; elseif ($by == "question_id") $arSqlOrder[] = " TR.QUESTION_ID ".$order." "; elseif ($by == "point") $arSqlOrder[] = " TR.POINT ".$order." "; elseif ($by == "correct") $arSqlOrder[] = " TR.CORRECT ".$order." "; elseif ($by == "answered") $arSqlOrder[] = " TR.ANSWERED ".$order." "; elseif ($by == "question_name") $arSqlOrder[] = " QUESTION_NAME ".$order." "; elseif ($by == "rand") $arSqlOrder[] = CTest::GetRandFunction(); else { $arSqlOrder[] = " TR.ID ".$order." "; $by = "id"; } } $strSqlOrder = ""; DelDuplicateSort($arSqlOrder); $arSqlOrderCnt = count($arSqlOrder); for ($i=0; $i<$arSqlOrderCnt; $i++) { if($i==0) $strSqlOrder = " ORDER BY "; else $strSqlOrder .= ","; $strSqlOrder .= $arSqlOrder[$i]; } $strSql .= $strSqlOrder; //echo $strSql; return $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__); }
" size="47"></td> </tr> <tr> <td><?php echo GetMessage("LEARNING_ADMIN_TEST"); ?> :</td> <td> <select name="filter_test_id"> <option value=""><?php echo GetMessage("LEARNING_ALL"); ?> </option> <?php $l = CTest::GetList(array(), array()); while ($l->ExtractFields("l_")) { ?> <option value="<?php echo $l_ID; ?> "<?php if ($filter_test_id == $l_ID) { echo " selected"; } ?> ><?php echo $l_NAME; ?> </option><?php }
/** * WARNING: don't use this method, it's for internal use only * * Convert course to non-course lesson (course will be removed, * but lesson will stay exists) * * WARNING: this method terminates (by die()/exit()) current execution flow * when SQL server error occured. It's due to bug in CDatabase::Update() in main * module (version info: * define("SM_VERSION","11.0.12"); * define("SM_VERSION_DATE","2012-02-21 17:00:00"); // YYYY-MM-DD HH:MI:SS * ) * * @param int $courseId (returned by GetLinkedCourse($lessonId) ) * * @access private */ protected static function CourseBecomeLesson($courseId) { global $DB; self::_EnsureArgsStrictlyCastableToIntegers($courseId); $linkedLessonId = CCourse::CourseGetLinkedLesson($courseId); if ($linkedLessonId === false) { return false; } // Check certificates (if exists => forbid removing course) $certificate = CCertification::GetList(array(), array("COURSE_ID" => $courseId, 'CHECK_PERMISSIONS' => 'N')); if ($certificate === false || $certificate->GetNext()) { return false; } // Remove tests $tests = CTest::GetList(array(), array("COURSE_ID" => $courseId)); if ($tests === false) { return false; } while ($arTest = $tests->Fetch()) { if (!CTest::Delete($arTest["ID"])) { return false; } } // Remove all prohibitions for lessons in context of course to be removed // and remove prohibitions for course to be removed in context of all other courses self::PublishProhibitionPurge($linkedLessonId, self::PUBLISH_PROHIBITION_PURGE_ALL_LESSONS_IN_COURSE_CONTEXT | self::PUBLISH_PROHIBITION_PURGE_LESSON_IN_ALL_COURSE_CONTEXT); $rc = $DB->Query("DELETE FROM b_learn_course\n\t\t\tWHERE ID=" . (string) (int) $courseId, true); // reload cache of LINKED_LESSON_ID -> COURSE_ID self::GetCourseToLessonMap_ReloadCache(); CLearnCacheOfLessonTreeComponent::MarkAsDirty(); /** * This code will be useful after bug in CDatabase::Update() * and CDatabase::Insert() will be solved and $ignore_errors setted * to true in Insert()/Update() call above. */ if ($rc === false) { throw new LearnException('EA_SQLERROR', LearnException::EXC_ERR_ALL_GIVEUP); } // If data not updated if ($rc === 0) { throw new LearnException('EA_OTHER: data not updated', LearnException::EXC_ERR_ALL_GIVEUP); } }
function GetList($arOrder = array(), $arFilter = array()) { global $DB, $USER; $arSqlSearch = CLAnswer::GetFilter($arFilter); $strSqlSearch = ""; for ($i = 0; $i < count($arSqlSearch); $i++) { if (strlen($arSqlSearch[$i]) > 0) { $strSqlSearch .= " AND " . $arSqlSearch[$i] . " "; } } $strSql = "SELECT CA.*, CQ.ID AS QUESTION_ID, CQ.NAME AS QUESTION_NAME " . "FROM b_learn_answer CA " . "INNER JOIN b_learn_question CQ ON CA.QUESTION_ID = CQ.ID " . "WHERE 1=1 " . $strSqlSearch; if (!is_array($arOrder)) { $arOrder = array(); } foreach ($arOrder as $by => $order) { $by = strtolower($by); $order = strtolower($order); if ($order != "asc") { $order = "desc"; } if ($by == "id") { $arSqlOrder[] = " CA.ID " . $order . " "; } elseif ($by == "sort") { $arSqlOrder[] = " CA.SORT " . $order . " "; } elseif ($by == "correct") { $arSqlOrder[] = " CA.CORRECT " . $order . " "; } elseif ($by == "answer") { $arSqlOrder[] = " CA.ANSWER " . $order . " "; } elseif ($by == "rand") { $arSqlOrder[] = CTest::GetRandFunction(); } else { $arSqlOrder[] = " CA.ID " . $order . " "; $by = "id"; } } $strSqlOrder = ""; DelDuplicateSort($arSqlOrder); for ($i = 0; $i < count($arSqlOrder); $i++) { if ($i == 0) { $strSqlOrder = " ORDER BY "; } else { $strSqlOrder .= ","; } $strSqlOrder .= $arSqlOrder[$i]; } $strSql .= $strSqlOrder; //echo $strSql; return $DB->Query($strSql, false, "File: " . __FILE__ . "<br>Line: " . __LINE__); }
} $ID = IntVal($ID); switch ($_REQUEST['action']) { case "delete": @set_time_limit(0); $DB->StartTransaction(); $ch = new CTest(); if (!$ch->Delete($ID)) { $DB->Rollback(); $lAdmin->AddGroupError(GetMessage("LEARNING_DELETE_ERROR"), $ID); } $DB->Commit(); break; case "activate": case "deactivate": $ch = new CTest(); $arFields = array("ACTIVE" => $_REQUEST['action'] == "activate" ? "Y" : "N"); if (!$ch->Update($ID, $arFields)) { if ($e = $APPLICATION->GetException()) { $lAdmin->AddGroupError(GetMessage("SAVE_ERROR") . $ID . ": " . $e->GetString(), $ID); } } break; } } if (isset($return_url) && strlen($return_url) > 0 && check_bitrix_sessid()) { LocalRedirect($return_url); } } // fetch data $rsData = CTest::GetList(array($by => $order), $arFilter);
if ($USER->GetID()) { $arTest["ATTEMPT_LIMIT"] += CGradeBook::GetExtraAttempts($USER->GetID(), $arParams["TEST_ID"]); } $oAccess = CLearnAccess::GetInstance($USER->GetID()); $isRelativelyHighAccessLevel = $oAccess->IsBaseAccess( CLearnAccess::OP_LESSON_CREATE | CLearnAccess::OP_LESSON_READ | CLearnAccess::OP_LESSON_WRITE | CLearnAccess::OP_LESSON_REMOVE); $bCheckPerm = (!$isRelativelyHighAccessLevel && !$USER->IsAdmin()); if ($bCheckPerm && $arTest["PREVIOUS_TEST_ID"] > 0 && $arTest["PREVIOUS_TEST_SCORE"] > 0 && !CTest::isPrevPassed($arTest["PREVIOUS_TEST_ID"], $arTest["PREVIOUS_TEST_SCORE"])) { if ($arTest["PREVIOUS_TEST_LINK"]) { $errors[] = str_replace("#TEST_LINK#", "\"".$arTest["PREVIOUS_TEST_LINK"]."\"", GetMessage("LEARNING_TEST_DENIED_PREVIOUS")); } } //Session variables $userID = $USER->GetID() ? $USER->GetID() : 0; $sessAttemptID =& $_SESSION["LEARN_".$arParams["TEST_ID"]."_ATTEMPT_ID_".$userID]; $sessAttemptFinished =& $_SESSION["LEARN_".$arParams["TEST_ID"]."_FINISHED_".$userID]; $sessAttemptError =& $_SESSION["LEARN_".$arParams["TEST_ID"]."_ERROR_".$userID]; $sessAttempt =& $_SESSION["LEARN_".$arParams["TEST_ID"]."_COMPLETED_".$userID]; $sessIncorrectMessage =& $_SESSION["LEARN_".$arParams["TEST_ID"]."_INCORRECT_MESSAGE_".$userID];