19 declare(strict_types=1);
    21 require_once 
'Modules/Test/classes/inc.AssessmentConstants.php';
    35         return 'showManScoringByQuestionParticipantsTable';
    40         return 'man_scoring_by_qst';
    50         if (!$this->testAccess->checkScoreParticipantsAccess()) {
    51             $this->tpl->setOnScreenMessage(
'info', $this->
lng->txt(
'cannot_edit_test'), 
true);
    52             $this->
ctrl->redirectByClass(
'ilobjtestgui', 
'infoScreen');
    59         $mathJaxSetting = 
new ilSetting(
'MathJax');
    61         if ($mathJaxSetting->get(
"enable")) {
    62             $this->tpl->addJavaScript($mathJaxSetting->get(
"path_to_mathjax"));
    65         $this->tpl->addJavaScript(
"./Services/JavaScript/js/Basic.js");
    66         $this->tpl->addJavaScript(
"./Services/Form/js/Form.js");
    67         $this->tpl->addJavascript(
'./Services/UIComponent/Modal/js/Modal.js');
    68         $this->
lng->toJSMap([
'answer' => $this->
lng->txt(
'answer')]);
    72         $qst_id = (
int) $table->getFilterItemByPostVar(
'question')->getValue();
    73         $passNr = $table->getFilterItemByPostVar(
'pass')->getValue();
    74         $finalized_filter = $table->getFilterItemByPostVar(
'finalize_evaluation')->getValue();
    75         $answered_filter = $table->getFilterItemByPostVar(
'only_answered')->getChecked();
    77         $selected_questionData = null;
    78         $complete_feedback = $this->
object->getCompleteManualFeedback($qst_id);
    80         if (is_numeric($qst_id)) {
    81             $info = $this->questioninfo->getQuestionInfo($qst_id);
    82             $selected_questionData = $info;
    85         if ($selected_questionData && is_numeric($passNr)) {
    86             $data = $this->
object->getCompleteEvaluationData(
false);
    87             $participants = 
$data->getParticipants();
    91                 $this->participant_access_filter->getScoreParticipantsUserFilter($this->ref_id)
    96                 $participant = $participants[$active_id];
    97                 $testResultData = $this->
object->getTestResult($active_id, $passNr - 1);
    99                 foreach ($testResultData as $questionData) {
   101                     $is_answered = (bool) ($questionData[
'answered'] ?? 
false);
   102                     $finalized_evaluation = (bool) ($questionData[
'finalized_evaluation'] ?? 
false);
   104                     if (isset($complete_feedback[$active_id][$passNr - 1][$qst_id])) {
   105                         $feedback = $complete_feedback[$active_id][$passNr - 1][$qst_id];
   108                     if (!isset($questionData[
'qid'])
   109                         || $questionData[
'qid'] !== $selected_questionData[
'question_id']
   110                         || $finalized_filter === self::ONLY_FINALIZED && !$finalized_evaluation
   111                         || $finalized_filter === self::EXCEPT_FINALIZED && $finalized_evaluation
   112                         || $answered_filter === 
true && !$is_answered) {
   117                         'pass_id' => $passNr - 1,
   118                         'active_id' => $active_id,
   119                         'qst_id' => $questionData[
'qid'],
   122                             (
int) $questionData[
'qid'],
   125                         'maximum_points' => $this->questioninfo->getMaximumPoints((
int) $questionData[
'qid']),
   126                         'name' => $participant->getName()
   131             $table->disable(
'header');
   134         $table->setTitle($this->
lng->txt(
'tst_man_scoring_by_qst'));
   136         if ($selected_questionData) {
   137             $maxpoints = $this->questioninfo->getMaximumPoints((
int) $selected_questionData[
'question_id']);
   138             $table->setCurQuestionMaxPoints($maxpoints);
   139             $maxpoints_txt = 
' (' . $maxpoints . 
' ' . $this->
lng->txt(
'points') . 
')';
   140             if ($maxpoints == 1) {
   141                 $maxpoints_txt = 
' (' . $maxpoints . 
' ' . $this->
lng->txt(
'point') . 
')';
   145                 $this->
lng->txt(
'tst_man_scoring_by_qst') . 
': ' . $selected_questionData[
'title'] . $maxpoints_txt .
   146                 ' [' . $this->
lng->txt(
'question_id_short') . 
': ' . $selected_questionData[
'question_id'] . 
']'   150         $table->setData($table_data);
   151         $this->tpl->setContent($table->getHTML());
   156         $transform_scoring = $this->
refinery->custom()->transformation(
function ($value) use (&$transform_scoring) {
   157             if (is_array($value)) {
   158                 foreach ($value as 
$key => $val) {
   159                     $value[
$key] = $transform_scoring->transform($val);
   161             } elseif (is_string($value)) {
   162                 $value = $this->
refinery->byTrying([
   163                     $this->
refinery->kindlyTo()->float(),
   165                 ])->transform($value);
   167                 throw new \ILIAS\Refinery\ConstraintViolationException(
   168                     sprintf(
'The value "%s" is no array or string.', var_export($value, 
true)),
   169                     'value_is_no_array_or_string',
   170                     var_export($value, 
true)
   177         $transform_finalization = $this->
refinery->custom()->transformation(
   178             function ($value) use (&$transform_finalization) {
   179                 if (is_array($value)) {
   180                     foreach ($value as 
$key => $val) {
   181                         $value[
$key] = $transform_finalization->transform($val);
   183                 } elseif (is_string($value)) {
   184                     $value = $this->
refinery->byTrying([
   185                         $this->
refinery->kindlyTo()->bool(),
   187                     ])->transform($value);
   189                     throw new \ILIAS\Refinery\ConstraintViolationException(
   190                         sprintf(
'The value "%s" is no array or string.', var_export($value, 
true)),
   191                         'value_is_no_array_or_string',
   192                         var_export($value, 
true)
   200         $scoring = $this->
http->wrapper()->post()->retrieve(
   204                 $this->refinery->always([])
   207         $finalization = $this->
http->wrapper()->post()->retrieve(
   210                 $transform_finalization,
   211                 $this->refinery->always([])
   215         $pass = key($scoring);
   216         $active_data = current($scoring);
   217         $active_ids = array_keys($active_data);
   219         if (!$this->testAccess->checkScoreParticipantsAccessForActiveId(current($active_ids))) {
   221                 $this->
http->saveResponse(
   222                     $this->
http->response()->withBody(
   226                 $this->
http->sendResponse();
   227                 $this->
http->close();
   230             $this->tpl->setOnScreenMessage(
'info', $this->
lng->txt(
'cannot_edit_test'), 
true);
   231             $this->
ctrl->redirectByClass(
'ilobjtestgui', 
'infoScreen');
   234         if ($scoring === []) {
   235             $this->tpl->setOnScreenMessage(
'failure', $this->
lng->txt(
'tst_save_manscoring_failed_unknown'));
   242         $maxPointsByQuestionId = [];
   246             $this->participant_access_filter->getScoreParticipantsUserFilter($this->ref_id)
   250         $changed_one = 
false;
   251         $lastAndHopefullyCurrentQuestionId = null;
   254             $questions = $active_data[$active_id];
   255             if (!is_array($questions)) {
   260             if (!$this->
object->getTestResult($active_id, $pass)) {
   264             $update_participant = 
false;
   267             foreach ($questions as $qst_id => $reached_points_string) {
   268                 $reached_points = $this->
refinery->kindlyTo()->float()
   269                     ->transform($reached_points_string);
   270                 if (!isset($manPointsPost[$pass])) {
   271                     $manPointsPost[$pass] = [];
   273                 if (!isset($manPointsPost[$pass][$active_id])) {
   274                     $manPointsPost[$pass][$active_id] = [];
   286                 if (isset($current_feedback_info[
'finalized_evaluation']) && $current_feedback_info[
'finalized_evaluation'] === 1) {
   288                     $feedback_text = $current_feedback_info[
'feedback'];
   291                 $maxPointsByQuestionId[$qst_id] = $this->questioninfo->getMaximumPoints($qst_id);
   292                 $manPointsPost[$pass][$active_id][$qst_id] = $reached_points;
   293                 if ($reached_points > $maxPointsByQuestionId[$qst_id]) {
   294                     $this->tpl->setOnScreenMessage(
   296                         sprintf($this->
lng->txt(
'tst_save_manscoring_failed'), $pass + 1),
   314                 if ($reached_points !== $old_points) {
   319                         $maxPointsByQuestionId[$qst_id],
   322                         $this->
object->areObligationsEnabled(),
   328             if ($update_participant) {
   336             $lastAndHopefullyCurrentQuestionId = $qst_id;
   339         $correction_feedback = [];
   340         $correction_points = 0;
   345             if ($lastAndHopefullyCurrentQuestionId) {
   347                 $qTitle = $question->getTitleForHTMLOutput();
   351                 $this->
lng->txt(
'tst_saved_manscoring_by_question_successfully'),
   356             $this->tpl->setOnScreenMessage(
'success', $msg, 
true);
   358             if (isset($active_id) && $lastAndHopefullyCurrentQuestionId) {
   361                     $lastAndHopefullyCurrentQuestionId,
   366                     $lastAndHopefullyCurrentQuestionId,
   372         if ($ajax && is_array($correction_feedback)) {
   373             $finalized_by_usr_id = $correction_feedback[
'finalized_by_usr_id'];
   374             if (!$finalized_by_usr_id) {
   375                 $finalized_by_usr_id = $this->
user->getId();
   378             $correction_feedback[
'finalized_on_date'] = 
'';
   380             if (is_int($correction_feedback[
'finalized_tstamp'])) {
   382                 $correction_feedback[
'finalized_on_date'] = $time->get(
IL_CAL_DATETIME);
   385             if (!$correction_feedback[
'feedback']) {
   386                 $correction_feedback[
'feedback'] = [];
   388             if ($correction_feedback[
'finalized_evaluation'] == 1) {
   389                 $correction_feedback[
'finalized_evaluation'] = $this->
lng->txt(
'yes');
   391                 $correction_feedback[
'finalized_evaluation'] = $this->
lng->txt(
'no');
   392                 $correction_feedback[
'finalized_by'] = 
'';
   395             $this->
http->saveResponse(
   396                 $this->
http->response()->withBody(
   400                                 'feedback' => $correction_feedback,
   401                                 'points' => $correction_points,
   403                                     'yes' => $this->
lng->txt(
'yes'),
   404                                     'no' => $this->
lng->txt(
'no')
   412             $this->
http->sendResponse();
   413             $this->
http->close();
   422         $table->resetOffset();
   423         $table->writeFilterToSession();
   430         $table->resetOffset();
   431         $table->resetFilter();
   437         $active_id = $this->testrequest->getActiveId();
   438         $pass = $this->testrequest->getPassId();
   439         $question_id = (
int) $this->testrequest->raw(
'qst_id');
   441         if (!$this->
getTestAccess()->checkScoreParticipantsAccessForActiveId($active_id)) {
   442             $this->
http->close(); 
   445         $data = $this->
object->getCompleteEvaluationData(
false);
   446         $participant = 
$data->getParticipant($active_id);
   447         $question_gui = $this->
object->createQuestionGUI(
'', $question_id);
   448         $tmp_tpl = 
new ilTemplate(
'tpl.il_as_tst_correct_solution_output.html', 
true, 
true, 
'Modules/Test');
   449         if ($this->
object->getAutosave()) {
   450             $aresult_output = $question_gui->getAutoSavedSolutionOutput(
   456                 $this->
object->getShowSolutionFeedback(),
   461             if ($aresult_output) {
   462                 $tmp_tpl->setVariable(
'TEXT_ASOLUTION_OUTPUT', $this->
lng->txt(
'autosavecontent'));
   463                 $tmp_tpl->setVariable(
'ASOLUTION_OUTPUT', $aresult_output);
   466         $result_output = $question_gui->getSolutionOutput(
   472             $this->
object->getShowSolutionFeedback(),
   476         $max_points = $question_gui->object->getMaximumPoints();
   483             $question_gui->object->getReachedPoints($active_id, $pass),
   486         $this->
appendFormToModal($tmp_tpl, $pass, $active_id, $question_id, $max_points);
   487         $tmp_tpl->setVariable(
'TEXT_YOUR_SOLUTION', $this->
lng->txt(
'answers_of') . 
' ' . $participant->getName());
   489         if ($this->
object->getShowSolutionSuggested() && strlen($suggested_solution) > 0) {
   490             $tmp_tpl->setVariable(
'TEXT_SOLUTION_HINT', $this->
lng->txt(
"solution_hint"));
   494         $tmp_tpl->setVariable(
'TEXT_SOLUTION_OUTPUT', $this->
lng->txt(
'question'));
   495         $tmp_tpl->setVariable(
'TEXT_RECEIVED_POINTS', $this->
lng->txt(
'scoring'));
   496         $add_title = 
' [' . $this->
lng->txt(
'question_id_short') . 
': ' . $question_id . 
']';
   497         $question_title = $this->
object->getQuestionTitle($question_gui->object->getTitleForHTMLOutput());
   498         $lng = $this->
lng->txt(
'points');
   499         if ($max_points == 1) {
   500             $lng = $this->
lng->txt(
'point');
   503         $tmp_tpl->setVariable(
   505             $question_title . 
' (' . $max_points . 
' ' . 
$lng . 
')' . $add_title
   507         $tmp_tpl->setVariable(
'SOLUTION_OUTPUT', $result_output);
   509         $tmp_tpl->setVariable(
   512                 $this->
lng->txt(
'part_received_a_of_b_points'),
   513                 $question_gui->object->getReachedPoints($active_id, $pass),
   518         $this->
http->saveResponse(
   519             $this->
http->response()->withBody(
   521             )->withHeader(\
ILIAS\
HTTP\Response\ResponseHeader::CONTENT_TYPE, 
'text/html')
   523         $this->
http->sendResponse();
   524         $this->
http->close();
   535             'TEXT_YOUR_SOLUTION',
   536             $this->
lng->txt(
'answers_of') . 
' ' . $participant_data->
getName()
   540             $this->
object->getAnonymity() == 1 ||
   541             ($this->
object->getAnonymity() == 2 && !$this->
access->checkAccess(
'write', 
'', $this->
object->getRefId()))
   544                 'TEXT_YOUR_SOLUTION',
   545                 $this->
lng->txt(
'answers_of') . 
' ' . $this->
lng->txt(
'anonymous')
   552         $add_title = 
' [' . $this->
lng->txt(
'question_id_short') . 
': ' . $question_id . 
']';
   553         $question_title = $this->
object->getQuestionTitle($title);
   554         $lng = $this->
lng->txt(
'points');
   555         if ($max_points == 1) {
   556             $lng = $this->
lng->txt(
'point');
   561             $question_title . 
' (' . $max_points . 
' ' . 
$lng . 
')' . $add_title
   567         $post_var = 
'[' . $pass . 
'][' . $active_id . 
'][' . $question_id . 
']';
   568         $scoring_post_var = 
'scoring' . $post_var;
   573         $form->setFormAction($this->
ctrl->getFormAction($this, 
'showManScoringByQuestionParticipantsTable'));
   574         $form->setTitle($this->
lng->txt(
'manscoring'));
   576         if (isset($feedback[
'finalized_evaluation']) && $feedback[
'finalized_evaluation'] == 1) {
   579             $scoring_post_var = $scoring_post_var . 
'_disabled';
   580             $hidden_points->setValue((
string) $reached_points);
   581             $form->addItem($hidden_points);
   585         if (array_key_exists(
'feedback', $feedback)) {
   586             $feedback_text = $feedback[
'feedback'];
   591                 $this->
lng->txt(
'set_manual_feedback'),
   592                 'm_feedback' . $post_var,
   597             $feedback_input = 
new ilTextAreaInputGUI($this->
lng->txt(
'set_manual_feedback'), 
'm_feedback' . $post_var);
   599         $feedback_input->
setValue($feedback_text);
   600         $form->addItem($feedback_input);
   603             $this->
lng->txt(
'tst_change_points_for_question'),
   606         $reached_points_form->allowDecimals(
true);
   607         $reached_points_form->setSize(5);
   608         $reached_points_form->setMaxValue($max_points, 
true);
   609         $reached_points_form->setMinValue(0);
   610         $reached_points_form->setDisabled($disable);
   611         $reached_points_form->setValue((
string) $reached_points);
   612         $reached_points_form->setClientSideValidation(
true);
   613         $form->addItem($reached_points_form);
   616         $hidden_points->setValue((
string) $max_points);
   617         $form->addItem($hidden_points);
   620         $hidden_points_name->setValue(
'scoring' . $post_var);
   621         $form->addItem($hidden_points_name);
   624         $hidden_feedback_name->setValue(
'm_feedback' . $post_var);
   625         $form->addItem($hidden_feedback_name);
   628         $post_id = 
'__' . $pass . 
'____' . $active_id . 
'____' . $question_id . 
'__';
   629         $hidden_feedback_id->setValue(
'm_feedback' . $post_id);
   630         $form->addItem($hidden_feedback_id);
   632         $evaluated = 
new ilCheckboxInputGUI($this->
lng->txt(
'finalized_evaluation'), 
'evaluated' . $post_var);
   633         if (isset($feedback[
'finalized_evaluation']) && (
int) $feedback[
'finalized_evaluation'] === 1) {
   634             $evaluated->setChecked(
true);
   636         $form->addItem($evaluated);
   638         $form->addCommandButton(
'checkConstraintsBeforeSaving', $this->
lng->txt(
'save'));
   646             $this->
ctrl->getLinkTarget($this, 
'checkConstraintsBeforeSaving', 
'', 
true, 
false)
   649             'INFO_TEXT_MAX_POINTS_EXCEEDS',
   650             sprintf($this->
lng->txt(
'tst_manscoring_maxpoints_exceeded_input_alert'), $max_points)
   673                 $this->
lng->txt(
'part_received_a_of_b_points'),
   682         $feedback = $this->testrequest->raw(
'feedback');
   683         if ($feedback === null || $feedback === 
'') {
   684             $feedback = $this->testrequest->raw(
'm_feedback');
   687         if ($feedback === null || $feedback === 
'') {
   692             $feedback[$pass][$active_id][$qst_id],
   707         bool $is_single_feedback
   711             $finalized = $finalization[$pass][$active_id][$qst_id] ?? 
false;
   714         $this->
object->saveManualFeedback(
   729         return isset($finalization[$pass][$active_id][$qst_id]);
 
static _getParticipantId($active_id)
Get user id for active id. 
 
static _getRichTextEditor()
Returns the identifier for the Rich Text Editor. 
 
static _getSuggestedSolutionOutput(int $question_id)
 
ilTestManScoringParticipantsBySelectedQuestionAndPassTableGUI 
 
static _lookupFullname(int $a_user_id)
 
Class ChatMainBarProvider . 
 
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
 
const TAB_ID_MANUAL_SCORING
 
appendQuestionTitleToModal(ilTemplate $tmp_tpl, int $question_id, float $max_points, string $title)
 
appendSolutionAndPointsToModal(ilTemplate $tmp_tpl, $result_output, $reached_points, $max_points)
 
applyManScoringByQuestionFilter()
 
setValue(string $a_value)
 
static instantiateQuestion(int $question_id)
 
static getSingleManualFeedback(int $active_id, int $question_id, int $pass)
 
setParticipantAccessFilter(Closure $participantAccessFilter)
 
static http()
Fetches the global http state from ILIAS. 
 
setVariable($variable, $value='')
Sets a variable value. 
 
appendFormToModal(ilTemplate $tmp_tpl, int $pass, int $active_id, int $question_id, float $max_points)
 
setActiveIdsFilter(array $active_ids_filter)
 
static _getReachedPoints(int $active_id, int $question_id, int $pass)
 
static _getUsedHTMLTagsAsString(string $a_module="")
Returns a string of all allowed HTML tags for text editing. 
 
doesValueExistsInPostArray(array $finalization, int $active_id, int $qst_id, int $pass)
 
checkConstraintsBeforeSaving()
 
resetManScoringByQuestionFilter()
 
appendUserNameToModal(ilTemplate $tmp_tpl, ilTestEvaluationUserData $participant_data)
 
ilTestParticipantData $participantData
 
static initjQuery(ilGlobalTemplateInterface $a_tpl=null)
inits and adds the jQuery JS-File to the global or a passed template 
 
This class represents a text area property in a property form. 
 
showManScoringByQuestionParticipantsTable(array $manPointsPost=[])
 
__construct(ilObjTest $a_object)
 
static _setReachedPoints(int $active_id, int $question_id, float $points, float $maxpoints, int $pass, bool $manualscoring, bool $obligationsEnabled, ?int $test_id=null)
Sets the points, a learner has reached answering the question Additionally objective results are upda...
 
retrieveFeedback(int $active_id, int $qst_id, int $pass)
 
saveFinalization(array $finalization, int $active_id, int $qst_id, int $pass, ?string $feedback, bool $is_single_feedback)
 
static initPanel(bool $a_resize=false, ?ilGlobalTemplateInterface $a_main_tpl=null)
Init yui panel used in Modules/Test, Services/TermsOfService (Jan 2022) 
 
static _updateStatus(int $a_obj_id, int $a_usr_id, ?object $a_obj=null, bool $a_percentage=false, bool $a_force_raise=false)
 
static initOverlay(?ilGlobalTemplateInterface $a_main_tpl=null)
Init YUI Overlay module used in Modules/Test, Services/TermsOfService, Services/Tracking, Services/UIComponent. 
 
saveManScoringByQuestion(bool $ajax=false)