From 98bc7933dd2848ad5528ad2a9c8552787a7fe2ad Mon Sep 17 00:00:00 2001 From: jcopado Date: Mon, 10 Jun 2019 16:15:10 +0200 Subject: [PATCH 01/23] 3.1 --- README.md | 150 +--- .../class.assStackQuestionAuthoringGUI.php | 62 ++ .../class.assStackQuestionFeedbackGUI.php | 136 ++-- classes/class.assStackQuestion.php | 9 +- classes/class.assStackQuestionGUI.php | 65 +- classes/class.ilassStackQuestionConfigGUI.php | 668 ++++++++++-------- .../class.assStackQuestionStackQuestion.php | 5 +- .../class.assStackQuestionConfig.php | 24 + .../class.assStackQuestionHealthcheck.php | 3 +- .../class.assStackQuestionPRTNode.php | 2 + .../class.assStackQuestionDisplay.php | 10 +- .../class.assStackQuestionFeedback.php | 23 +- classes/utils/class.assStackQuestionUtils.php | 54 +- lang/ilias_de.lang | 4 +- lang/ilias_en.lang | 2 + plugin.php | 7 +- sql/dbupdate.php | 24 +- 17 files changed, 738 insertions(+), 510 deletions(-) diff --git a/README.md b/README.md index 05a4f0b2..a2b03d33 100644 --- a/README.md +++ b/README.md @@ -83,155 +83,11 @@ input you can evaluate your answer (in self assessment mode) or move to the next Version History =============== +* The stable version 3.1.x for **ILIAS 5.4** with new feedback styles is found in the Github branch **master-ilias54** * The stable version 3.0.x for **ILIAS 5.3** with new functionalities from STACK such a new input types is found in the Github branch **master-ilias53** * The stable version 2.4.x for **ILIAS 5.2 to 5.3** is found in the GitHub branch **master-ilias52** * The stable version 2.3.x for **ILIAS 5.0 to 5.1** is found in the GitHub branch **master** -Update from Version 2.x ------------------------ -After updating the code files of the plugin, the update is started in the plugin administration of ILIAS. -All STACK questions of your platform will be translated to the new syntax for CAS text in STACK (use of {@..@} instead of @...@) -This change is automatically done in the plugin update, but we recommend to check the questions before use it in tests. - -PLEASE BACKUP YOUR DATABASE before you run the update from an older version. Depending on the number of questions, the update takes some minutes, please set the PHP variable max_execution_time high enough. - -The translation is also done when importing questions from ILIAS or MoodleXML, but please notice that this conversion is one way.You can import "old CASText behaviour" questions to a platform with STACK plugin version 3.0+. -But if you import "new CASText behaviour" questions to a platform with a previous version of the plugin, your question will not be properly shown on that platform. - -Version 3.0.22 (2019-05-03) for ILIAS 5.3 ----------------------------------------- -The following bug reports were fixed: -- https://mantis.ilias.de/view.php?id=22847 About validation in equivalence inputs -- https://mantis.ilias.de/view.php?id=24640 About model answer being variables which are a set of numbers. -- https://mantis.ilias.de/view.php?id=24998 About not showing best solution properly when best solution is 0. -- Partial solution for https://mantis.ilias.de/view.php?id=24273 for Algebraic inputs. Not solved for other question types. -- https://mantis.ilias.de/view.php?id=24835 About matrix brackets -- https://mantis.ilias.de/view.php?id=25256 About user input not shown in validation or test results - -Version 3.0.20 (2019-04-03) for ILIAS 5.3 ----------------------------------------- -The following bug reports were fixed: -- https://mantis.ilias.de/view.php?id=24998 - -Version 3.0.17 (2019-03-13) for ILIAS 5.3 ------------------------------------------ -- Configuration of multiple MaximaPool servers for different purposes (Authoring, Test Run) - -Version 3.0.16 (2019-02-27) for ILIAS 5.3 ------------------------------------------ -- Added a new feature Copy of Nodes and PRT: In question Authoring now exists the option to copy nodes and PRT, when clicking on copying Node or PRT, the chosen element is stored in the session, then, the user should go to the question or PRT the user wants to paste te node/prt and click on paste. A new PRT or a new node will be created with the values of the copied one. Please notice that when a node is copied to a PRT, the fields next node when true/false are not copied and should be edited by hand. -The following bug reports were fixed: -- https://mantis.ilias.de/view.php?id=24835 about matrix brackets - -Version 3.0.12 (2018-11-30) for ILIAS 5.3 ----------------------------------------- -- Solved some problems with best solution display when question variables are used in model answer in algebraic inputs. -- Solved some problems with Matrix display in best solution -The following bug reports were fixed: -- https://mantis.ilias.de/view.php?id=23977 -- https://mantis.ilias.de/view.php?id=23895 about syntax hints - -Version 3.0.11 (2018-11-26) for ILIAS 5.3 ----------------------------------------- -- Solved problems to establish default values for options, inputs and PRT, now all already present default values works properly. -- Added the following default values to plugin configuration: Options: Matrix Parenthesis, Inputs: Syntax hint, Forbidden word, allowed words, show validation (as dropdown) and extra options for inputs, PRT: Simplification, First node of predefined PRT: Answertest, test options, quiet feedback, and mode, score, penalty and answernote for both positive and negative branch. -- Added TinyMCE editor for default feedback in configuration/options. -- Some text changes has been made in the german language. -The following bug report were fixed: -- https://mantis.ilias.de/view.php?id=24003 about missing translation to german. -- https://mantis.ilias.de/view.php?id=23913 about grammatical error in german -- https://mantis.ilias.de/view.php?id=24121 about missing display of best solution - -Version 3.0.10 (2018-10-24) for ILIAS 5.3 ----------------------------------------- -Validation button is now directly attached to the input for algebraic inputs, instead of having an space between them. -Validation buttons now doesn´t use the bootstrap style. -Some minor changes has been made, and the following bugs has been solved. -- https://mantis.ilias.de/view.php?id=23753 about checking the user response in the code. -- https://mantis.ilias.de/view.php?id=23314 about info messages -- https://mantis.ilias.de/view.php?id=23533 about validation of string inputs -- https://mantis.ilias.de/view.php?id=23414 about testcases - -Version 3.0.9 (2018-10-10) for ILIAS 5.3 ----------------------------------------- -Validation button is now displayed as a small "check" button, and is always displayed next to the input it belongs. -Some minor bugs has been solved in this version, please use https://mantis.ilias.de to report bugs. - -Version 3.0.8 (2018-09-07) for ILIAS 5.3 ----------------------------------------- -Inputs representation in validation and best solution now takes the minimal size as possible, depending on user or teacher input, and it´s displayed as code text, instead of repeating the input again - -Version 3.0.7 (2018-09-03) for ILIAS 5.3 ----------------------------------------- -Some important changes has been made to question view, either in preview, test mode or printview, the main goal of this changes is to fulfill the needs of SIG Mathe+ILIAS in terms of going back to previous 5.2 style of inputs presentation -- All inputs which can be validated got the validation view changed to a disabled input or textarea filled in with the user solution on the left side, and the validation feedback on the right side. -- Validation messages are now displayed with a white background in order to distinct it from question text. -- The behaviour of inputs presentation in best solution in aligned to validation, instead of showing only a message saying "a possible solution is..." a disabled input is presented filled in with the model answer, All these inputs have the same format as the question input. -Some minor bugs has been solved in this version, please use https://mantis.ilias.de to report bugs. - -Version 3.0.6 (2018-06-25) for ILIAS 5.3 ----------------------------------------- -Some index has been created in the DB, in order to improve performance. -Some code changes were made in order to allow STACK questions run in Learning modules through PCPluginQuestion plugin. -Some bugfix were made on this version: -- https://www.ilias.de/mantis/view.php?id=23135 About showing validation in dropdown, checkbox and radiobutton inputs -- https://www.ilias.de/mantis/view.php?id=22900 About showing validation after question has been evaluated -- https://www.ilias.de/mantis/view.php?id=22655 About error messages shown in wrong places. -- https://www.ilias.de/mantis/view.php?id=22954 About missing german text in units questions. -- https://www.ilias.de/mantis/view.php?id=23237 About problem when updating to 3.0 with prt feedback. - -Version 3.0.5 (2018-05-28) for ILIAS 5.3 ----------------------------------------- -Some bugfix were made on this version: -- https://www.ilias.de/mantis/view.php?id=22847 About validation in new input types -- https://www.ilias.de/mantis/view.php?id=22969 About validation options -- https://www.ilias.de/mantis/view.php?id=23016 About equivalence input firstline option -- https://www.ilias.de/mantis/view.php?id=22900 about showing validation. - -Version 3.0.4 (2018-04-26) for ILIAS 5.3 ----------------------------------------- -Some bugfix were made on this version: -- https://www.ilias.de/mantis/view.php?id=22945 About space between checkboxes and radiobuttons and texts -- https://www.ilias.de/mantis/view.php?id=22938 About problems installing the plugin in a fresh 5.3 client -- https://www.ilias.de/mantis/view.php?id=22925 About answertests names in german missing -- https://www.ilias.de/mantis/view.php?id=22912 About german text file -- https://www.ilias.de/mantis/view.php?id=22946 About validation in equivalence inputs -- https://www.ilias.de/mantis/view.php?id=22947 About syntax hint in equivalence inputs -- https://www.ilias.de/mantis/view.php?id=22847 About validation in equivalence inputs -- Some other minor changes. - -Version 3.0.3 (2018-04-05) for ILIAS 5.3 ----------------------------------------- -Some bugfix were made on this version: -- https://www.ilias.de/mantis/view.php?id=22795 About Deployed seeds navigation -- https://www.ilias.de/mantis/view.php?id=22782 About testcases - - -Version 3.0.2 (2018-03-28) for ILIAS 5.3 ----------------------------------------- -Some bugfix were made on this version: -- https://www.ilias.de/mantis/view.php?id=22780 regarding br before inputs -- https://www.ilias.de/mantis/view.php?id=22779 about HTML in version 3.0 - -Version 3.0.0 (2018-03-07) for ILIAS 5.3 +Version 3.1.0 (2019-06-10) for ILIAS 5.4 ---------------------------------------- -This is a major update. It uses the core classes from STACK version 4.0, the sample questions have also be changed. Please read the section "Update from version 2.x". - -NEW FEATURES: -- 8 new input types (We highly recommend to read the Documentation of all new input types that can be found here: https://stack2.maths.ed.ac.uk/demo/question/type/stack/doc/doc.php/Authoring/Inputs.md): - - Numerical input: - This input type requires the student to type in a number of some kind. Any expression with a variable will be rejected as invalid. - - Scientific units input: - The support for scientific units includes an input type which enables teachers to check units as valid/invalid. - - Equivalence reasoning input: - The purpose of this input type is to enable students to work line by line and reason by equivalence. Note, the teacher's answer and any syntax hint must be a list! If you just pass in an expression strange behaviour may result. - - Dropdown/Checkbox/Radio: - The dropdown, checkbox and radio input types enable teachers to create multiple choice questions. - - String input: - This is a normal input into which students may type whatever they choose. It is always converted into a Maxima string internally. Note that there is no way whatsoever to parse the student's string into a Maxima expression. If you accept a string, then it will always remain a string! You can't later check for algebraic equivalence, the only tests available will be simple string matches, regular expressions etc - - Notes input - This input is a text area into which students may type whatever they choose. It can be used to gather their notes or "working". However, this input always returns an empty value to the CAS, so that the contents are never assessed. - - CASText now supports conditional statements and adaptive blocks. - - Healthcheck has been rebuilt, now shows more information about the CAS connection and the Maxima version used. - - Maxima Libraries can be added to maximalocal from plugin configuration (Notice that this feature doesn't work with server configuration) - +This version includes the changes needed to run STACK questions in ILIAS 5.4, together with the new feedback styles for node feedback, that can be managed through plugin configuration and Layout and Styles / Content styles. To select an specific feedback style you should create a new paragraph style class with a name starting with "STACK". \ No newline at end of file diff --git a/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php b/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php index d30f22e4..ce3cbaae 100644 --- a/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php +++ b/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php @@ -949,6 +949,9 @@ public function getNodePositivePart(assStackQuestionPRT $prt, assStackQuestionPR $node_pos_specific_feedback_info_text .= $this->addInfoTooltip("cas_text"); $node_pos_specific_feedback->setInfo($node_pos_specific_feedback_info_text); + $node_pos_feedback_class = new ilSelectInputGUI($this->getPlugin()->txt('prt_node_pos_feedback_class'), 'prt_' . $prt->getPRTName() . '_node_' . $node->getNodeName() . '_pos_feedback_class'); + $node_pos_feedback_class->setOptions($this->getFeedbackOptions()); + $node_pos_feedback_class->setInfo($this->getPlugin()->txt('prt_node_pos_feedback_class_info')); $this->getQuestionGUI()->setRTESupport($node_pos_specific_feedback); @@ -961,6 +964,7 @@ public function getNodePositivePart(assStackQuestionPRT $prt, assStackQuestionPR //$node_pos_next_node->setValue($this->default[""]); $node_pos_answernote->setValue($this->default["prt_pos_answernote"]); //$node_pos_specific_feedback->setValue($this->default[""]); + $node_pos_feedback_class->setValue(1); } else { $node_pos_mode->setValue($node->getTrueScoreMode()); @@ -969,6 +973,7 @@ public function getNodePositivePart(assStackQuestionPRT $prt, assStackQuestionPR $node_pos_next_node->setValue($node->getTrueNextNode()); $node_pos_answernote->setValue($node->getTrueAnswerNote()); $node_pos_specific_feedback->setValue($node->getTrueFeedback()); + $node_pos_feedback_class->setValue($node->getTrueFeedbackFormat()); } @@ -982,6 +987,7 @@ public function getNodePositivePart(assStackQuestionPRT $prt, assStackQuestionPR } $positive_part->addFormProperty($node_pos_answernote); $positive_part->addFormProperty($node_pos_specific_feedback); + $positive_part->addFormProperty($node_pos_feedback_class); return $positive_part; } @@ -1031,6 +1037,9 @@ public function getNodeNegativePart(assStackQuestionPRT $prt, assStackQuestionPR $node_neg_specific_feedback_info_text .= $this->addInfoTooltip("cas_text"); $node_neg_specific_feedback->setInfo($node_neg_specific_feedback_info_text); + $node_neg_feedback_class = new ilSelectInputGUI($this->getPlugin()->txt('prt_node_neg_feedback_class'), 'prt_' . $prt->getPRTName() . '_node_' . $node->getNodeName() . '_neg_feedback_class'); + $node_neg_feedback_class->setOptions($this->getFeedbackOptions()); + $node_neg_feedback_class->setInfo($this->getPlugin()->txt('prt_node_neg_feedback_class_info')); $this->getQuestionGUI()->setRTESupport($node_neg_specific_feedback); @@ -1043,6 +1052,7 @@ public function getNodeNegativePart(assStackQuestionPRT $prt, assStackQuestionPR //$node_neg_next_node->setValue($this->default[""]); $node_neg_answernote->setValue($this->default["prt_neg_answernote"]); //$node_neg_specific_feedback->setValue($this->default[""]); + $node_neg_feedback_class->setValue(1); } else { $node_neg_mode->setValue($node->getFalseScoreMode()); @@ -1051,6 +1061,7 @@ public function getNodeNegativePart(assStackQuestionPRT $prt, assStackQuestionPR $node_neg_next_node->setValue($node->getFalseNextNode()); $node_neg_answernote->setValue($node->getFalseAnswerNote()); $node_neg_specific_feedback->setValue($node->getFalseFeedback()); + $node_neg_feedback_class->setValue($node->getFalseFeedbackFormat()); } //Add properties to form @@ -1063,6 +1074,8 @@ public function getNodeNegativePart(assStackQuestionPRT $prt, assStackQuestionPR } $negative_part->addFormProperty($node_neg_answernote); $negative_part->addFormProperty($node_neg_specific_feedback); + $negative_part->addFormProperty($node_neg_feedback_class); + return $negative_part; } @@ -1194,4 +1207,53 @@ public function getTemplate() return $this->template; } + public function getFeedbackOptions() + { + global $DIC; + $lng = $DIC->language(); + require_once('./Customizing/global/plugins/Modules/TestQuestionPool/Questions/assStackQuestion/classes/model/configuration/class.assStackQuestionConfig.php'); + $options = array(); + + //Add default option + $options[1] = $lng->txt("default"); + + $config_options = assStackQuestionConfig::_getStoredSettings("feedback"); + foreach ($config_options as $option => $css_class) + { + if ($css_class != "") + { + /* + * AS WE ARE USING THE TRUE/FALSE FEEDBACK FORMAT FIELD OF THE DATABASE + * WHICH IS NOT USED AT THE MOMENT, AND IS ALWAYS 0 OR 1. WE HAVE TO + * DEFINE VALUES FOR EACH OF THE FEEDBACK STYLES, BEGINNING BY 2, TO DISTINGUISH + * QUESTION WHICH USES THIS STYLES AND THOSE WHICH NOT. + */ + + switch ($option) + { + case "feedback_node_right": + $options[2] = $this->getPlugin()->txt($option); + break; + case "feedback_node_wrong": + $options[3] = $this->getPlugin()->txt($option); + break; + case "feedback_solution_hint": + $options[4] = $this->getPlugin()->txt($option); + break; + case "feedback_extra_info": + $options[5] = $this->getPlugin()->txt($option); + break; + case "feedback_plot_feedback": + $options[6] = $this->getPlugin()->txt($option); + break; + case "feedback_extra_1": + $options[7] = $this->getPlugin()->txt($option); + break; + default: + } + } + } + + return $options; + } } \ No newline at end of file diff --git a/classes/GUI/question_display/class.assStackQuestionFeedbackGUI.php b/classes/GUI/question_display/class.assStackQuestionFeedbackGUI.php index b0763e7b..44a9a5d5 100644 --- a/classes/GUI/question_display/class.assStackQuestionFeedbackGUI.php +++ b/classes/GUI/question_display/class.assStackQuestionFeedbackGUI.php @@ -51,9 +51,11 @@ function __construct(ilassStackQuestionPlugin $plugin, $feedback_data, $specific //Set feedback data $this->setFeedback($feedback_data); - if (sizeof($this->getFeedback('prt')) > 1) { + if (sizeof($this->getFeedback('prt')) > 1) + { $this->show_user_response = TRUE; - } else { + } else + { $this->show_user_response = FALSE; } @@ -62,7 +64,8 @@ function __construct(ilassStackQuestionPlugin $plugin, $feedback_data, $specific $mathJaxSetting = new ilSetting("MathJax"); $this->getTemplate()->addJavaScript($mathJaxSetting->get("path_to_mathjax")); - if (is_string($specific_feedback)) { + if (is_string($specific_feedback)) + { $this->specific_feedback = $specific_feedback; } } @@ -114,8 +117,10 @@ private function fillTemplate($graphical_output, $show_points, $show_feedback, $ //General feedback info $this->fillGeneralInfo($show_question_text, $show_points, $show_feedback, $show_correct_solution); //PRT Specific part - if (is_array($this->getFeedback('prt'))) { - foreach ($this->getFeedback('prt') as $prt_name => $prt) { + if (is_array($this->getFeedback('prt'))) + { + foreach ($this->getFeedback('prt') as $prt_name => $prt) + { $this->fillSpecificPrtFeedback($show_question_text, $prt_name, $prt, $graphical_output, $show_points, $show_feedback, $show_correct_solution); } } @@ -132,8 +137,10 @@ private function fillBestSolutionTemplate($mode = "correct") $this->getTemplate()->setVariable('QUESTION_TEXT', assStackQuestionUtils::_getLatex($this->getQuestionTextFilledIn($mode))); //Fill how to solve - if ($mode == "correct") { - $this->getTemplate()->setVariable('HOW_TO_SOLVE', assStackQuestionUtils::_getLatex($this->getQuestionHowToSolve($this->getFeedback('general_feedback')))); + if ($mode == "correct") + { + $text = assStackQuestionUtils::_getLatex($this->getQuestionHowToSolve($this->getFeedback('general_feedback'))); + $this->getTemplate()->setVariable('HOW_TO_SOLVE', assStackQuestionUtils::_getFeedbackStyledText($text, "feedback_solution_hint")); } @@ -175,18 +182,22 @@ private function fillBestSolutionTemplate($mode = "correct") private function fillGeneralInfo($show_question_text, $show_points, $show_feedback, $show_correct_solution) { // question_text - if ($this->getFeedback('question_text') != '' AND $_GET['activecommand'] != 'directfeedback') { + if ($this->getFeedback('question_text') != '' AND $_GET['activecommand'] != 'directfeedback') + { //If test is finished use LaTeX - if ($_GET['cmd'] != 'preview') { + if ($_GET['cmd'] != 'preview') + { $this->getTemplate()->setVariable('QUESTION_TEXT_MESSAGE', $this->getPlugin()->txt('message_question_text')); $this->getTemplate()->setVariable('QUESTION_TEXT', assStackQuestionUtils::_replacePlaceholders(assStackQuestionUtils::_getLatex($this->getFeedback('question_text')))); - } else { + } else + { $this->getTemplate()->setVariable('QUESTION_TEXT_MESSAGE', $this->getPlugin()->txt('message_question_text')); $this->getTemplate()->setVariable('QUESTION_TEXT', assStackQuestionUtils::_replacePlaceholders(assStackQuestionUtils::_getLatex($this->getFeedback('general_feedback')))); } - } elseif ($this->getFeedback('general_feedback') != '' AND $_GET['activecommand'] == 'directfeedback') { + } elseif ($this->getFeedback('general_feedback') != '' AND $_GET['activecommand'] == 'directfeedback') + { //If test is finished use LaTeX $this->getTemplate()->setVariable('QUESTION_TEXT_MESSAGE', $this->getPlugin()->txt('message_general_feedback')); @@ -194,11 +205,13 @@ private function fillGeneralInfo($show_question_text, $show_points, $show_feedba } //If there are general feedback to be shown - if ($show_feedback AND $this->getFeedback('general_feedback') != '') { + if ($show_feedback AND $this->getFeedback('general_feedback') != '') + { //If test is finished use LaTeX //$this->getTemplate()->setVariable('GENERAL_FEEDBACK_MESSAGE', $this->getPlugin()->txt('message_general_feedback')); //$this->getTemplate()->setVariable('GENERAL_FEEDBACK', assStackQuestionUtils::_getLatex($this->getFeedback('general_feedback'))); - } else { + } else + { //Show message for no general feedback. //v1.6.1 Not use general_feedback //$this->getTemplate()->setVariable('GENERAL_FEEDBACK', $this->getPlugin()->txt('message_no_how_to_solve_in_this_question')); @@ -233,27 +246,32 @@ private function fillSpecificPrtFeedback($show_question_text, $prt_name, $prt, $ $this->getTemplate()->setCurrentBlock('question_part'); $this->getTemplate()->setVariable('PRT_NAME', $prt_name); //Fill the user response part - if (($this->show_user_response AND $_GET['activecommand'] == 'directfeedback') OR $_GET['activecommand'] != 'directfeedback') { + if (($this->show_user_response AND $_GET['activecommand'] == 'directfeedback') OR $_GET['activecommand'] != 'directfeedback') + { $this->fillUserResponse($prt['response'], $show_correct_solution); } //Set block again to continue filling the question part $this->getTemplate()->setCurrentBlock('question_part'); //Points reached in this prt - if (($this->show_user_response AND $_GET['activecommand'] == 'directfeedback') OR $_GET['activecommand'] != 'directfeedback') { - if (!is_null($prt['points']) AND $show_points) { + if (($this->show_user_response AND $_GET['activecommand'] == 'directfeedback') OR $_GET['activecommand'] != 'directfeedback') + { + if (!is_null($prt['points']) AND $show_points) + { $this->getTemplate()->setVariable('POINTS_MESSAGE', $this->getPlugin()->txt('message_points')); $this->getTemplate()->setVariable('POINTS', $prt['points']); } } //Errors - if ($prt['errors'] AND $show_feedback) { + if ($prt['errors'] AND $show_feedback) + { $this->getTemplate()->setVariable('ERROR_MESSAGE', $this->getPlugin()->txt('message_error_part')); $this->getTemplate()->setVariable('ERROR', assStackQuestionUtils::_getLatex($prt['errors'])); } //Specific feedback given for this prt - if ($prt['feedback']) { + if ($prt['feedback']) + { //$this->getTemplate()->setVariable('FEEDBACK_MESSAGE', $this->getPlugin()->txt('message_feedback_solution_part')); $this->getTemplate()->setVariable('PART_FEEDBACK', assStackQuestionUtils::_getLatex($prt['feedback'])); } @@ -265,9 +283,11 @@ private function fillSpecificPrtFeedback($show_question_text, $prt_name, $prt, $ }*/ //Fill color for the feedback status of this input. - if ($graphical_output AND $_GET['cmd'] != 'outUserListOfAnswerPasses') { + if ($graphical_output AND $_GET['cmd'] != 'outUserListOfAnswerPasses') + { //Status message - if (is_array($prt['status'])) { + if (is_array($prt['status'])) + { $this->getTemplate()->setVariable('FEEDBACK_STATUS', $prt['status']['message']); } @@ -287,17 +307,20 @@ private function fillUserResponse($response_data, $show_correct_solution) { $this->getTemplate()->setVariable('USER_RESPONSE_CONTAINER_MESSAGE', $this->getPlugin()->txt('message_user_response_container')); //For each input evaluated in current PRT - foreach ($response_data as $input_name => $response) { + foreach ($response_data as $input_name => $response) + { //Set block $this->getTemplate()->setCurrentBlock('user_response_part'); //If there is a model answer to show - if (isset($response['model_answer'])) { + if (isset($response['model_answer'])) + { //User response $this->getTemplate()->setVariable('USER_RESPONSE_MESSAGE', $this->getPlugin()->txt('message_user_solution_part')); $this->getTemplate()->setVariable('USER_RESPONSE', $response['display']); //Teacher solution //TODO this may not work in all configurations detetmine how to call the system delimiters for LaTeX - if ($show_correct_solution AND $_GET['activecommand'] != 'directfeedback') { + if ($show_correct_solution AND $_GET['activecommand'] != 'directfeedback') + { //$this->getTemplate()->setVariable('TEACHER_ANSWER_MESSAGE', $this->getPlugin()->txt('message_best_solution')); //$this->getTemplate()->setVariable('TEACHER_ANSWER', ilUtil::insertLatexImages('\[ ' . assStackQuestionUtils::_solveKeyBracketsBug($response['model_answer'])) . ' \]'); } @@ -314,7 +337,8 @@ private function fillUserResponse($response_data, $show_correct_solution) */ private function getColor($status) { - switch ($status) { + switch ($status) + { case 1: return "#b5eeac"; case 0: @@ -331,21 +355,29 @@ public function getQuestionTextFilledIn($mode = "correct") $question_text = $this->getFeedback('question_text'); $specific_feedback = $this->specific_feedback; //$question_text = preg_replace('/\[\[validation:(.*?)\]\]/', "", $question_text); - if (is_array($this->getFeedback('prt'))) { - foreach ($this->getFeedback('prt') as $prt_name => $prt) { - if(is_array($prt['response'])){ - foreach ($prt['response'] as $input_name => $input) { - if ($input['model_answer'] != "" AND $mode == "correct") { + if (is_array($this->getFeedback('prt'))) + { + foreach ($this->getFeedback('prt') as $prt_name => $prt) + { + if (is_array($prt['response'])) + { + foreach ($prt['response'] as $input_name => $input) + { + if ($input['model_answer'] != "" AND $mode == "correct") + { $question_text = str_replace("[[input:" . $input_name . "]]", $input['model_answer'], $question_text); $question_text = str_replace("[[validation:" . $input_name . "]]", $input['model_answer_display'], $question_text); - } elseif ($input['model_answer'] != "" AND $mode == "user") { + } elseif ($input['model_answer'] != "" AND $mode == "user") + { $question_text = str_replace("[[input:" . $input_name . "]]", $this->getFilledInputUser($input['display']), $question_text); $question_text = str_replace("[[feedback:" . $prt_name . "]]", $this->replacementForPRTPlaceholders($prt, $prt_name, $input), $question_text); $specific_feedback = str_replace("[[feedback:" . $prt_name . "]]", $this->replacementForPRTPlaceholders($prt, $prt_name, $input), $specific_feedback); - } elseif ($mode == "user") { + } elseif ($mode == "user") + { $question_text = str_replace("[[input:" . $input_name . "]]", $this->getPlugin()->txt("no_model_solution_for_this_input"), $question_text); $question_text = str_replace("[[feedback:" . $prt_name . "]]", $this->replacementForPRTPlaceholders($prt, $prt_name, $input), $question_text); - } elseif ($mode == "correct") { + } elseif ($mode == "correct") + { $question_text = str_replace("[[input:" . $input_name . "]]", $this->getPlugin()->txt("no_model_solution_for_this_input"), $question_text); $question_text = str_replace("[[feedback:" . $prt_name . "]]", "", $question_text); } @@ -354,7 +386,8 @@ public function getQuestionTextFilledIn($mode = "correct") } } - if ($mode == "correct") { + if ($mode == "correct") + { $string = ""; //feedback $string .= ''; $deco_question_text = $string; - } elseif ($mode == "user") { + } elseif ($mode == "user") + { $deco_question_text = $question_text; } @@ -391,6 +425,7 @@ private function replacementForPRTPlaceholders($prt, $prt_name, $input) $string .= $prt['feedback']; $string .= $prt['errors']; $string .= ''; + return $string; } @@ -404,7 +439,8 @@ private function getQuestionHowToSolve($text) { $deco_how_to_solve = ""; - if ($text) { + if ($text) + { $deco_how_to_solve = ''; } @@ -464,17 +500,22 @@ private function setFeedback($feedback_data) */ public function getFeedback($selector = '', $prt_name = '') { - if ($selector AND $prt_name) { + if ($selector AND $prt_name) + { //For selection of specific data within an prt return $this->feedback['prt'][$prt_name][$selector]; - } elseif ($selector) { + } elseif ($selector) + { //For selection of specific data non related to an input. - if (isset($this->feedback[$selector])) { + if (isset($this->feedback[$selector])) + { return $this->feedback[$selector]; - } else { + } else + { return ""; } - } else { + } else + { return $this->feedback; } } @@ -482,11 +523,16 @@ public function getFeedback($selector = '', $prt_name = '') public function getUserAnswersFromFeedback() { $user_answers = array(); - if (is_array($this->getFeedback('prt'))) { - foreach ($this->getFeedback('prt') as $prt_name => $prt) { - if (isset($prt['response'])) { - foreach ($prt['response'] as $input_name => $value) { - if (!array_key_exists($input_name, $user_answers)) { + if (is_array($this->getFeedback('prt'))) + { + foreach ($this->getFeedback('prt') as $prt_name => $prt) + { + if (isset($prt['response'])) + { + foreach ($prt['response'] as $input_name => $value) + { + if (!array_key_exists($input_name, $user_answers)) + { $user_answers[$input_name] = $value['value']; } } diff --git a/classes/class.assStackQuestion.php b/classes/class.assStackQuestion.php index c9055021..fd8cebb2 100644 --- a/classes/class.assStackQuestion.php +++ b/classes/class.assStackQuestion.php @@ -1943,5 +1943,12 @@ public function setErrors($error) $_SESSION["stack_authoring_errors"][$this->getId()][] = $error; } - + /** + * @param array $valuePairs + * @return array $indexedValues + */ + public function fetchIndexedValuesFromValuePairs(array $valuePairs) + { + return $valuePairs; + } } \ No newline at end of file diff --git a/classes/class.assStackQuestionGUI.php b/classes/class.assStackQuestionGUI.php index e826cb07..6f7398aa 100644 --- a/classes/class.assStackQuestionGUI.php +++ b/classes/class.assStackQuestionGUI.php @@ -482,6 +482,14 @@ public function getPreview($show_question_only = FALSE, $showInlineFeedback = fa $tpl->addCss($this->plugin->getStyleSheetLocation('css/qpl_xqcas_question_preview.css')); $tpl->addCss($this->plugin->getStyleSheetLocation('css/qpl_xqcas_question_display.css')); + //Include content Styles + $style_ids = assStackQuestionUtils::_getContentStylesAvailable(); + require_once "./Services/Style/Content/classes/class.ilObjStyleSheet.php"; + foreach ($style_ids as $id) + { + $tpl->addCss(ilObjStyleSheet::getContentStylePath((int)$id)); + } + $questionoutput = $question_preview_gui->get(); //Returns output (with page if needed) if (!$show_question_only) @@ -504,6 +512,9 @@ public function getPreview($show_question_only = FALSE, $showInlineFeedback = fa */ public function getTestOutput($active_id, $pass = NULL, $is_question_postponed = FALSE, $user_post_solutions = FALSE, $show_specific_inline_feedback) { + $this->active_id = $active_id; + $this->pass = $pass; + $solutions = NULL; // get the solution of the user for the active pass or from the last pass if allowed if ($active_id) @@ -564,6 +575,15 @@ public function getTestQuestionOutput($solutions, $show_specific_inline_feedback $this->plugin->includeClass("GUI/question_display/class.assStackQuestionDisplayGUI.php"); //Get question display data $tpl->addCss($this->plugin->getStyleSheetLocation('css/qpl_xqcas_question_display.css')); + + //Include content Styles + $style_ids = assStackQuestionUtils::_getContentStylesAvailable(); + require_once "./Services/Style/Content/classes/class.ilObjStyleSheet.php"; + foreach ($style_ids as $id) + { + $tpl->addCss(ilObjStyleSheet::getContentStylePath((int)$id)); + } + $value_format_user_response = assStackQuestionUtils::_getUserResponse($this->object->getId(), $this->object->getStackQuestion()->getInputs(), $feedback_data); $question_display_object = new assStackQuestionDisplay($this->plugin, $this->object->getStackQuestion(), $value_format_user_response, $feedback_data); $question_display_data = $question_display_object->getQuestionDisplayData(TRUE); @@ -595,6 +615,8 @@ public function getTestQuestionOutput($solutions, $show_specific_inline_feedback function getSolutionOutput($active_id, $pass = NULL, $graphicalOutput = FALSE, $result_output = FALSE, $show_question_only = TRUE, $show_feedback = TRUE, $show_correct_solution = FALSE, $show_manual_scoring = FALSE, $show_question_text = TRUE) { $solution_template = new ilTemplate("tpl.il_as_tst_solution_output.html", TRUE, TRUE, "Modules/TestQuestionPool"); + $this->active_id = $active_id; + $this->pass = $pass; //Check for PASS if ($active_id) { @@ -629,15 +651,15 @@ function getSolutionOutput($active_id, $pass = NULL, $graphicalOutput = FALSE, $ { //User Solution //Returns user solution HTML - $solution_output = $this->getQuestionOutput($solutions, FALSE, $show_feedback, TRUE); + $solution_output = $this->getQuestionOutput($solutions, true, $show_feedback, TRUE); //2.3.12 add feedback to solution - $solution_output .= $this->getSpecificFeedbackOutput($active_id, $pass); + $solution_output .= $this->getSpecificFeedbackOutput($solutions); } else { //Correct solution //Returns best solution HTML. - $solution_output = $this->getQuestionOutput($solutions, TRUE, $show_feedback); + $solution_output = $this->getQuestionOutput($solutions, FALSE, $show_feedback); } $question_text = $this->object->getQuestion(); @@ -699,6 +721,7 @@ public function getQuestionOutput($solutions, $best_solution, $show_feedback, $j { $question_text = $solutions["question_text"]; + //Get Model answer from solutions and replace placeholders if (isset($solutions["prt"])) { @@ -763,7 +786,7 @@ public function getQuestionOutput($solutions, $best_solution, $show_feedback, $j $question_text = str_replace("[[validation:" . $input_name . "]]", $validation_replacement, $question_text); } else { - $input_replacement = ""; + $input_replacement = ""; } $size = $input->getBoxSize(); $input_text = ""; @@ -794,7 +817,6 @@ public function getQuestionOutput($solutions, $best_solution, $show_feedback, $j } $size = strlen($input_replacement) + 5; $input_html_display = ''; - $question_text = str_replace("[[input:" . $input_name . "]]", $input_html_display, $question_text); break; } @@ -843,14 +865,22 @@ public function getQuestionOutput($solutions, $best_solution, $show_feedback, $j } /** - * Return the specific feedback - * @param int $active_id - * @param int $pass - * @return string + * Returns the answer specific feedback for the question + * + * Please not that the solution array structure is STACK specific! + * + * @param array $userSolution ($userSolution[] = ) + * @return string HTML Code with the answer specific feedback + * @see assStackQuestion::getSolutionValues() **/ - public function getSpecificFeedbackOutput($active_id, $pass) + public function getSpecificFeedbackOutput($userSolution) { - //Check for PASS + //We cannot use $userSolution, we need to get active id and pass to get the +//Check for PASS + + $active_id = $this->active_id; + $pass = $this->pass; + if ($active_id) { require_once './Modules/Test/classes/class.ilObjTest.php'; @@ -878,6 +908,7 @@ public function getSpecificFeedbackOutput($active_id, $pass) } } $specific_feedback = $this->object->getOptions()->getSpecificFeedback(); + //Search for feedback placeholders in specific feedback text. foreach ($this->object->getPotentialResponsesTrees() as $prt_name => $prt) { @@ -890,11 +921,11 @@ public function getSpecificFeedbackOutput($active_id, $pass) $string .= ''; + //$string .= ''; $specific_feedback = str_replace("[[feedback:" . $prt_name . "]]", $string, $specific_feedback); } else { @@ -1610,6 +1641,14 @@ public function importQuestionFromMoodleForm() $lng = $DIC->language(); $tabs = $DIC->tabs(); + + //#25145 + if (isset($_REQUEST["test_ref_id"])) + { + ilUtil::sendFailure($lng->txt("qpl_qst_xqcas_import_in_test_error"), TRUE); + $DIC->ctrl()->redirect($this, 'editQuestion'); + } + if ($this->object->getSelfAssessmentEditingMode()) { $this->getLearningModuleTabs(); diff --git a/classes/class.ilassStackQuestionConfigGUI.php b/classes/class.ilassStackQuestionConfigGUI.php index 98237ee1..280fc42f 100644 --- a/classes/class.ilassStackQuestionConfigGUI.php +++ b/classes/class.ilassStackQuestionConfigGUI.php @@ -16,12 +16,12 @@ */ class ilassStackQuestionConfigGUI extends ilPluginConfigGUI { - /** @var assStackQuestionConfig */ - protected $config; + /** @var assStackQuestionConfig */ + protected $config; - /** @var ilassStackQuestionPlugin */ - protected $plugin_object = null; + /** @var ilassStackQuestionPlugin */ + protected $plugin_object = null; /** * @@ -40,17 +40,17 @@ public function performCommand($cmd) $cmd = $ctrl->getCmd($this, "configure"); switch ($cmd) { - case 'configure'; - case 'showConnectionSettings': - case 'saveConnectionSettings': - case 'showServerList': - case 'addServer': - case 'editServer': - case 'saveConnectionSettings': - case 'saveServerSettings': - case 'confirmDeleteServers': - $this->initTabs('show_connection_settings'); - break; + case 'configure'; + case 'showConnectionSettings': + case 'saveConnectionSettings': + case 'showServerList': + case 'addServer': + case 'editServer': + case 'saveConnectionSettings': + case 'saveServerSettings': + case 'confirmDeleteServers': + $this->initTabs('show_connection_settings'); + break; case 'showOtherSettings': case 'showDisplaySettings': @@ -65,21 +65,24 @@ public function performCommand($cmd) case 'setDefaultSettingsForInputs': case 'setDefaultSettingsForOptions': case 'setDefaultSettingsForPRTs': + case 'showFeedbackStylesSettings': + case 'saveFeedbackStylesSettings': + case 'setFeedbackStylesSettings': $this->initTabs('show_other_settings'); break; case 'showHealthcheck': - case 'runHealthcheck': + case 'runHealthcheck': $this->initTabs('show_healthcheck'); break; } - $this->$cmd(); + $this->$cmd(); } /** - * Init the tabs - * @param string $a_active id of the active tab (activates it an adds its sub tabs) + * Init the tabs + * @param string $a_active id of the active tab (activates it an adds its sub tabs) */ public function initTabs($a_active = "") { @@ -87,27 +90,28 @@ public function initTabs($a_active = "") $ctrl = $DIC->ctrl(); $tabs = $DIC->tabs(); - $tabs->addTab("show_connection_settings", $this->plugin_object->txt('show_connection_settings'), $ctrl->getLinkTarget($this, 'showConnectionSettings')); - $tabs->addTab("show_other_settings", $this->plugin_object->txt('show_other_settings'), $ctrl->getLinkTarget($this, 'showOtherSettings')); - $tabs->addTab("show_healthcheck", $this->plugin_object->txt('show_healthcheck'), $ctrl->getLinkTarget($this, 'showHealthcheck')); + $tabs->addTab("show_connection_settings", $this->plugin_object->txt('show_connection_settings'), $ctrl->getLinkTarget($this, 'showConnectionSettings')); + $tabs->addTab("show_other_settings", $this->plugin_object->txt('show_other_settings'), $ctrl->getLinkTarget($this, 'showOtherSettings')); + $tabs->addTab("show_healthcheck", $this->plugin_object->txt('show_healthcheck'), $ctrl->getLinkTarget($this, 'showHealthcheck')); - $tabs->activateTab($a_active); + $tabs->activateTab($a_active); - switch ($a_active) + switch ($a_active) { - case 'show_connection_settings': - $tabs->addSubTab('basic_connection_settings', $this->plugin_object->txt('basic_connection_settings'), $ctrl->getLinkTarget($this, 'showConnectionSettings')); - if ($this->config->get('platform_type') == 'server') - { - $tabs->addSubTab('server_configuration', $this->plugin_object->txt('server_configuration'), $ctrl->getLinkTarget($this, 'showServerList')); - } - break; + case 'show_connection_settings': + $tabs->addSubTab('basic_connection_settings', $this->plugin_object->txt('basic_connection_settings'), $ctrl->getLinkTarget($this, 'showConnectionSettings')); + if ($this->config->get('platform_type') == 'server') + { + $tabs->addSubTab('server_configuration', $this->plugin_object->txt('server_configuration'), $ctrl->getLinkTarget($this, 'showServerList')); + } + break; case 'show_other_settings': $tabs->addSubTab('show_display_settings', $this->plugin_object->txt('show_display_settings'), $ctrl->getLinkTargetByClass('ilassStackQuestionConfigGUI', 'showDisplaySettings')); $tabs->addSubTab('show_default_options_settings', $this->plugin_object->txt('show_default_options_settings'), $ctrl->getLinkTargetByClass('ilassStackQuestionConfigGUI', 'showDefaultOptionsSettings')); $tabs->addSubTab('show_default_inputs_settings', $this->plugin_object->txt('show_default_inputs_settings'), $ctrl->getLinkTargetByClass('ilassStackQuestionConfigGUI', 'showDefaultInputsSettings')); $tabs->addSubTab('show_default_prts_settings', $this->plugin_object->txt('show_default_prts_settings'), $ctrl->getLinkTargetByClass('ilassStackQuestionConfigGUI', 'showDefaultPRTsSettings')); + $tabs->addSubTab('show_feedback_styles_settings', $this->plugin_object->txt('feedback_styles_settings'), $ctrl->getLinkTargetByClass('ilassStackQuestionConfigGUI', 'showFeedbackStylesSettings')); break; } } @@ -127,155 +131,151 @@ function configure() public function showConnectionSettings() { - global $DIC, $tpl; - $tabs = $DIC->tabs(); - $tabs->activateSubTab('basic_connection_settings'); + global $DIC, $tpl; + $tabs = $DIC->tabs(); + $tabs->activateSubTab('basic_connection_settings'); $form = $this->getConnectionSettingsForm(); $tpl->setContent($form->getHTML()); } public function showServerList() - { - global $DIC, $tpl; - $DIC->tabs()->activateSubTab('server_configuration'); - - $button = ilLinkButton::getInstance(); - $button->setCaption($this->plugin_object->txt('add_server'), false); - $button->setUrl($DIC->ctrl()->getLinkTarget($this, 'addServer')); - $DIC->toolbar()->addButtonInstance($button); - - $this->plugin_object->includeClass('GUI/tables/class.assStackQuestionServerTableGUI.php'); - $table = new assStackQuestionServerTableGUI($this, 'showServerList'); - $tpl->setContent($table->getHTML()); - } - - public function addServer() - { - global $DIC, $tpl; - $tabs = $DIC->tabs(); - $tabs->activateSubTab('server_configuration'); - - $form = $this->getServerSettingsForm(); - $tpl->setContent($form->getHTML()); - } - - public function editServer() - { - global $DIC, $tpl; - $tabs = $DIC->tabs(); - $tabs->activateSubTab('server_configuration'); - - $DIC->ctrl()->setParameter($this, 'server_id', $_GET['server_id']); - $button = ilLinkButton::getInstance(); - $button->setCaption($this->plugin_object->txt('show_healthcheck'), false); - $button->setUrl($DIC->ctrl()->getLinkTarget($this, 'runHealthcheck')); - $DIC->toolbar()->addButtonInstance($button); - - $form = $this->getServerSettingsForm($_GET['server_id']); - $tpl->setContent($form->getHTML()); - } - - - public function activateServers() - { - $this->changeServerActivation(true); - } - - public function deactivateServers() - { - $this->changeServerActivation(false); - } - - protected function changeServerActivation($active) - { - global $DIC; - - $this->plugin_object->includeClass("model/configuration/class.assStackQuestionServer.php"); - - if (isset($_POST['server_id'])) - { - $server_ids = (array) $_POST['server_id']; - } - elseif (isset($_GET['server_id'])) - { - $server_ids = (array) $_GET['server_id']; - } - - if (empty($server_ids)) - { - ilUtil::sendFailure($this->plugin_object->txt('no_server_selected'), true); - } - else - { - foreach ($server_ids as $server_id) - { - $server = assStackQuestionServer::getServerById($server_id); - $server->setActive($active); - } - assStackQuestionServer::saveServers(); - - if (count($server_ids) == 1) - { - ilUtil::sendSuccess($this->plugin_object->txt($active ? 'server_activated' : 'server_deactivated'), true); - } - else - { - ilUtil::sendSuccess($this->plugin_object->txt($active ? 'servers_activated' : 'servers_deactivated'), true); - } - } - $DIC->ctrl()->redirect($this, 'showServerList'); - } - - public function confirmDeleteServers() - { - global $DIC, $tpl; - - $this->plugin_object->includeClass("model/configuration/class.assStackQuestionServer.php"); - - if (isset($_POST['server_id'])) - { - $server_ids = (array) $_POST['server_id']; - } - elseif (isset($_GET['server_id'])) - { - $server_ids = (array) $_GET['server_id']; - } - - if (empty($server_ids)) - { - ilUtil::sendFailure($this->plugin_object->txt('no_server_selected'), true); - $DIC->ctrl()->redirect($this, 'showServerList'); - } - - $gui = new ilConfirmationGUI(); - $gui->setHeaderText($this->plugin_object->txt('confirm_delete_servers')); - $gui->setFormAction($DIC->ctrl()->getFormAction($this)); - $gui->setConfirm($DIC->language()->txt('delete'), 'deleteServers'); - $gui->setCancel($DIC->language()->txt('cancel'), 'showServerList'); - - foreach ($server_ids as $server_id) - { - $server = assStackQuestionServer::getServerById($server_id); - $gui->addItem('server_id[]', $server_id, $server->getAddress()); - } - $tpl->setContent($gui->getHTML()); - } - - public function deleteServers() - { - global $DIC; - $this->plugin_object->includeClass("model/configuration/class.assStackQuestionServer.php"); - - $server_ids = (array) $_POST['server_id']; - assStackQuestionServer::deleteServers($server_ids); - - ilUtil::sendSuccess($this->plugin_object->txt(count($server_ids) == 1 ? 'server_deleted' : 'servers_deleted'), true); - $DIC->ctrl()->redirect($this, 'showServerList'); - } - - - public function showOtherSettings() + { + global $DIC, $tpl; + $DIC->tabs()->activateSubTab('server_configuration'); + + $button = ilLinkButton::getInstance(); + $button->setCaption($this->plugin_object->txt('add_server'), false); + $button->setUrl($DIC->ctrl()->getLinkTarget($this, 'addServer')); + $DIC->toolbar()->addButtonInstance($button); + + $this->plugin_object->includeClass('GUI/tables/class.assStackQuestionServerTableGUI.php'); + $table = new assStackQuestionServerTableGUI($this, 'showServerList'); + $tpl->setContent($table->getHTML()); + } + + public function addServer() + { + global $DIC, $tpl; + $tabs = $DIC->tabs(); + $tabs->activateSubTab('server_configuration'); + + $form = $this->getServerSettingsForm(); + $tpl->setContent($form->getHTML()); + } + + public function editServer() + { + global $DIC, $tpl; + $tabs = $DIC->tabs(); + $tabs->activateSubTab('server_configuration'); + + $DIC->ctrl()->setParameter($this, 'server_id', $_GET['server_id']); + $button = ilLinkButton::getInstance(); + $button->setCaption($this->plugin_object->txt('show_healthcheck'), false); + $button->setUrl($DIC->ctrl()->getLinkTarget($this, 'runHealthcheck')); + $DIC->toolbar()->addButtonInstance($button); + + $form = $this->getServerSettingsForm($_GET['server_id']); + $tpl->setContent($form->getHTML()); + } + + + public function activateServers() + { + $this->changeServerActivation(true); + } + + public function deactivateServers() + { + $this->changeServerActivation(false); + } + + protected function changeServerActivation($active) + { + global $DIC; + + $this->plugin_object->includeClass("model/configuration/class.assStackQuestionServer.php"); + + if (isset($_POST['server_id'])) + { + $server_ids = (array)$_POST['server_id']; + } elseif (isset($_GET['server_id'])) + { + $server_ids = (array)$_GET['server_id']; + } + + if (empty($server_ids)) + { + ilUtil::sendFailure($this->plugin_object->txt('no_server_selected'), true); + } else + { + foreach ($server_ids as $server_id) + { + $server = assStackQuestionServer::getServerById($server_id); + $server->setActive($active); + } + assStackQuestionServer::saveServers(); + + if (count($server_ids) == 1) + { + ilUtil::sendSuccess($this->plugin_object->txt($active ? 'server_activated' : 'server_deactivated'), true); + } else + { + ilUtil::sendSuccess($this->plugin_object->txt($active ? 'servers_activated' : 'servers_deactivated'), true); + } + } + $DIC->ctrl()->redirect($this, 'showServerList'); + } + + public function confirmDeleteServers() + { + global $DIC, $tpl; + + $this->plugin_object->includeClass("model/configuration/class.assStackQuestionServer.php"); + + if (isset($_POST['server_id'])) + { + $server_ids = (array)$_POST['server_id']; + } elseif (isset($_GET['server_id'])) + { + $server_ids = (array)$_GET['server_id']; + } + + if (empty($server_ids)) + { + ilUtil::sendFailure($this->plugin_object->txt('no_server_selected'), true); + $DIC->ctrl()->redirect($this, 'showServerList'); + } + + $gui = new ilConfirmationGUI(); + $gui->setHeaderText($this->plugin_object->txt('confirm_delete_servers')); + $gui->setFormAction($DIC->ctrl()->getFormAction($this)); + $gui->setConfirm($DIC->language()->txt('delete'), 'deleteServers'); + $gui->setCancel($DIC->language()->txt('cancel'), 'showServerList'); + + foreach ($server_ids as $server_id) + { + $server = assStackQuestionServer::getServerById($server_id); + $gui->addItem('server_id[]', $server_id, $server->getAddress()); + } + $tpl->setContent($gui->getHTML()); + } + + public function deleteServers() + { + global $DIC; + $this->plugin_object->includeClass("model/configuration/class.assStackQuestionServer.php"); + + $server_ids = (array)$_POST['server_id']; + assStackQuestionServer::deleteServers($server_ids); + + ilUtil::sendSuccess($this->plugin_object->txt(count($server_ids) == 1 ? 'server_deleted' : 'servers_deleted'), true); + $DIC->ctrl()->redirect($this, 'showServerList'); + } + + + public function showOtherSettings() { global $DIC; $tabs = $DIC->tabs(); @@ -324,10 +324,21 @@ public function showDefaultPRTsSettings() $tpl->setContent($form->getHTML()); } + public function showFeedbackStylesSettings() + { + global $DIC, $tpl; + $tabs = $DIC->tabs(); + $tabs->setTabActive('show_other_settings'); + $tabs->setSubTabActive('show_feedback_styles_settings'); + + $form = $this->getFeedbackStylesSettingsForm(); + $tpl->setContent($form->getHTML()); + } + /** * Show the healthcheck screen - * @param bool $a_run run the healthcheck + * @param bool $a_run run the healthcheck */ public function showHealthcheck($a_run = false) { @@ -351,10 +362,10 @@ public function showHealthcheck($a_run = false) if ($a_run) { - if ($this->config->get('platform_type') == 'server') - { - ilUtil::sendInfo($this->plugin_object->txt('srv_address') . ':
'. assStackQuestionConfig::_getServerAddress()); - } + if ($this->config->get('platform_type') == 'server') + { + ilUtil::sendInfo($this->plugin_object->txt('srv_address') . ':
' . assStackQuestionConfig::_getServerAddress()); + } //Create Healthcheck $this->plugin_object->includeClass("model/configuration/class.assStackQuestionHealthcheck.php"); @@ -382,13 +393,13 @@ public function showHealthcheck($a_run = false) $tpl->setContent($toolbar->getHTML() . $result_html); } - /** - * Run a healthcheck - */ - public function runHealthcheck() - { - $this->showHealthcheck(true); - } + /** + * Run a healthcheck + */ + public function runHealthcheck() + { + $this->showHealthcheck(true); + } /* * FORMS CREATION METHODS @@ -453,26 +464,26 @@ public function getConnectionSettingsForm() $cas_result_caching->setValue('db'); $form->addItem($cas_result_caching); - if ($connection_data['platform_type'] == 'win') { - - //Maxima command - $maxima_command = new ilTextInputGUI($this->plugin_object->txt('maxima_command'), 'maxima_command'); - $maxima_command->setInfo($this->plugin_object->txt('maxima_command_info')); - $maxima_command->setValue($connection_data['maxima_command']); - $form->addItem($maxima_command); - } - elseif ($connection_data['platform_type'] == 'server') - { - $link = $DIC->ctrl()->getLinkTarget($this,'showServerList'); - $maxima_command = new ilNonEditableValueGUI($this->plugin_object->txt('maxima_command'), ''); - $maxima_command->setValue($this->plugin_object->txt('maxima_command_server')); - $maxima_command->setInfo(sprintf($this->plugin_object->txt('maxima_command_server_info'), $link)); - $form->addItem($maxima_command); - } - - if ($connection_data['platform_type'] == 'win' OR $connection_data['platform_type'] == 'server') - { - //Plot command + if ($connection_data['platform_type'] == 'win') + { + + //Maxima command + $maxima_command = new ilTextInputGUI($this->plugin_object->txt('maxima_command'), 'maxima_command'); + $maxima_command->setInfo($this->plugin_object->txt('maxima_command_info')); + $maxima_command->setValue($connection_data['maxima_command']); + $form->addItem($maxima_command); + } elseif ($connection_data['platform_type'] == 'server') + { + $link = $DIC->ctrl()->getLinkTarget($this, 'showServerList'); + $maxima_command = new ilNonEditableValueGUI($this->plugin_object->txt('maxima_command'), ''); + $maxima_command->setValue($this->plugin_object->txt('maxima_command_server')); + $maxima_command->setInfo(sprintf($this->plugin_object->txt('maxima_command_server_info'), $link)); + $form->addItem($maxima_command); + } + + if ($connection_data['platform_type'] == 'win' OR $connection_data['platform_type'] == 'server') + { + //Plot command $plot_command = new ilTextInputGUI($this->plugin_object->txt('plot_command'), 'plot_command'); $plot_command->setInfo($this->plugin_object->txt('plot_command_info')); $plot_command->setValue($connection_data['plot_command']); @@ -846,59 +857,135 @@ public function getDefaultPRTSettingsForm() } public function getServerSettingsForm($a_server_id = null) - { - global $DIC; - $ctrl = $DIC->ctrl(); - $lng = $DIC->language(); - - $this->plugin_object->includeClass("model/configuration/class.assStackQuestionServer.php"); - - if (isset($a_server_id) && $a_server_id > 0) - { - $server = assStackQuestionServer::getServerById($a_server_id); - $title = $this->plugin_object->txt('edit_server'); - $ctrl->setParameter($this, 'server_id', $a_server_id); - } - else - { - $server = assStackQuestionServer::getDefaultServer(); - $title = $this->plugin_object->txt('add_server'); - } - - $form = new ilPropertyFormGUI(); - $form->setTitle($title); - $form->setFormAction($ctrl->getFormAction($this)); - - // purpose - $options = []; - foreach (assStackQuestionServer::getPurposes() as $purpose) - { - $options[$purpose] = $this->plugin_object->txt('srv_purpose_' . $purpose); - } - $purpose = new ilSelectInputGUI($this->plugin_object->txt('srv_purpose'), 'purpose'); - $purpose->setInfo($this->plugin_object->txt('srv_purpose_info')); - $purpose->setRequired(true); - $purpose->setOptions($options); - $purpose->setValue($server->getPurpose()); - $form->addItem($purpose); - - $address = new ilTextInputGUI($this->plugin_object->txt('srv_address'), 'address'); - $address->setInfo($this->plugin_object->txt('srv_address_info')); - $address->setRequired(true); - $address->setValue($server->getAddress()); - $form->addItem($address); - - $active = new ilCheckboxInputGUI($lng->txt('active'), 'active'); - $active->setInfo($this->plugin_object->txt('srv_active_info')); - $active->setChecked($server->isActive()); - $form->addItem($active); - - $form->addCommandButton('saveServerSettings', $lng->txt('save')); - $form->addCommandButton('showServerList', $lng->txt('cancel')); - - return $form; - } + { + global $DIC; + $ctrl = $DIC->ctrl(); + $lng = $DIC->language(); + + $this->plugin_object->includeClass("model/configuration/class.assStackQuestionServer.php"); + + if (isset($a_server_id) && $a_server_id > 0) + { + $server = assStackQuestionServer::getServerById($a_server_id); + $title = $this->plugin_object->txt('edit_server'); + $ctrl->setParameter($this, 'server_id', $a_server_id); + } else + { + $server = assStackQuestionServer::getDefaultServer(); + $title = $this->plugin_object->txt('add_server'); + } + + $form = new ilPropertyFormGUI(); + $form->setTitle($title); + $form->setFormAction($ctrl->getFormAction($this)); + + // purpose + $options = []; + foreach (assStackQuestionServer::getPurposes() as $purpose) + { + $options[$purpose] = $this->plugin_object->txt('srv_purpose_' . $purpose); + } + $purpose = new ilSelectInputGUI($this->plugin_object->txt('srv_purpose'), 'purpose'); + $purpose->setInfo($this->plugin_object->txt('srv_purpose_info')); + $purpose->setRequired(true); + $purpose->setOptions($options); + $purpose->setValue($server->getPurpose()); + $form->addItem($purpose); + + $address = new ilTextInputGUI($this->plugin_object->txt('srv_address'), 'address'); + $address->setInfo($this->plugin_object->txt('srv_address_info')); + $address->setRequired(true); + $address->setValue($server->getAddress()); + $form->addItem($address); + + $active = new ilCheckboxInputGUI($lng->txt('active'), 'active'); + $active->setInfo($this->plugin_object->txt('srv_active_info')); + $active->setChecked($server->isActive()); + $form->addItem($active); + + $form->addCommandButton('saveServerSettings', $lng->txt('save')); + $form->addCommandButton('showServerList', $lng->txt('cancel')); + + return $form; + } + + public function getFeedbackStylesSettingsForm() + { + global $DIC; + $ctrl = $DIC->ctrl(); + $db = $DIC->database(); + $lng = $DIC->language(); + + require_once("./Services/Form/classes/class.ilPropertyFormGUI.php"); + $form = new ilPropertyFormGUI(); + $form->setFormAction($ctrl->getFormAction($this)); + + //Values from DB + $feedback_data = assStackQuestionConfig::_getStoredSettings('feedback'); + + //Get all Styles available + $styles_array = array(); + $styles_array["default"] = $lng->txt("default"); + + $query = "SELECT style_id, characteristic FROM style_char WHERE type = 'text_block'"; + $result = $db->query($query); + while ($row = $db->fetchAssoc($result)) + { + $style_name = $row["characteristic"]; + if (preg_match("#^STACK(.*)$#i", $style_name)) + { + $styles_array[$row["characteristic"]] = $row["characteristic"]; + } + } + + /* + * AS WE ARE USING THE TRUE/FALSE FEEDBACK FORMAT FIELD OF THE DATABASE + * WHICH IS NOT USED AT THE MOMENT, AND IS ALWAYS 0 OR 1. WE HAVE TO + * DEFINE VALUES FOR EACH OF THE FEEDBACK STYLES, BEGINNING BY 2, TO DISTINGUISH + * QUESTION WHICH USES THIS STYLES AND THOSE WHICH NOT. + */ + + //Feedback style for right responses ---> 2 + $right_responses = new ilSelectInputGUI($this->plugin_object->txt('feedback_node_right'), 'feedback_node_right'); + $right_responses->setOptions($styles_array); + $right_responses->setInfo($this->plugin_object->txt('feedback_node_right_info')); + $right_responses->setValue($feedback_data['feedback_node_right']); + $form->addItem($right_responses); + + //Feedback style for wrong responses ---> 3 + $wrong_responses = new ilSelectInputGUI($this->plugin_object->txt('feedback_node_wrong'), 'feedback_node_wrong'); + $wrong_responses->setOptions($styles_array); + $wrong_responses->setInfo($this->plugin_object->txt('feedback_node_wrong_info')); + $wrong_responses->setValue($feedback_data['feedback_node_wrong']); + $form->addItem($wrong_responses); + + //Feedback style for solution hint ---> 4 + $solution_hint = new ilSelectInputGUI($this->plugin_object->txt('feedback_solution_hint'), 'feedback_solution_hint'); + $solution_hint->setOptions($styles_array); + $solution_hint->setInfo($this->plugin_object->txt('feedback_solution_hint_info')); + $solution_hint->setValue($feedback_data['feedback_solution_hint']); + $form->addItem($solution_hint); + + //Feedback style for Extra Information ---> 5 + $extra_info = new ilSelectInputGUI($this->plugin_object->txt('feedback_extra_info'), 'feedback_extra_info'); + $extra_info->setOptions($styles_array); + $extra_info->setInfo($this->plugin_object->txt('feedback_extra_info_info')); + $extra_info->setValue($feedback_data['feedback_extra_info']); + $form->addItem($extra_info); + + //Feedback style for Plot ---> 6 + $plot_feedback = new ilSelectInputGUI($this->plugin_object->txt('feedback_plot_feedback'), 'feedback_plot_feedback'); + $plot_feedback->setOptions($styles_array); + $plot_feedback->setInfo($this->plugin_object->txt('feedback_plot_feedback_info')); + $plot_feedback->setValue($feedback_data['feedback_plot_feedback']); + $form->addItem($plot_feedback); + + $form->setTitle($this->plugin_object->txt('feedback_styles_settings')); + $form->addCommandButton("saveFeedbackStylesSettings", $this->plugin_object->txt("save")); + $form->addCommandButton("showFeedbackStylesSettings", $this->plugin_object->txt("cancel")); + return $form; + } public function clearCache() { @@ -992,33 +1079,44 @@ public function saveDefaultPRTsSettings() } public function saveServerSettings() - { - global $DIC, $tpl; - $form = $this->getServerSettingsForm($_GET['server_id']); - if ($form->checkInput()) - { - if (isset($_GET['server_id'])) - { - $server = assStackQuestionServer::getServerById($_GET['server_id']); - } - else - { - $server = assStackQuestionServer::getDefaultServer(); - } - $server->setPurpose($form->getInput('purpose')); - $server->setAddress($form->getInput('address')); - $server->setActive($form->getInput('active')); - $server->save(); - - ilUtil::sendSuccess($this->plugin_object->txt('server_saved'), true); - $DIC->ctrl()->redirect($this, 'showServerList'); - } - else - { - $form->setValuesByPost(); - $tpl->setContent($form->getHTML()); - } - } + { + global $DIC, $tpl; + $form = $this->getServerSettingsForm($_GET['server_id']); + if ($form->checkInput()) + { + if (isset($_GET['server_id'])) + { + $server = assStackQuestionServer::getServerById($_GET['server_id']); + } else + { + $server = assStackQuestionServer::getDefaultServer(); + } + $server->setPurpose($form->getInput('purpose')); + $server->setAddress($form->getInput('address')); + $server->setActive($form->getInput('active')); + $server->save(); + + ilUtil::sendSuccess($this->plugin_object->txt('server_saved'), true); + $DIC->ctrl()->redirect($this, 'showServerList'); + } else + { + $form->setValuesByPost(); + $tpl->setContent($form->getHTML()); + } + } + + public function saveFeedbackStylesSettings() + { + $ok = $this->config->saveFeedbackStyleSettings(); + if ($ok) + { + ilUtil::sendSuccess($this->plugin_object->txt('config_feedback_styles_changed_message')); + } else + { + ilUtil::sendFailure($this->plugin_object->txt('config_error_message')); + } + $this->showFeedbackStylesSettings(); + } /* diff --git a/classes/model/class.assStackQuestionStackQuestion.php b/classes/model/class.assStackQuestionStackQuestion.php index ca15248d..e75217da 100644 --- a/classes/model/class.assStackQuestionStackQuestion.php +++ b/classes/model/class.assStackQuestionStackQuestion.php @@ -469,10 +469,7 @@ public function addTeacherAnswersToSession(assStackQuestion $question) $response[$name] = $teacher_answer_casstring; } } - $session = $this->getSession(); - $session->add_vars($response); - $session->instantiate(); - $this->setSession($session); + $this->getSession()->add_vars($response); } /** diff --git a/classes/model/configuration/class.assStackQuestionConfig.php b/classes/model/configuration/class.assStackQuestionConfig.php index a20b400f..b329e791 100644 --- a/classes/model/configuration/class.assStackQuestionConfig.php +++ b/classes/model/configuration/class.assStackQuestionConfig.php @@ -317,6 +317,30 @@ public function saveDefaultInputsSettings() return TRUE; } + public function saveFeedbackStyleSettings() + { + //Old settings + $saved_feedback_data = self::_getStoredSettings('feedback'); + //New settings + $new_feedback_data = $this->getAdminInput(); + + //Checkboxes workaround + if (!array_key_exists('prt_simplify', $new_feedback_data)) + { + $new_feedback_data['prt_simplify'] = 1; + } + //Save to DB + foreach ($saved_feedback_data as $paremeter_name => $saved_value) + { + if (array_key_exists($paremeter_name, $new_feedback_data) AND $saved_feedback_data[$paremeter_name] != $new_feedback_data[$paremeter_name]) + { + $this->saveToDB($paremeter_name, $new_feedback_data[$paremeter_name], 'feedback'); + } + } + + return TRUE; + } + /** * Saves new default inputs settings to the DB */ diff --git a/classes/model/configuration/class.assStackQuestionHealthcheck.php b/classes/model/configuration/class.assStackQuestionHealthcheck.php index 706926b0..291b3e54 100644 --- a/classes/model/configuration/class.assStackQuestionHealthcheck.php +++ b/classes/model/configuration/class.assStackQuestionHealthcheck.php @@ -80,7 +80,7 @@ public function checkMaximaConnection() //texdisplaystyle $this->setMaximaConnectionStatus(html_writer::tag('p', stack_string('texdisplaystyle')), 'texdisplaystyle'); //healthchecksampledisplaytex - $this->setMaximaConnectionStatus(html_writer::tag('p', stack_string('healthchecksampledisplaytex')), 'healthchecksampledisplaytex'); + $this->setMaximaConnectionStatus(html_writer::tag('p', assStackQuestionUtils::_solveKeyBracketsBug(stack_string('healthchecksampledisplaytex'))), 'healthchecksampledisplaytex'); //texinlinestyle $this->setMaximaConnectionStatus(html_writer::tag('p', stack_string('texinlinestyle')), 'texinlinestyle'); //healthchecksampleinlinetex @@ -88,6 +88,7 @@ public function checkMaximaConnection() //healthchecklatexmathjax $this->setMaximaConnectionStatus(html_writer::tag('p', stack_string('healthchecklatexmathjax')), 'healthchecklatexmathjax'); + //Maxima configuration file // Try to list available versions of Maxima (linux only, without the DB). if ($this->config->platform !== 'win') diff --git a/classes/model/ilias_object/class.assStackQuestionPRTNode.php b/classes/model/ilias_object/class.assStackQuestionPRTNode.php index c0219af9..16d0f009 100644 --- a/classes/model/ilias_object/class.assStackQuestionPRTNode.php +++ b/classes/model/ilias_object/class.assStackQuestionPRTNode.php @@ -442,6 +442,7 @@ public function writePostData($prt_name, $node_name, $new_prt_name = "", $new_no $this->setTrueNextNode(ilUtil::stripSlashes($_POST[$prefix . '_pos_next'])); $this->setTrueAnswerNote(ilUtil::stripSlashes($_POST[$prefix . '_pos_answernote'] == NULL ? "" : $_POST[$prefix . '_pos_answernote'])); $this->setTrueFeedback(ilUtil::stripSlashes($_POST[$prefix . '_pos_specific_feedback'] == NULL ? "" : $_POST[$prefix . '_pos_specific_feedback'], true, $a_rte_tags)); + $this->setTrueFeedbackFormat(ilUtil::stripSlashes($_POST[$prefix . '_pos_feedback_class'])); $this->setFalseScore(ilUtil::stripSlashes($_POST[$prefix . '_neg_score']) == NULL ? 0 : ilUtil::stripSlashes($_POST[$prefix . '_neg_score'])); $this->setFalseScoreMode(ilUtil::stripSlashes($_POST[$prefix . '_neg_mod'])); @@ -449,6 +450,7 @@ public function writePostData($prt_name, $node_name, $new_prt_name = "", $new_no $this->setFalseNextNode(ilUtil::stripSlashes($_POST[$prefix . '_neg_next'])); $this->setFalseAnswerNote(ilUtil::stripSlashes($_POST[$prefix . '_neg_answernote'] == NULL ? "" : $_POST[$prefix . '_neg_answernote'])); $this->setFalseFeedback(ilUtil::stripSlashes($_POST[$prefix . '_neg_specific_feedback'] == NULL ? "" : $_POST[$prefix . '_neg_specific_feedback'], true, $a_rte_tags)); + $this->setFalseFeedbackFormat(ilUtil::stripSlashes($_POST[$prefix . '_neg_feedback_class'])); if ($new_prt_name) { diff --git a/classes/model/question_display/class.assStackQuestionDisplay.php b/classes/model/question_display/class.assStackQuestionDisplay.php index 603c1b64..089d84ba 100644 --- a/classes/model/question_display/class.assStackQuestionDisplay.php +++ b/classes/model/question_display/class.assStackQuestionDisplay.php @@ -263,14 +263,18 @@ private function replacementForPRTPlaceholders($prt, $prt_name, $in_test) { //feedback $string .= ''; } + return $string; } diff --git a/classes/model/question_evaluation/class.assStackQuestionFeedback.php b/classes/model/question_evaluation/class.assStackQuestionFeedback.php index 512dbb72..517dafe1 100644 --- a/classes/model/question_evaluation/class.assStackQuestionFeedback.php +++ b/classes/model/question_evaluation/class.assStackQuestionFeedback.php @@ -172,8 +172,27 @@ private function fillFeedback($prt_state) { foreach ($prt_state->__get('feedback') as $feedback_obj) { - $feedback .= $prt_state->substitue_variables_in_feedback($feedback_obj->feedback); - $feedback .= '
'; + switch ($feedback_obj->format) + { + case "2": + $feedback .= assStackQuestionUtils::_getFeedbackStyledText($prt_state->substitue_variables_in_feedback($feedback_obj->feedback), "feedback_node_right"); + break; + case "3": + $feedback .= assStackQuestionUtils::_getFeedbackStyledText($prt_state->substitue_variables_in_feedback($feedback_obj->feedback), "feedback_node_wrong"); + break; + case "4": + $feedback .= assStackQuestionUtils::_getFeedbackStyledText($prt_state->substitue_variables_in_feedback($feedback_obj->feedback), "feedback_solution_hint"); + break; + case "5": + $feedback .= assStackQuestionUtils::_getFeedbackStyledText($prt_state->substitue_variables_in_feedback($feedback_obj->feedback), "feedback_extra_info"); + break; + case "6": + $feedback .= assStackQuestionUtils::_getFeedbackStyledText($prt_state->substitue_variables_in_feedback($feedback_obj->feedback), "feedback_plot_feedback"); + break; + default: + $feedback .= $prt_state->substitue_variables_in_feedback($feedback_obj->feedback); + break; + } } } diff --git a/classes/utils/class.assStackQuestionUtils.php b/classes/utils/class.assStackQuestionUtils.php index 1b45b8ed..3d286293 100644 --- a/classes/utils/class.assStackQuestionUtils.php +++ b/classes/utils/class.assStackQuestionUtils.php @@ -146,10 +146,12 @@ public static function _getUserResponse($question_id, array $inputs, array $prev $current_response = array(); $user_response_from_db = array(); - if(sizeof($previous_response)){ + if (sizeof($previous_response)) + { foreach ($previous_response["prt"] as $prt_name => $prt_info) { - if(sizeof($prt_info["response"])){ + if (sizeof($prt_info["response"])) + { foreach ($prt_info["response"] as $input_name => $input_info) { $user_response_from_db[$input_name] = $input_info["value"]; @@ -179,7 +181,7 @@ public static function _getUserResponse($question_id, array $inputs, array $prev return $user_response; } - /** + /** * @param $user_response * @param $question_id * @param $inputs @@ -300,7 +302,7 @@ public static function _changeUserResponseStyle($user_response, $question_id, $i foreach ($inputs as $input_name => $input) { //If input is not matrix - if (is_subclass_of($input,"stack_dropdown_input")) + if (is_subclass_of($input, "stack_dropdown_input")) { $new_user_response_array['xqcas_input_' . $input_name . '_value'] = $input->maxima_to_response_array($user_response[$input_name]); } elseif (!is_a($input, 'stack_matrix_input')) @@ -641,4 +643,48 @@ public static function stack_output_castext($castext) return stack_maths::process_display_castext($castext); } + /** + * Returns the ID of each content styles available in the platform. + */ + public static function _getContentStylesAvailable() + { + global $DIC; + $db = $DIC->database(); + + $styles_id = array(); + $query = "SELECT DISTINCT id FROM style_data WHERE active = '1'"; + $result = $db->query($query); + while ($row = $db->fetchAssoc($result)) + { + $styles_id[] = $row["id"]; + } + + return $styles_id; + } + + /** + * Returns a text with a format from the content style + * @param $a_text + * @param $a_format + * @return string + */ + public static function _getFeedbackStyledText($a_text, $a_format) + { + //Get Styles assigned to Formats + $config_options = assStackQuestionConfig::_getStoredSettings("feedback"); + require_once "./Services/Style/Content/classes/class.ilObjStyleSheet.php"; + + //Return text depending Format + switch ($a_format) + { + case "feedback_default": + //Use default style of the platform + return $a_text; + default: + //Use specific feedback style + $style_assigned = $config_options[$a_format]; + return '
' . $a_text . '
'; + } + } + } diff --git a/lang/ilias_de.lang b/lang/ilias_de.lang index 02b7c04f..731621a8 100644 --- a/lang/ilias_de.lang +++ b/lang/ilias_de.lang @@ -431,4 +431,6 @@ servers_deactivated#:#Die Server wurden deaktiviert. no_server_selected#:#Bitte wählen Sie einen Server aus. confirm_delete_servers#:#Möchten Sie den/die folgenden Server löschen? server_deleted#:#Der Server wurde gelöscht. -servers_deleted#:#Die Server wurden gelöscht. \ No newline at end of file +servers_deleted#:#Die Server wurden gelöscht. +deletion_error_connected_node#:#You cannot delete this node as is connected to a PRT, please change the PRT structure to disconnect the node before delete it. +import_in_test_error#:#Import STACK questions from MoodleXML is not allowed in tests, please import it into a question pool before including it into a test. \ No newline at end of file diff --git a/lang/ilias_en.lang b/lang/ilias_en.lang index 799cfd91..206fe565 100644 --- a/lang/ilias_en.lang +++ b/lang/ilias_en.lang @@ -452,3 +452,5 @@ no_server_selected#:#Please select a server. confirm_delete_servers#:#Delete the following server(s)? server_deleted#:#The server is deleted. servers_deleted#:#The servers are deleted. +deletion_error_connected_node#:#You cannot delete this node as is connected to a PRT, please change the PRT structure to disconnect the node before delete it. +import_in_test_error#:#Import STACK questions from MoodleXML is not allowed in tests, please import it into a question pool before including it into a test. \ No newline at end of file diff --git a/plugin.php b/plugin.php index 26d350d5..f52435f2 100644 --- a/plugin.php +++ b/plugin.php @@ -8,12 +8,13 @@ $id = "xqcas"; // code version; must be changed for all code changes -$version = "3.0.22"; + +$version = "3.1.0"; // ilias min and max version; must always reflect the versions that should // run with the plugin -$ilias_min_version = "5.3.0"; -$ilias_max_version = "5.3.999"; +$ilias_min_version = "5.4.0"; +$ilias_max_version = "5.4.999"; // optional, but useful: Add one or more responsible persons and a contact email $responsible = "Fred Neumann, Jesus Copado"; diff --git a/sql/dbupdate.php b/sql/dbupdate.php index 03c70412..d2fe66db 100644 --- a/sql/dbupdate.php +++ b/sql/dbupdate.php @@ -737,4 +737,26 @@ $db->insert("xqcas_configuration", array('parameter_name' => array('text', "prt_neg_penalty"), 'value' => array('clob', '0'), 'group_name' => array('text', 'prts'))); $db->insert("xqcas_configuration", array('parameter_name' => array('text', "prt_neg_answernote"), 'value' => array('clob', 'prt1-0-F'), 'group_name' => array('text', 'prts'))); } -?> \ No newline at end of file +?> +<#36> + +<#37> +database(); +//Create feedback styles +if ($db->tableExists('xqcas_configuration')) +{ + //Feedback style 1 will be used as default, in case feedback_default is chosen, the value in true/false_feedback_format will be 1, and no specific style will be used, but platform style + $db->insert("xqcas_configuration", array('parameter_name' => array('text', "feedback_default"), 'value' => array('clob', ''), 'group_name' => array('text', 'feedback'))); + //Specific feedback formats. + $db->insert("xqcas_configuration", array('parameter_name' => array('text', "feedback_node_right"), 'value' => array('clob', ''), 'group_name' => array('text', 'feedback'))); + $db->insert("xqcas_configuration", array('parameter_name' => array('text', "feedback_node_wrong"), 'value' => array('clob', ''), 'group_name' => array('text', 'feedback'))); + $db->insert("xqcas_configuration", array('parameter_name' => array('text', "feedback_node_partially"), 'value' => array('clob', ''), 'group_name' => array('text', 'feedback'))); + $db->insert("xqcas_configuration", array('parameter_name' => array('text', "feedback_solution_hint"), 'value' => array('clob', ''), 'group_name' => array('text', 'feedback'))); + $db->insert("xqcas_configuration", array('parameter_name' => array('text', "feedback_extra_info"), 'value' => array('clob', ''), 'group_name' => array('text', 'feedback'))); + $db->insert("xqcas_configuration", array('parameter_name' => array('text', "feedback_plot_feedback"), 'value' => array('clob', ''), 'group_name' => array('text', 'feedback'))); +} +?> From ace1d5157a04e12062000b3a7ba7064ef4e61b39 Mon Sep 17 00:00:00 2001 From: jcopado Date: Mon, 24 Jun 2019 16:05:57 +0200 Subject: [PATCH 02/23] 3.1.1 --- .../class.assStackQuestionFeedbackGUI.php | 14 +- classes/class.assStackQuestionGUI.php | 37 ++-- classes/class.ilassStackQuestionConfigGUI.php | 47 ++++- .../class.assStackQuestionMoodleXMLExport.php | 3 + .../class.assStackQuestionConfig.php | 185 ++++++++++-------- .../class.assStackQuestionMoodleImport.php | 16 +- .../class.assStackQuestionDisplay.php | 9 +- .../class.assStackQuestionFeedback.php | 7 +- classes/utils/class.assStackQuestionUtils.php | 28 ++- lang/ilias_de.lang | 26 ++- lang/ilias_en.lang | 23 +-- plugin.php | 2 +- sql/dbupdate.php | 11 ++ 13 files changed, 255 insertions(+), 153 deletions(-) diff --git a/classes/GUI/question_display/class.assStackQuestionFeedbackGUI.php b/classes/GUI/question_display/class.assStackQuestionFeedbackGUI.php index 44a9a5d5..05177790 100644 --- a/classes/GUI/question_display/class.assStackQuestionFeedbackGUI.php +++ b/classes/GUI/question_display/class.assStackQuestionFeedbackGUI.php @@ -390,15 +390,12 @@ public function getQuestionTextFilledIn($mode = "correct") { $string = ""; //feedback - $string .= ''; - $deco_question_text = $string; + $deco_question_text = assStackQuestionUtils::_getFeedbackStyledText($string, "feedback_default"); } elseif ($mode == "user") { $deco_question_text = $question_text; @@ -417,16 +414,16 @@ private function replacementForPRTPlaceholders($prt, $prt_name, $input) { $string = ""; //feedback - $string .= ''; - return $string; + $config_options = assStackQuestionConfig::_getStoredSettings("feedback"); + + return assStackQuestionUtils::_getFeedbackStyledText($string, "feedback_default"); } private function getFilledInputUser($value) @@ -441,8 +438,7 @@ private function getQuestionHowToSolve($text) if ($text) { - $deco_how_to_solve = ''; + $deco_how_to_solve = assStackQuestionUtils::_getFeedbackStyledText($text,"feedback_default"); } return $deco_how_to_solve; diff --git a/classes/class.assStackQuestionGUI.php b/classes/class.assStackQuestionGUI.php index 6f7398aa..f4fd790a 100644 --- a/classes/class.assStackQuestionGUI.php +++ b/classes/class.assStackQuestionGUI.php @@ -482,12 +482,12 @@ public function getPreview($show_question_only = FALSE, $showInlineFeedback = fa $tpl->addCss($this->plugin->getStyleSheetLocation('css/qpl_xqcas_question_preview.css')); $tpl->addCss($this->plugin->getStyleSheetLocation('css/qpl_xqcas_question_display.css')); - //Include content Styles - $style_ids = assStackQuestionUtils::_getContentStylesAvailable(); - require_once "./Services/Style/Content/classes/class.ilObjStyleSheet.php"; - foreach ($style_ids as $id) + //Include content Style + $style_id = assStackQuestionUtils::_getActiveContentStyleId(); + if (strlen($style_id)) { - $tpl->addCss(ilObjStyleSheet::getContentStylePath((int)$id)); + require_once "./Services/Style/Content/classes/class.ilObjStyleSheet.php"; + $tpl->addCss(ilObjStyleSheet::getContentStylePath((int)$style_id)); } $questionoutput = $question_preview_gui->get(); @@ -576,12 +576,12 @@ public function getTestQuestionOutput($solutions, $show_specific_inline_feedback //Get question display data $tpl->addCss($this->plugin->getStyleSheetLocation('css/qpl_xqcas_question_display.css')); - //Include content Styles - $style_ids = assStackQuestionUtils::_getContentStylesAvailable(); - require_once "./Services/Style/Content/classes/class.ilObjStyleSheet.php"; - foreach ($style_ids as $id) + //Include content Style + $style_id = assStackQuestionUtils::_getActiveContentStyleId(); + if (strlen($style_id)) { - $tpl->addCss(ilObjStyleSheet::getContentStylePath((int)$id)); + require_once "./Services/Style/Content/classes/class.ilObjStyleSheet.php"; + $tpl->addCss(ilObjStyleSheet::getContentStylePath((int)$style_id)); } $value_format_user_response = assStackQuestionUtils::_getUserResponse($this->object->getId(), $this->object->getStackQuestion()->getInputs(), $feedback_data); @@ -651,7 +651,7 @@ function getSolutionOutput($active_id, $pass = NULL, $graphicalOutput = FALSE, $ { //User Solution //Returns user solution HTML - $solution_output = $this->getQuestionOutput($solutions, true, $show_feedback, TRUE); + $solution_output = $this->getQuestionOutput($solutions, FALSE, $show_feedback, TRUE); //2.3.12 add feedback to solution $solution_output .= $this->getSpecificFeedbackOutput($solutions); @@ -659,7 +659,7 @@ function getSolutionOutput($active_id, $pass = NULL, $graphicalOutput = FALSE, $ { //Correct solution //Returns best solution HTML. - $solution_output = $this->getQuestionOutput($solutions, FALSE, $show_feedback); + $solution_output = $this->getQuestionOutput($solutions, TRUE, $show_feedback); } $question_text = $this->object->getQuestion(); @@ -826,17 +826,12 @@ public function getQuestionOutput($solutions, $best_solution, $show_feedback, $j if ($show_feedback) { $string = ""; - //feedback - $string .= ''; - - $question_text = str_replace("[[feedback:" . $prt_name . "]]", $string, $question_text); + $question_text = str_replace("[[feedback:" . $prt_name . "]]", assStackQuestionUtils::_getFeedbackStyledText($string, "feedback_default"), $question_text); } } } @@ -918,15 +913,13 @@ public function getSpecificFeedbackOutput($userSolution) { $string = ""; //feedback - $string .= ''; - $specific_feedback = str_replace("[[feedback:" . $prt_name . "]]", $string, $specific_feedback); + + $specific_feedback = str_replace("[[feedback:" . $prt_name . "]]", assStackQuestionUtils::_getFeedbackStyledText($string, "feedback_default"), $specific_feedback); } else { $specific_feedback = str_replace("[[feedback:" . $prt_name . "]]", $this->object->getPlugin()->txt("preview_no_answer"), $specific_feedback); diff --git a/classes/class.ilassStackQuestionConfigGUI.php b/classes/class.ilassStackQuestionConfigGUI.php index 280fc42f..383bdb13 100644 --- a/classes/class.ilassStackQuestionConfigGUI.php +++ b/classes/class.ilassStackQuestionConfigGUI.php @@ -925,14 +925,31 @@ public function getFeedbackStylesSettingsForm() //Get all Styles available $styles_array = array(); - $styles_array["default"] = $lng->txt("default"); + $styles_array["0"] = $lng->txt("default"); - $query = "SELECT style_id, characteristic FROM style_char WHERE type = 'text_block'"; - $result = $db->query($query); - while ($row = $db->fetchAssoc($result)) + $stylesheet_active = $feedback_data["feedback_stylesheet_id"]; + + //Available standard styles + require_once "./Services/Style/Content/classes/class.ilObjStyleSheet.php"; + $available_styles = ilObjStyleSheet::_getStandardStyles(); + $available_styles[""] = $lng->txt("default"); + + //Feedback Stylesheet selection + $header = new ilFormSectionHeaderGUI(); + $header->setTitle($this->plugin_object->txt("feedback_stylesheet_id")); + $form->addItem($header); + + $feedback_stylesheet_id = new ilSelectInputGUI($this->plugin_object->txt('feedback_stylesheet_id'), 'feedback_stylesheet_id'); + $feedback_stylesheet_id->setOptions($available_styles); + $feedback_stylesheet_id->setInfo($this->plugin_object->txt('feedback_stylesheet_id_info')); + $feedback_stylesheet_id->setValue($feedback_data['feedback_stylesheet_id']); + $form->addItem($feedback_stylesheet_id); + + if (strlen($stylesheet_active)) { - $style_name = $row["characteristic"]; - if (preg_match("#^STACK(.*)$#i", $style_name)) + $query = "SELECT style_id, characteristic FROM style_char WHERE type = 'text_block' AND style_id = '" . $stylesheet_active . "' "; + $result = $db->query($query); + while ($row = $db->fetchAssoc($result)) { $styles_array[$row["characteristic"]] = $row["characteristic"]; } @@ -945,6 +962,23 @@ public function getFeedbackStylesSettingsForm() * QUESTION WHICH USES THIS STYLES AND THOSE WHICH NOT. */ + //General Feedback Style + $header = new ilFormSectionHeaderGUI(); + $header->setTitle($this->plugin_object->txt("feedback_default")); + $form->addItem($header); + + //Feedback DEFAULT style ---> 1 + $feedback_default = new ilSelectInputGUI($this->plugin_object->txt('feedback_default'), 'feedback_default'); + $feedback_default->setOptions($styles_array); + $feedback_default->setInfo($this->plugin_object->txt('feedback_default_info')); + $feedback_default->setValue($feedback_data['feedback_default']); + $form->addItem($feedback_default); + + //Nodes feedback + $header = new ilFormSectionHeaderGUI(); + $header->setTitle($this->plugin_object->txt("nodes_feedback")); + $form->addItem($header); + //Feedback style for right responses ---> 2 $right_responses = new ilSelectInputGUI($this->plugin_object->txt('feedback_node_right'), 'feedback_node_right'); $right_responses->setOptions($styles_array); @@ -980,7 +1014,6 @@ public function getFeedbackStylesSettingsForm() $plot_feedback->setValue($feedback_data['feedback_plot_feedback']); $form->addItem($plot_feedback); - $form->setTitle($this->plugin_object->txt('feedback_styles_settings')); $form->addCommandButton("saveFeedbackStylesSettings", $this->plugin_object->txt("save")); $form->addCommandButton("showFeedbackStylesSettings", $this->plugin_object->txt("cancel")); diff --git a/classes/export/MoodleXML/class.assStackQuestionMoodleXMLExport.php b/classes/export/MoodleXML/class.assStackQuestionMoodleXMLExport.php index 21d80b7d..c957b532 100644 --- a/classes/export/MoodleXML/class.assStackQuestionMoodleXMLExport.php +++ b/classes/export/MoodleXML/class.assStackQuestionMoodleXMLExport.php @@ -202,6 +202,7 @@ function toMoodleXML() $a_xml_writer->xmlElement("truepenalty", NULL, $node->getTruePenalty()); $a_xml_writer->xmlElement("truenextnode", NULL, $node->getTrueNextNode()); $a_xml_writer->xmlElement("trueanswernote", NULL, $node->getTrueAnswerNote()); + $a_xml_writer->xmlElement("truefeedbackformat", NULL, $node->getTrueFeedbackFormat()); $a_xml_writer->xmlStartTag("truefeedback", array("format" => "html")); $media = $this->getRTEMedia($node->getTrueFeedback()); @@ -214,6 +215,8 @@ function toMoodleXML() $a_xml_writer->xmlElement("falsepenalty", NULL, $node->getFalsePenalty()); $a_xml_writer->xmlElement("falsenextnode", NULL, $node->getFalseNextNode()); $a_xml_writer->xmlElement("falseanswernote", NULL, $node->getFalseAnswerNote()); + $a_xml_writer->xmlElement("falsefeedbackformat", NULL, $node->getFalseFeedbackFormat()); + $a_xml_writer->xmlStartTag("falsefeedback", array("format" => "html")); $media = $this->getRTEMedia($node->getFalseFeedback()); diff --git a/classes/model/configuration/class.assStackQuestionConfig.php b/classes/model/configuration/class.assStackQuestionConfig.php index b329e791..5c476779 100644 --- a/classes/model/configuration/class.assStackQuestionConfig.php +++ b/classes/model/configuration/class.assStackQuestionConfig.php @@ -15,11 +15,11 @@ */ class assStackQuestionConfig { - /** @var assStackQuestionServer */ - protected static $server; + /** @var assStackQuestionServer */ + protected static $server; - /** @var array */ - protected $settings; + /** @var array */ + protected $settings; public function __construct($plugin_object = "") @@ -32,19 +32,20 @@ public function __construct($plugin_object = "") */ - /** - * Get a configuration setting - * @param $name - * @return mixed - */ - public function get($name) - { - if (!isset($this->settings)) - { - $this->settings = self::_getStoredSettings('all'); - } - return $this->settings[$name]; - } + /** + * Get a configuration setting + * @param $name + * @return mixed + */ + public function get($name) + { + if (!isset($this->settings)) + { + $this->settings = self::_getStoredSettings('all'); + } + + return $this->settings[$name]; + } /** * This class can be called from anywhere to get configuration @@ -73,64 +74,66 @@ public static function _getStoredSettings($selector) } - /** - * Read the server configuration from a configuration array - * This avoids a second reading - * @param $config - */ + /** + * Read the server configuration from a configuration array + * This avoids a second reading + * @param $config + */ public static function _readServers($config) - { - require_once (__DIR__ . '/class.assStackQuestionServer.php'); - assStackQuestionServer::readServersFromConfig($config); - } - - - /** - * Get the maxima server address for the current request - * The chosen server is cached for the request - * - * @return string - */ - public static function _getServerAddress() - { - require_once (__DIR__ . '/class.assStackQuestionServer.php'); - - if (isset(self::$server)) - { - return self::$server->getAddress(); - } - - if (!empty($_REQUEST['server_id'])) - { - self::$server = assStackQuestionServer::getServerById($_REQUEST['server_id']); - return self::$server->getAddress(); - - } - - switch (strtolower($_GET['cmdClass'])) - { - case 'iltestplayerfixedquestionsetgui': - case 'iltestplayerrandomquestionsetgui': - case 'iltestplayerdynamicquestionsetgui': - $purpose = assStackQuestionServer::PURPOSE_RUN; - break; - - default: - switch (basename($_SERVER['SCRIPT_FILENAME'])) - { - case 'validation.php': - case 'instant_validiation.php': - $purpose= assStackQuestionServer::PURPOSE_RUN; - break; - default: - $purpose = assStackQuestionServer::PURPOSE_EDIT; - } - } - - - self::$server = assStackQuestionServer::getServerForPurpose($purpose); - return self::$server->getAddress(); - } + { + require_once(__DIR__ . '/class.assStackQuestionServer.php'); + assStackQuestionServer::readServersFromConfig($config); + } + + + /** + * Get the maxima server address for the current request + * The chosen server is cached for the request + * + * @return string + */ + public static function _getServerAddress() + { + require_once(__DIR__ . '/class.assStackQuestionServer.php'); + + if (isset(self::$server)) + { + return self::$server->getAddress(); + } + + if (!empty($_REQUEST['server_id'])) + { + self::$server = assStackQuestionServer::getServerById($_REQUEST['server_id']); + + return self::$server->getAddress(); + + } + + switch (strtolower($_GET['cmdClass'])) + { + case 'iltestplayerfixedquestionsetgui': + case 'iltestplayerrandomquestionsetgui': + case 'iltestplayerdynamicquestionsetgui': + $purpose = assStackQuestionServer::PURPOSE_RUN; + break; + + default: + switch (basename($_SERVER['SCRIPT_FILENAME'])) + { + case 'validation.php': + case 'instant_validiation.php': + $purpose = assStackQuestionServer::PURPOSE_RUN; + break; + default: + $purpose = assStackQuestionServer::PURPOSE_EDIT; + } + } + + + self::$server = assStackQuestionServer::getServerForPurpose($purpose); + + return self::$server->getAddress(); + } /* @@ -324,17 +327,29 @@ public function saveFeedbackStyleSettings() //New settings $new_feedback_data = $this->getAdminInput(); - //Checkboxes workaround - if (!array_key_exists('prt_simplify', $new_feedback_data)) + //Check if Content Style has changed, if changed set pther fields to 0, otherwise, save it with new values + if ($saved_feedback_data["feedback_stylesheet_id"] != $new_feedback_data["feedback_stylesheet_id"]) { - $new_feedback_data['prt_simplify'] = 1; - } - //Save to DB - foreach ($saved_feedback_data as $paremeter_name => $saved_value) + //Save to DB + foreach ($saved_feedback_data as $parameter_name => $saved_value) + { + if ($parameter_name != "feedback_stylesheet_id") + { + $this->saveToDB($parameter_name, "0", 'feedback'); + } else + { + $this->saveToDB($parameter_name, $new_feedback_data[$parameter_name], 'feedback'); + } + } + } else { - if (array_key_exists($paremeter_name, $new_feedback_data) AND $saved_feedback_data[$paremeter_name] != $new_feedback_data[$paremeter_name]) + //Save to DB modified dat + foreach ($saved_feedback_data as $paremeter_name => $saved_value) { - $this->saveToDB($paremeter_name, $new_feedback_data[$paremeter_name], 'feedback'); + if (array_key_exists($paremeter_name, $new_feedback_data) AND $saved_feedback_data[$paremeter_name] != $new_feedback_data[$paremeter_name]) + { + $this->saveToDB($paremeter_name, $new_feedback_data[$paremeter_name], 'feedback'); + } } } @@ -414,9 +429,9 @@ public function saveDefaultPRTsSettings() } /** - * Save a configuration setting to the database - * (needs to be public for assStackQuestionServer::saveServers) - * + * Save a configuration setting to the database + * (needs to be public for assStackQuestionServer::saveServers) + * * @param $parameter_name //Is the of the parameter to modify (this is the Primary Key in DB) * @param $value //Is the value of the parameter * @param $group_name //Is the selector for different categories of data diff --git a/classes/model/import/MoodleXML/class.assStackQuestionMoodleImport.php b/classes/model/import/MoodleXML/class.assStackQuestionMoodleImport.php index 4a56b987..b03becdf 100644 --- a/classes/model/import/MoodleXML/class.assStackQuestionMoodleImport.php +++ b/classes/model/import/MoodleXML/class.assStackQuestionMoodleImport.php @@ -575,7 +575,13 @@ private function getPRTNodesFromXML($data, $prt_name) $new_node->setTrueScore(strip_tags($prt_node['truescore'])); $new_node->setTruePenalty(strip_tags($prt_node['truepenalty'])); $new_node->setTrueAnswerNote($prt_node['trueanswernote']); - $new_node->setTrueFeedbackFormat(1); + if (isset($prt_node['truefeedbackformat'])) + { + $new_node->setTrueFeedbackFormat($prt_node['truefeedbackformat']); + } else + { + $new_node->setTrueFeedbackFormat(1); + } $mapping = $this->getMediaObjectsFromXML($prt_node['truefeedback'][0]['file']); $truefeedback = assStackQuestionUtils::_casTextConverter($this->replaceMediaObjectReferences($prt_node['truefeedback'][0]['text'], $mapping), $this->getQuestion()->getTitle(), TRUE); @@ -586,7 +592,13 @@ private function getPRTNodesFromXML($data, $prt_name) $new_node->setFalseScore(strip_tags($prt_node['falsescore'])); $new_node->setFalsePenalty(strip_tags($prt_node['falsepenalty'])); $new_node->setFalseAnswerNote($prt_node['falseanswernote']); - $new_node->setFalseFeedbackFormat(1); + if (isset($prt_node['falsefeedbackformat'])) + { + $new_node->setFalseFeedbackFormat($prt_node['falsefeedbackformat']); + } else + { + $new_node->setFalseFeedbackFormat(1); + } $mapping = $this->getMediaObjectsFromXML($prt_node['falsefeedback'][0]['file']); $falsefeedback = assStackQuestionUtils::_casTextConverter($this->replaceMediaObjectReferences($prt_node['falsefeedback'][0]['text'], $mapping), $this->getQuestion()->getTitle(), TRUE); diff --git a/classes/model/question_display/class.assStackQuestionDisplay.php b/classes/model/question_display/class.assStackQuestionDisplay.php index 089d84ba..93c07dda 100644 --- a/classes/model/question_display/class.assStackQuestionDisplay.php +++ b/classes/model/question_display/class.assStackQuestionDisplay.php @@ -262,7 +262,6 @@ private function replacementForPRTPlaceholders($prt, $prt_name, $in_test) if (sizeof($this->getInlineFeedback())) { //feedback - $string .= ''; } - return $string; + return assStackQuestionUtils::_getFeedbackStyledText($string, "feedback_default"); } /* @@ -561,10 +559,7 @@ public function replacementForValidationInput($input, $input_name, $in_test, $re } if (is_a($input, "stack_notes_input")) { - $string = ""; - $string .= ''; + $string = assStackQuestionUtils::_getFeedbackStyledText($this->getPlugin()->txt("notes_best_solution_message"), "feedback_default"); $result["value"] = $string; $result["display"] = ""; diff --git a/classes/model/question_evaluation/class.assStackQuestionFeedback.php b/classes/model/question_evaluation/class.assStackQuestionFeedback.php index 517dafe1..f21752b4 100644 --- a/classes/model/question_evaluation/class.assStackQuestionFeedback.php +++ b/classes/model/question_evaluation/class.assStackQuestionFeedback.php @@ -190,7 +190,7 @@ private function fillFeedback($prt_state) $feedback .= assStackQuestionUtils::_getFeedbackStyledText($prt_state->substitue_variables_in_feedback($feedback_obj->feedback), "feedback_plot_feedback"); break; default: - $feedback .= $prt_state->substitue_variables_in_feedback($feedback_obj->feedback); + $feedback .= assStackQuestionUtils::_getFeedbackStyledText($prt_state->substitue_variables_in_feedback($feedback_obj->feedback), "feedback_default"); break; } } @@ -515,10 +515,7 @@ public function getCorrectResponsePlaceholders($input_name = "") } if (is_a($input, "stack_notes_input")) { - $string = ""; - $string .= ''; + $string = assStackQuestionUtils::_getFeedbackStyledText($this->getPlugin()->txt("notes_best_solution_message"), "feedback_default"); $result["value"] = $string; $result["display"] = ""; diff --git a/classes/utils/class.assStackQuestionUtils.php b/classes/utils/class.assStackQuestionUtils.php index 3d286293..44a933dc 100644 --- a/classes/utils/class.assStackQuestionUtils.php +++ b/classes/utils/class.assStackQuestionUtils.php @@ -652,7 +652,7 @@ public static function _getContentStylesAvailable() $db = $DIC->database(); $styles_id = array(); - $query = "SELECT DISTINCT id FROM style_data WHERE active = '1'"; + $query = "SELECT id FROM style_data WHERE active = '1'"; $result = $db->query($query); while ($row = $db->fetchAssoc($result)) { @@ -678,13 +678,35 @@ public static function _getFeedbackStyledText($a_text, $a_format) switch ($a_format) { case "feedback_default": - //Use default style of the platform - return $a_text; + if ($config_options["feedback_default"] == "0") + { + return ''; + } else + { + $style_assigned = $config_options[$a_format]; + + return '
' . $a_text . '
'; + } default: //Use specific feedback style $style_assigned = $config_options[$a_format]; + return '
' . $a_text . '
'; } } + public static function _getActiveContentStyleId() + { + global $DIC; + $db = $DIC->database(); + + $styles_id = array(); + $query = "SELECT value FROM xqcas_configuration WHERE parameter_name = 'feedback_stylesheet_id'"; + $result = $db->query($query); + while ($row = $db->fetchAssoc($result)) + { + return $row["value"]; + } + } + } diff --git a/lang/ilias_de.lang b/lang/ilias_de.lang index 731621a8..0d342f4f 100644 --- a/lang/ilias_de.lang +++ b/lang/ilias_de.lang @@ -400,6 +400,25 @@ notes_best_solution_message#:#Notizen haben keine bestmögliche Lösung show_default_prts_settings#:#Vorgabewerte für Rückmeldebäume-Einstellungen default_prts_settings#:#Standard-Einstellungen für Rückmeldebäume und Knoten config_default_prts_message#:#Die Einstellungen für Rückmeldebäume wurden erfolgreich geändert. +prt_node_pos_feedback_class#:#Feedback-Style, wenn wahr +prt_node_pos_feedback_class_info#:#Wählen Sie den Feedback-Style, wenn der Answertest dieses Knotens wahr ist. +prt_node_neg_feedback_class#:#Feedback-Style, wenn falsch +prt_node_neg_feedback_class_info#:#Wählen Sie den Feedback-Style, wenn der Answertest dieses Knotens falsch ist. +feedback_styles_settings#:#Feedback-Style Einstellungen +feedback_styles_settings#:#Feedback-Style Einstellungen +feedback_node_right#:#Richtig +feedback_node_right_info#:#Feedback-Style für richtige Antworten +feedback_node_wrong#:#Falsch +feedback_node_wrong_info#:#Feedback-Style für falsche Antworten +feedback_solution_hint#:#Hinweis +feedback_solution_hint_info#:#Feedback-Style für Lösungshinweise +feedback_extra_info#:#Info +feedback_extra_info_info#:#Feedback-Style für zusätzliche Informationen +feedback_plot_feedback#:#Diagramm +feedback_plot_feedback_info#:#Für Diagramme benutzter Feedback-Style +config_feedback_styles_changed_message#:#Die Standardeinstellungen für Feedback-Style wurden erfolgreich geändert. +feedback_extra_1#:#Teilweise korrekt +feedback_extra_1_info#:#Feedback-Style für teilweise korrekte Antworten copy_node#:#Knoten kopieren paste_node#:#Knoten einfügen copy_prt#:# Rückmeldebaum kopieren @@ -433,4 +452,9 @@ confirm_delete_servers#:#Möchten Sie den/die folgenden Server löschen? server_deleted#:#Der Server wurde gelöscht. servers_deleted#:#Die Server wurden gelöscht. deletion_error_connected_node#:#You cannot delete this node as is connected to a PRT, please change the PRT structure to disconnect the node before delete it. -import_in_test_error#:#Import STACK questions from MoodleXML is not allowed in tests, please import it into a question pool before including it into a test. \ No newline at end of file +import_in_test_error#:#Import STACK questions from MoodleXML is not allowed in tests, please import it into a question pool before including it into a test. +feedback_stylesheet_id#:#Content-Style +feedback_stylesheet_id_info#:#Wählen Sie den Content-Style, der für das STACK Feedback verwendet wird. Es können nur aktive Content-Style ausgewählt werden. Wenn kein Inhaltsstil ausgewählt ist, wird der Standard-Feedback-Style verwendet. Bitte beachten Sie, dass bei einer Änderung des Inhaltsstils alle Werte in diesem Formular auf Standard zurückgesetzt werden. +feedback_default#:#Allgemeiner Feedback-Style +feedback_default_info#:#Wählen Sie den Feedback-Style für Feedback-Nachrichten in STACK-Fragen. Die meisten Feedback-Nachrichten, die Sie von diesem Fragetyp erhalten, haben diesen Stil, aber nicht das Feedback der möglichen Antwort-Knotenbäume. +nodes_feedback#:#Feedback von Knoten \ No newline at end of file diff --git a/lang/ilias_en.lang b/lang/ilias_en.lang index 206fe565..817b9d45 100644 --- a/lang/ilias_en.lang +++ b/lang/ilias_en.lang @@ -401,25 +401,21 @@ show_default_prts_settings#:#Default values for Potential response Trees and Fir default_prts_settings#:#Default values for Potential response Trees config_default_prts_message#:#The default settings for PRT have been changed successfully. prt_node_pos_feedback_class#:#Feedback Style if True -prt_node_pos_feedback_class_info#:#Choose the feedback style if this node's answertest is true, feedback style can be managed in plugin configuration. +prt_node_pos_feedback_class_info#:#Choose the feedback style if this node's answertest is true prt_node_neg_feedback_class#:#Feedback Style if False -prt_node_neg_feedback_class_info#:#Choose the feedback style if this node's answertest is false, feedback style can be managed in plugin configuration. +prt_node_neg_feedback_class_info#:#Choose the feedback style if this node's answertest is false feedback_styles_settings#:#Feedback Styles Settings -feedback_node_right#:#Right Answer +feedback_node_right#:#Right feedback_node_right_info#:#Feedback style for right answers -feedback_node_wrong#:#Wrong Answer +feedback_node_wrong#:#Wrong feedback_node_wrong_info#:#Feedback style for wrong answers -feedback_solution_hint#:#Solution Hint +feedback_solution_hint#:#Hint feedback_solution_hint_info#:#Feedback style for solution hints -feedback_extra_info#:#Extra Information +feedback_extra_info#:#Info feedback_extra_info_info#:#Feedback style used for extra information feedback_plot_feedback#:#Plot feedback_plot_feedback_info#:#Feedback style used for plots config_feedback_styles_changed_message#:#The default settings for Feedback Styles have been changed successfully. -feedback_extra_1#:#Partially correct -feedback_extra_1_info#:#Feedback style for partially correct answers -options_stepwise_feedback#:#Stepwise Feedback -options_stepwise_feedback_info#:#Allow students to evaluate each PRT separately without reload the page copy_node#:#Copy Node paste_node#:#Paste Node copy_prt#:#Copy Potential Response Tree @@ -453,4 +449,9 @@ confirm_delete_servers#:#Delete the following server(s)? server_deleted#:#The server is deleted. servers_deleted#:#The servers are deleted. deletion_error_connected_node#:#You cannot delete this node as is connected to a PRT, please change the PRT structure to disconnect the node before delete it. -import_in_test_error#:#Import STACK questions from MoodleXML is not allowed in tests, please import it into a question pool before including it into a test. \ No newline at end of file +import_in_test_error#:#Import STACK questions from MoodleXML is not allowed in tests, please import it into a question pool before including it into a test. +feedback_stylesheet_id#:#Content Style +feedback_stylesheet_id_info#:#Select the Content Style used for STACK Feedback. Only active content styles can be selected. If no Content Style is chosen the default feedback style will be applied. Please notice, in case you change the Content Style, all values in this form will be set to default. +feedback_default#:#General Feedback Style +feedback_default_info#:#Select the feedback style for feedback messages in STACK Questions. Most of the feedback messages you will get from this question type will have this style, but not the Potential Response Tree Nodes feedback. +nodes_feedback#:#Feedback from Nodes \ No newline at end of file diff --git a/plugin.php b/plugin.php index f52435f2..cf809688 100644 --- a/plugin.php +++ b/plugin.php @@ -9,7 +9,7 @@ // code version; must be changed for all code changes -$version = "3.1.0"; +$version = "3.1.1"; // ilias min and max version; must always reflect the versions that should // run with the plugin diff --git a/sql/dbupdate.php b/sql/dbupdate.php index d2fe66db..f540d21d 100644 --- a/sql/dbupdate.php +++ b/sql/dbupdate.php @@ -760,3 +760,14 @@ $db->insert("xqcas_configuration", array('parameter_name' => array('text', "feedback_plot_feedback"), 'value' => array('clob', ''), 'group_name' => array('text', 'feedback'))); } ?> +<#38> +database(); +//Create feedback styles +if ($db->tableExists('xqcas_configuration')) +{ + //We have to store the id of the content style we want to use for stack feedback styles + $db->insert("xqcas_configuration", array('parameter_name' => array('text', "feedback_stylesheet_id"), 'value' => array('clob', ''), 'group_name' => array('text', 'feedback'))); +} +?> From 75df04cec990a4552e78c689eee2e4f3bb894421 Mon Sep 17 00:00:00 2001 From: jcopado Date: Mon, 24 Jun 2019 16:13:16 +0200 Subject: [PATCH 03/23] 3.1.1 --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a2b03d33..0f4c8069 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ Version History * The stable version 2.4.x for **ILIAS 5.2 to 5.3** is found in the GitHub branch **master-ilias52** * The stable version 2.3.x for **ILIAS 5.0 to 5.1** is found in the GitHub branch **master** -Version 3.1.0 (2019-06-10) for ILIAS 5.4 +Version 3.1.1 (2019-06-24) for ILIAS 5.4 ---------------------------------------- -This version includes the changes needed to run STACK questions in ILIAS 5.4, together with the new feedback styles for node feedback, that can be managed through plugin configuration and Layout and Styles / Content styles. To select an specific feedback style you should create a new paragraph style class with a name starting with "STACK". \ No newline at end of file +This version includes the changes needed to run STACK questions in ILIAS 5.4. +* A new feature has been included: Feedback Styles, that can be managed through plugin configuration and Layout and Styles / Content styles. You can use your own content style for STACK feedback, In plugin configuration there is a new tab under General Settings / Feedback Styles Settings where settings for this new feature can be found. From 43fc6fe715868fd54b1e6840cc94b2233cd1a7d3 Mon Sep 17 00:00:00 2001 From: jcopado Date: Tue, 25 Jun 2019 15:55:34 +0200 Subject: [PATCH 04/23] 3.1.1 (Feedback style shown even if no text error solved) --- classes/utils/class.assStackQuestionUtils.php | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/classes/utils/class.assStackQuestionUtils.php b/classes/utils/class.assStackQuestionUtils.php index 44a933dc..ded317a5 100644 --- a/classes/utils/class.assStackQuestionUtils.php +++ b/classes/utils/class.assStackQuestionUtils.php @@ -675,24 +675,31 @@ public static function _getFeedbackStyledText($a_text, $a_format) require_once "./Services/Style/Content/classes/class.ilObjStyleSheet.php"; //Return text depending Format - switch ($a_format) + if (strlen($a_text)) { - case "feedback_default": - if ($config_options["feedback_default"] == "0") - { - return ''; - } else - { + switch ($a_format) + { + case "feedback_default": + if ($config_options["feedback_default"] == "0") + { + return ''; + } else + { + $style_assigned = $config_options[$a_format]; + + return '
' . $a_text . '
'; + } + default: + //Use specific feedback style $style_assigned = $config_options[$a_format]; return '
' . $a_text . '
'; - } - default: - //Use specific feedback style - $style_assigned = $config_options[$a_format]; - - return '
' . $a_text . '
'; + } + } else + { + return $a_text; } + } public static function _getActiveContentStyleId() From d8fae2afa99341a9f25cad57053a7b55de4323bc Mon Sep 17 00:00:00 2001 From: jcopado Date: Wed, 26 Jun 2019 12:49:29 +0200 Subject: [PATCH 05/23] 3.1.1 (Do not store style in DB but a placeholder, and manage style in the code to avoid problems when deleting styles) --- .../class.assStackQuestionDisplayGUI.php | 4 +-- .../class.assStackQuestionFeedbackGUI.php | 5 ++- classes/class.assStackQuestionGUI.php | 2 +- .../class.assStackQuestionFeedback.php | 13 ++++--- classes/utils/class.assStackQuestionUtils.php | 35 +++++++++++++++++++ 5 files changed, 48 insertions(+), 11 deletions(-) diff --git a/classes/GUI/question_display/class.assStackQuestionDisplayGUI.php b/classes/GUI/question_display/class.assStackQuestionDisplayGUI.php index 6ba5ae10..9e3e7071 100644 --- a/classes/GUI/question_display/class.assStackQuestionDisplayGUI.php +++ b/classes/GUI/question_display/class.assStackQuestionDisplayGUI.php @@ -254,9 +254,9 @@ private function replacePlaceholders($show_feedback = FALSE) { $display = $this->getDisplay('prts', $prt_name); } - $question_text = str_replace("[[feedback:{$prt_name}]]", $display['display'], $this->getDisplay('question_text')); + $question_text = str_replace("[[feedback:{$prt_name}]]", assStackQuestionUtils::_replaceFeedbackPlaceHolders($display['display']), $this->getDisplay('question_text')); $this->setDisplay($question_text, 'question_text'); - $question_specific_feedback = str_replace("[[feedback:{$prt_name}]]", $display['display'], $this->getDisplay('question_specific_feedback')); + $question_specific_feedback = str_replace("[[feedback:{$prt_name}]]", assStackQuestionUtils::_replaceFeedbackPlaceHolders($display['display']), $this->getDisplay('question_specific_feedback')); $this->setDisplay($question_specific_feedback, 'question_specific_feedback'); } } else diff --git a/classes/GUI/question_display/class.assStackQuestionFeedbackGUI.php b/classes/GUI/question_display/class.assStackQuestionFeedbackGUI.php index 05177790..61491cf4 100644 --- a/classes/GUI/question_display/class.assStackQuestionFeedbackGUI.php +++ b/classes/GUI/question_display/class.assStackQuestionFeedbackGUI.php @@ -412,13 +412,16 @@ public function getQuestionTextFilledIn($mode = "correct") */ private function replacementForPRTPlaceholders($prt, $prt_name, $input) { + /* + * THIS FUNCTION WORKS ONLY FOR TEST, FOR PREVIEW GO TO PREVIWEGUI + */ $string = ""; //feedback //Generic feedback $string .= $prt['status']['message']; //$string .= '
'; //Specific feedback - $string .= $prt['feedback']; + $string .= $this->replaceFeedbackPlaceHolders($prt['feedback']); $string .= $prt['errors']; $config_options = assStackQuestionConfig::_getStoredSettings("feedback"); diff --git a/classes/class.assStackQuestionGUI.php b/classes/class.assStackQuestionGUI.php index f4fd790a..30fbd737 100644 --- a/classes/class.assStackQuestionGUI.php +++ b/classes/class.assStackQuestionGUI.php @@ -916,7 +916,7 @@ public function getSpecificFeedbackOutput($userSolution) //Generic feedback $string .= $solutions["prt"][$prt_name]['status']['message']; //Specific feedback - $string .= $solutions["prt"][$prt_name]["feedback"]; + $string .= assStackQuestionUtils::_replaceFeedbackPlaceHolders($solutions["prt"][$prt_name]["feedback"]); $string .= $solutions["prt"][$prt_name]["errors"]; $specific_feedback = str_replace("[[feedback:" . $prt_name . "]]", assStackQuestionUtils::_getFeedbackStyledText($string, "feedback_default"), $specific_feedback); diff --git a/classes/model/question_evaluation/class.assStackQuestionFeedback.php b/classes/model/question_evaluation/class.assStackQuestionFeedback.php index f21752b4..01c69fbf 100644 --- a/classes/model/question_evaluation/class.assStackQuestionFeedback.php +++ b/classes/model/question_evaluation/class.assStackQuestionFeedback.php @@ -91,7 +91,6 @@ private function createPRTFeedback($prt_name, $prt_data) $prt_feedback['status'] = $this->fillStatus($prt_data['state']); //fill answernote $prt_feedback['answernote'] = $this->fillAnswerNote($prt_data['state']); - return $prt_feedback; } @@ -175,22 +174,22 @@ private function fillFeedback($prt_state) switch ($feedback_obj->format) { case "2": - $feedback .= assStackQuestionUtils::_getFeedbackStyledText($prt_state->substitue_variables_in_feedback($feedback_obj->feedback), "feedback_node_right"); + $feedback .= "[[feedback_node_right]]".$prt_state->substitue_variables_in_feedback($feedback_obj->feedback). "[[feedback_node_right_close]]"; break; case "3": - $feedback .= assStackQuestionUtils::_getFeedbackStyledText($prt_state->substitue_variables_in_feedback($feedback_obj->feedback), "feedback_node_wrong"); + $feedback .= "[[feedback_node_wrong]]".$prt_state->substitue_variables_in_feedback($feedback_obj->feedback). "[[feedback_node_wrong_close]]"; break; case "4": - $feedback .= assStackQuestionUtils::_getFeedbackStyledText($prt_state->substitue_variables_in_feedback($feedback_obj->feedback), "feedback_solution_hint"); + $feedback .= "[[feedback_solution_hint]]".$prt_state->substitue_variables_in_feedback($feedback_obj->feedback). "[[feedback_solution_hint_close]]"; break; case "5": - $feedback .= assStackQuestionUtils::_getFeedbackStyledText($prt_state->substitue_variables_in_feedback($feedback_obj->feedback), "feedback_extra_info"); + $feedback .= "[[feedback_extra_info]]".$prt_state->substitue_variables_in_feedback($feedback_obj->feedback). "[[feedback_extra_info_close]]"; break; case "6": - $feedback .= assStackQuestionUtils::_getFeedbackStyledText($prt_state->substitue_variables_in_feedback($feedback_obj->feedback), "feedback_plot_feedback"); + $feedback .= "[[feedback_plot_feedback]]".$prt_state->substitue_variables_in_feedback($feedback_obj->feedback). "[[feedback_plot_feedback_close]]"; break; default: - $feedback .= assStackQuestionUtils::_getFeedbackStyledText($prt_state->substitue_variables_in_feedback($feedback_obj->feedback), "feedback_default"); + $feedback .= $prt_state->substitue_variables_in_feedback($feedback_obj->feedback); break; } } diff --git a/classes/utils/class.assStackQuestionUtils.php b/classes/utils/class.assStackQuestionUtils.php index ded317a5..5655e4a0 100644 --- a/classes/utils/class.assStackQuestionUtils.php +++ b/classes/utils/class.assStackQuestionUtils.php @@ -716,4 +716,39 @@ public static function _getActiveContentStyleId() } } + public static function _replaceFeedbackPlaceHolders($feedback){ + //Get Styles assigned to Formats + $config_options = assStackQuestionConfig::_getStoredSettings("feedback"); + + $text = $feedback; + //Search for right feedback + $style_assigned = $config_options["feedback_node_right"]; + $text = str_replace("[[feedback_node_right]]", '
',$text); + $text = str_replace("[[feedback_node_right_close]]", '
',$text); + + //Search for wrong feedback + $style_assigned = $config_options["feedback_node_wrong"]; + $text = str_replace("[[feedback_node_wrong]]", '
',$text); + $text = str_replace("[[feedback_node_wrong_close]]", '
',$text); + + //Search for wrong feedback + $style_assigned = $config_options["feedback_solution_hint"]; + $text = str_replace("[[feedback_solution_hint]]", '
',$text); + $text = str_replace("[[feedback_solution_hint_close]]", '
',$text); + + //Replace Extra info + $style_assigned = $config_options["feedback_extra_info"]; + $text = str_replace("[[feedback_extra_info]]", '
',$text); + $text = str_replace("[[feedback_extra_info_close]]", '
',$text); + + //Replace Extra info + $style_assigned = $config_options["feedback_plot_feedback"]; + $text = str_replace("[[feedback_plot_feedback]]", '
',$text); + $text = str_replace("[[feedback_plot_feedback_close]]", '
',$text); + + return $text; + } + + + } From c4728396b4376789e2ea430bc99ae07edef53f18 Mon Sep 17 00:00:00 2001 From: jcopado Date: Mon, 1 Jul 2019 12:19:58 +0200 Subject: [PATCH 06/23] 3.1.1 (Do not store style in DB but a placeholder, and manage style in the code to avoid problems when deleting styles) --- README.md | 6 ++++ .../class.assStackQuestionAuthoringGUI.php | 36 +++++++++++++++++-- .../class.assStackQuestionConfig.php | 3 +- .../class.assStackQuestionDisplay.php | 20 +++++++++-- lang/ilias_de.lang | 3 +- lang/ilias_en.lang | 3 +- plugin.php | 2 +- 7 files changed, 64 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 0f4c8069..61a95aa5 100644 --- a/README.md +++ b/README.md @@ -92,3 +92,9 @@ Version 3.1.1 (2019-06-24) for ILIAS 5.4 ---------------------------------------- This version includes the changes needed to run STACK questions in ILIAS 5.4. * A new feature has been included: Feedback Styles, that can be managed through plugin configuration and Layout and Styles / Content styles. You can use your own content style for STACK feedback, In plugin configuration there is a new tab under General Settings / Feedback Styles Settings where settings for this new feature can be found. + +Version 3.1.2 (2019-07-01) for ILIAS 5.4 +---------------------------------------- +The following bugs have been solved: +- https://mantis.ilias.de/view.php?id=25256 About validation of matrix inputs after checking results in preview mode. +- https://mantis.ilias.de/view.php?id=25290 About default values for PRT and Nodes not working properly in non-new questions. \ No newline at end of file diff --git a/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php b/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php index ce3cbaae..0bd5e317 100644 --- a/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php +++ b/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php @@ -113,6 +113,10 @@ public function showAuthoringPanel() $this->getPlugin()->includeClass('utils/FormProperties/class.ilTabsFormPropertyGUI.php'); $this->getPlugin()->includeClass('utils/FormProperties/class.ilButtonFormPropertyGUI.php'); + //https://mantis.ilias.de/view.php?id=25290 + require_once('./Customizing/global/plugins/Modules/TestQuestionPool/Questions/assStackQuestion/classes/model/configuration/class.assStackQuestionConfig.php'); + $this->default = assStackQuestionConfig::_getStoredSettings("all"); + //Add general properties to form like question text, title, author... //ADD predefined input and validation fields if ($this->getQuestionGUI()->object->getQuestion() == "") @@ -120,8 +124,6 @@ public function showAuthoringPanel() $this->new_question = TRUE; $this->getQuestionGUI()->object->setQuestion("[[input:ans1]] [[validation:ans1]]"); $this->getQuestionGUI()->object->setPoints("1"); - require_once('./Customizing/global/plugins/Modules/TestQuestionPool/Questions/assStackQuestion/classes/model/configuration/class.assStackQuestionConfig.php'); - $this->default = assStackQuestionConfig::_getStoredSettings("all"); } //Add question title when blank @@ -268,9 +270,25 @@ public function addPRTs() $new_prt = new assStackQuestionPRT(-1, $this->getQuestionGUI()->object->getId()); $new_prt->setPRTName('new_prt'); $new_prt->setPRTValue(1); + //https://mantis.ilias.de/view.php?id=25290 + $new_prt->setAutoSimplify($this->default["prt_simplify"]); $new_prt->checkPRT(TRUE); + //https://mantis.ilias.de/view.php?id=25290 $new_prt_node = new assStackQuestionPRTNode(-1, $this->getQuestionGUI()->object->getId(), 'new_prt', '0', -1, -1); + $new_prt_node->setAnswerTest($this->default["prt_node_answer_test"]); + $new_prt_node->setQuiet($this->default["prt_node_quiet"]); + $new_prt_node->setTestOptions($this->default["prt_node_options"]); + + $new_prt_node->setTrueScoreMode($this->default["prt_pos_mod"]); + $new_prt_node->setFalseScoreMode($this->default["prt_neg_mod"]); + + $new_prt_node->setTrueScore($this->default["prt_pos_score"]); + $new_prt_node->setFalseScore($this->default["prt_neg_score"]); + + $new_prt_node->setTruePenalty($this->default["prt_pos_penalty"]); + $new_prt_node->setFalsePenalty($this->default["prt_neg_penalty"]); + $new_prt_node->checkPRTNode(TRUE); $new_prt->setPRTNodes(array('0' => $new_prt_node)); $new_prt->setFirstNodeName($new_prt->getFirstNodeName(TRUE)); @@ -764,6 +782,20 @@ public function getNodesPart(assStackQuestionPRT $prt, $container_width = "") if ($prt->getPRTName() != 'new_prt') { $new_prt_node = new assStackQuestionPRTNode(-1, $this->getQuestionGUI()->object->getId(), $prt->getPRTName(), $prt->getPRTName() . '_new_node', -1, -1); + //https://mantis.ilias.de/view.php?id=25290 + $new_prt_node->setAnswerTest($this->default["prt_node_answer_test"]); + $new_prt_node->setQuiet($this->default["prt_node_quiet"]); + $new_prt_node->setTestOptions($this->default["prt_node_options"]); + + $new_prt_node->setTrueScoreMode($this->default["prt_pos_mod"]); + $new_prt_node->setFalseScoreMode($this->default["prt_neg_mod"]); + + $new_prt_node->setTrueScore($this->default["prt_pos_score"]); + $new_prt_node->setFalseScore($this->default["prt_neg_score"]); + + $new_prt_node->setTruePenalty($this->default["prt_pos_penalty"]); + $new_prt_node->setFalsePenalty($this->default["prt_neg_penalty"]); + $new_prt_node->checkPRTNode(TRUE); $new_node_part = $this->getNodePart($prt, $new_prt_node); $new_node_part->setTitle($this->getPlugin()->txt('add_new_node')); diff --git a/classes/model/configuration/class.assStackQuestionConfig.php b/classes/model/configuration/class.assStackQuestionConfig.php index 5c476779..daad6db5 100644 --- a/classes/model/configuration/class.assStackQuestionConfig.php +++ b/classes/model/configuration/class.assStackQuestionConfig.php @@ -452,7 +452,8 @@ public function saveToDB($parameter_name, $value, $group_name) */ public function getAdminInput() { - $data = ilUtil::stripSlashesRecursive($_POST); + //https://mantis.ilias.de/view.php?id=25290 + $data = ilUtil::stripSlashesRecursive($_POST, FALSE); //Clean array unset($data['cmd']); diff --git a/classes/model/question_display/class.assStackQuestionDisplay.php b/classes/model/question_display/class.assStackQuestionDisplay.php index 93c07dda..9f39dc72 100644 --- a/classes/model/question_display/class.assStackQuestionDisplay.php +++ b/classes/model/question_display/class.assStackQuestionDisplay.php @@ -187,9 +187,16 @@ private function replacementForInputPlaceholders($input, $input_name, $in_test, //Solve problem with string input type if (is_array($student_answer)) { - if ($student_answer[$input_name] == NULL) + if (get_class($input) == 'stack_matrix_input') { - return ""; + //https://mantis.ilias.de/view.php?id=25256 + return $state->contentsdisplayed; + } else + { + if ($student_answer[$input_name] == NULL) + { + return ""; + } } } @@ -508,7 +515,14 @@ public function replacementForValidationInput($input, $input_name, $in_test, $re for ($j = 0; $j < $matrix_input_columns; $j++) { $user_matrix .= ""; - $user_filled_input = '' . $student_answer[$input_name][$input_name . "_sub_" . $i . "_" . $j] . ''; + //https://mantis.ilias.de/view.php?id=25256 + if ($in_test) + { + $user_filled_input = '' . $student_answer[$input_name][$input_name . "_sub_" . $i . "_" . $j] . ''; + } else + { + $user_filled_input = '' . $student_answer[$input_name . "_sub_" . $i . "_" . $j] . ''; + } $user_matrix .= $user_filled_input; $user_matrix .= ""; } diff --git a/lang/ilias_de.lang b/lang/ilias_de.lang index 0d342f4f..54dce19f 100644 --- a/lang/ilias_de.lang +++ b/lang/ilias_de.lang @@ -457,4 +457,5 @@ feedback_stylesheet_id#:#Content-Style feedback_stylesheet_id_info#:#Wählen Sie den Content-Style, der für das STACK Feedback verwendet wird. Es können nur aktive Content-Style ausgewählt werden. Wenn kein Inhaltsstil ausgewählt ist, wird der Standard-Feedback-Style verwendet. Bitte beachten Sie, dass bei einer Änderung des Inhaltsstils alle Werte in diesem Formular auf Standard zurückgesetzt werden. feedback_default#:#Allgemeiner Feedback-Style feedback_default_info#:#Wählen Sie den Feedback-Style für Feedback-Nachrichten in STACK-Fragen. Die meisten Feedback-Nachrichten, die Sie von diesem Fragetyp erhalten, haben diesen Stil, aber nicht das Feedback der möglichen Antwort-Knotenbäume. -nodes_feedback#:#Feedback von Knoten \ No newline at end of file +nodes_feedback#:#Feedback von Knoten +config_prts_changed_message#:#Änderungen wurden übernommen \ No newline at end of file diff --git a/lang/ilias_en.lang b/lang/ilias_en.lang index 817b9d45..85763f60 100644 --- a/lang/ilias_en.lang +++ b/lang/ilias_en.lang @@ -454,4 +454,5 @@ feedback_stylesheet_id#:#Content Style feedback_stylesheet_id_info#:#Select the Content Style used for STACK Feedback. Only active content styles can be selected. If no Content Style is chosen the default feedback style will be applied. Please notice, in case you change the Content Style, all values in this form will be set to default. feedback_default#:#General Feedback Style feedback_default_info#:#Select the feedback style for feedback messages in STACK Questions. Most of the feedback messages you will get from this question type will have this style, but not the Potential Response Tree Nodes feedback. -nodes_feedback#:#Feedback from Nodes \ No newline at end of file +nodes_feedback#:#Feedback from Nodes +config_prts_changed_message#:#Changes have been applied \ No newline at end of file diff --git a/plugin.php b/plugin.php index cf809688..a398f837 100644 --- a/plugin.php +++ b/plugin.php @@ -9,7 +9,7 @@ // code version; must be changed for all code changes -$version = "3.1.1"; +$version = "3.1.2"; // ilias min and max version; must always reflect the versions that should // run with the plugin From 7c47a18dd4f487ff382c4af1e450ec6a81791af8 Mon Sep 17 00:00:00 2001 From: Fred Neumann Date: Mon, 29 Jul 2019 12:17:13 +0200 Subject: [PATCH 07/23] Improved explanations of feedback styles --- lang/ilias_de.lang | 4 ++-- lang/ilias_en.lang | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lang/ilias_de.lang b/lang/ilias_de.lang index 54dce19f..f38ae1d0 100644 --- a/lang/ilias_de.lang +++ b/lang/ilias_de.lang @@ -454,8 +454,8 @@ servers_deleted#:#Die Server wurden gelöscht. deletion_error_connected_node#:#You cannot delete this node as is connected to a PRT, please change the PRT structure to disconnect the node before delete it. import_in_test_error#:#Import STACK questions from MoodleXML is not allowed in tests, please import it into a question pool before including it into a test. feedback_stylesheet_id#:#Content-Style -feedback_stylesheet_id_info#:#Wählen Sie den Content-Style, der für das STACK Feedback verwendet wird. Es können nur aktive Content-Style ausgewählt werden. Wenn kein Inhaltsstil ausgewählt ist, wird der Standard-Feedback-Style verwendet. Bitte beachten Sie, dass bei einer Änderung des Inhaltsstils alle Werte in diesem Formular auf Standard zurückgesetzt werden. +feedback_stylesheet_id_info#:#Wählen Sie den Content-Style, der für das STACK-Feedback verwendet wird. Es können nur aktive Content-Style ausgewählt werden. Wenn kein Inhaltsstil ausgewählt ist, wird der Standard-Feedback-Style verwendet. Bitte beachten Sie, dass bei einer Änderung des Inhaltsstils alle Werte in diesem Formular auf Standard zurückgesetzt werden. feedback_default#:#Allgemeiner Feedback-Style -feedback_default_info#:#Wählen Sie den Feedback-Style für Feedback-Nachrichten in STACK-Fragen. Die meisten Feedback-Nachrichten, die Sie von diesem Fragetyp erhalten, haben diesen Stil, aber nicht das Feedback der möglichen Antwort-Knotenbäume. +feedback_default_info#:#Wählen Sie den Feedback-Style für Feedback-Nachrichten in STACK-Fragen. Er wird für den Abschnitt einer Feedback-Nachricht von STACK verwendet. Innerhalb dieses Abschnitts sind die Feedbacks der Knoten eines Rückmeldebaums eingebettet, die zusätzlich mit eigenen Styles versehen werden können. nodes_feedback#:#Feedback von Knoten config_prts_changed_message#:#Änderungen wurden übernommen \ No newline at end of file diff --git a/lang/ilias_en.lang b/lang/ilias_en.lang index 85763f60..1ccaebc1 100644 --- a/lang/ilias_en.lang +++ b/lang/ilias_en.lang @@ -451,8 +451,8 @@ servers_deleted#:#The servers are deleted. deletion_error_connected_node#:#You cannot delete this node as is connected to a PRT, please change the PRT structure to disconnect the node before delete it. import_in_test_error#:#Import STACK questions from MoodleXML is not allowed in tests, please import it into a question pool before including it into a test. feedback_stylesheet_id#:#Content Style -feedback_stylesheet_id_info#:#Select the Content Style used for STACK Feedback. Only active content styles can be selected. If no Content Style is chosen the default feedback style will be applied. Please notice, in case you change the Content Style, all values in this form will be set to default. +feedback_stylesheet_id_info#:#Select the content style used for STACK Feedback. Only active content styles can be selected. If no content style is chosen the default feedback style will be applied. Please notice, in case you change the content style, all values in this form will be set to default. feedback_default#:#General Feedback Style -feedback_default_info#:#Select the feedback style for feedback messages in STACK Questions. Most of the feedback messages you will get from this question type will have this style, but not the Potential Response Tree Nodes feedback. +feedback_default_info#:#Select the feedback style for feedback messages in STACK questions. It is used for the section of a STACK feedback message. Within this section, the feedbacks of the nodes of a potential response tree are embedded, which can also be provided with their own styles. nodes_feedback#:#Feedback from Nodes config_prts_changed_message#:#Changes have been applied \ No newline at end of file From 1543eb1d280cf802c28d1558278fcfc649e975d2 Mon Sep 17 00:00:00 2001 From: jcopado Date: Wed, 31 Jul 2019 14:36:58 +0200 Subject: [PATCH 08/23] 3.1.3 --- README.md | 7 ++- .../class.assStackQuestionAuthoringGUI.php | 51 +++++-------------- lang/ilias_de.lang | 4 +- lang/ilias_en.lang | 4 +- plugin.php | 2 +- 5 files changed, 24 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 61a95aa5..eaf210f3 100644 --- a/README.md +++ b/README.md @@ -97,4 +97,9 @@ Version 3.1.2 (2019-07-01) for ILIAS 5.4 ---------------------------------------- The following bugs have been solved: - https://mantis.ilias.de/view.php?id=25256 About validation of matrix inputs after checking results in preview mode. -- https://mantis.ilias.de/view.php?id=25290 About default values for PRT and Nodes not working properly in non-new questions. \ No newline at end of file +- https://mantis.ilias.de/view.php?id=25290 About default values for PRT and Nodes not working properly in non-new questions. + +Version 3.1.3 (2019-07-31) for ILIAS 5.4 +---------------------------------------- +Some small changes has been made in language variables +Now all feedback Types are always displayed in the authoring interface also if no content style has been chosen in the plugin configuration. \ No newline at end of file diff --git a/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php b/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php index 0bd5e317..8685ec5d 100644 --- a/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php +++ b/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php @@ -1243,48 +1243,23 @@ public function getFeedbackOptions() { global $DIC; $lng = $DIC->language(); - require_once('./Customizing/global/plugins/Modules/TestQuestionPool/Questions/assStackQuestion/classes/model/configuration/class.assStackQuestionConfig.php'); $options = array(); //Add default option - $options[1] = $lng->txt("default"); - $config_options = assStackQuestionConfig::_getStoredSettings("feedback"); - foreach ($config_options as $option => $css_class) - { - if ($css_class != "") - { - /* - * AS WE ARE USING THE TRUE/FALSE FEEDBACK FORMAT FIELD OF THE DATABASE - * WHICH IS NOT USED AT THE MOMENT, AND IS ALWAYS 0 OR 1. WE HAVE TO - * DEFINE VALUES FOR EACH OF THE FEEDBACK STYLES, BEGINNING BY 2, TO DISTINGUISH - * QUESTION WHICH USES THIS STYLES AND THOSE WHICH NOT. - */ - - switch ($option) - { - case "feedback_node_right": - $options[2] = $this->getPlugin()->txt($option); - break; - case "feedback_node_wrong": - $options[3] = $this->getPlugin()->txt($option); - break; - case "feedback_solution_hint": - $options[4] = $this->getPlugin()->txt($option); - break; - case "feedback_extra_info": - $options[5] = $this->getPlugin()->txt($option); - break; - case "feedback_plot_feedback": - $options[6] = $this->getPlugin()->txt($option); - break; - case "feedback_extra_1": - $options[7] = $this->getPlugin()->txt($option); - break; - default: - } - } - } + /* + * AS WE ARE USING THE TRUE/FALSE FEEDBACK FORMAT FIELD OF THE DATABASE + * WHICH IS NOT USED AT THE MOMENT, AND IS ALWAYS 0 OR 1. WE HAVE TO + * DEFINE VALUES FOR EACH OF THE FEEDBACK STYLES, BEGINNING BY 2, TO DISTINGUISH + * QUESTION WHICH USES THIS STYLES AND THOSE WHICH NOT. + */ + + $options[1] = $lng->txt("default"); + $options[2] = $this->getPlugin()->txt("feedback_node_right"); + $options[3] = $this->getPlugin()->txt("feedback_node_wrong"); + $options[4] = $this->getPlugin()->txt("feedback_solution_hint"); + $options[5] = $this->getPlugin()->txt("feedback_extra_info"); + $options[6] = $this->getPlugin()->txt("feedback_plot_feedback"); return $options; } diff --git a/lang/ilias_de.lang b/lang/ilias_de.lang index f38ae1d0..429e726d 100644 --- a/lang/ilias_de.lang +++ b/lang/ilias_de.lang @@ -407,9 +407,9 @@ prt_node_neg_feedback_class_info#:#Wählen Sie den Feedback-Style, wenn der Answ feedback_styles_settings#:#Feedback-Style Einstellungen feedback_styles_settings#:#Feedback-Style Einstellungen feedback_node_right#:#Richtig -feedback_node_right_info#:#Feedback-Style für richtige Antworten +feedback_node_right_info#:#Feedback-Typ für richtige Antworten feedback_node_wrong#:#Falsch -feedback_node_wrong_info#:#Feedback-Style für falsche Antworten +feedback_node_wrong_info#:#Feedback-Typ für falsche Antworten feedback_solution_hint#:#Hinweis feedback_solution_hint_info#:#Feedback-Style für Lösungshinweise feedback_extra_info#:#Info diff --git a/lang/ilias_en.lang b/lang/ilias_en.lang index 1ccaebc1..45eb8eef 100644 --- a/lang/ilias_en.lang +++ b/lang/ilias_en.lang @@ -400,9 +400,9 @@ notes_best_solution_message#:#Notes inputs have no best solution show_default_prts_settings#:#Default values for Potential response Trees and First nodes default_prts_settings#:#Default values for Potential response Trees config_default_prts_message#:#The default settings for PRT have been changed successfully. -prt_node_pos_feedback_class#:#Feedback Style if True +prt_node_pos_feedback_class#:#Feedback Type if True prt_node_pos_feedback_class_info#:#Choose the feedback style if this node's answertest is true -prt_node_neg_feedback_class#:#Feedback Style if False +prt_node_neg_feedback_class#:#Feedback Type if False prt_node_neg_feedback_class_info#:#Choose the feedback style if this node's answertest is false feedback_styles_settings#:#Feedback Styles Settings feedback_node_right#:#Right diff --git a/plugin.php b/plugin.php index a398f837..052525d7 100644 --- a/plugin.php +++ b/plugin.php @@ -9,7 +9,7 @@ // code version; must be changed for all code changes -$version = "3.1.2"; +$version = "3.1.3"; // ilias min and max version; must always reflect the versions that should // run with the plugin From df7c57497e5ad06bca6d3c1c298c0a128eaddea0 Mon Sep 17 00:00:00 2001 From: jcopado Date: Fri, 23 Aug 2019 15:45:01 +0200 Subject: [PATCH 09/23] 3.1.4 --- README.md | 6 +- .../class.assStackQuestionAuthoringGUI.php | 9 +- .../class.assStackQuestionMoodleImport.php | 646 +++++++++++++++++- .../class.assStackQuestionDisplay.php | 2 +- classes/stack/cas/cassession.class.php | 2 +- classes/stack/cas/casstring.class.php | 2 +- classes/stack/cas/castext.class.php | 8 +- .../stack/input/checkbox/checkbox.class.php | 12 +- classes/utils/class.assStackQuestionUtils.php | 12 + plugin.php | 2 +- 10 files changed, 678 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index eaf210f3..a016c372 100644 --- a/README.md +++ b/README.md @@ -102,4 +102,8 @@ The following bugs have been solved: Version 3.1.3 (2019-07-31) for ILIAS 5.4 ---------------------------------------- Some small changes has been made in language variables -Now all feedback Types are always displayed in the authoring interface also if no content style has been chosen in the plugin configuration. \ No newline at end of file +Now all feedback Types are always displayed in the authoring interface also if no content style has been chosen in the plugin configuration. + +Version 3.1.4 (2019-08-23) for ILIAS 5.4 +---------------------------------------- +This version includes support for PHP 7.2 in ILIAS 5.4 platform, during the process of update this plugin some ILIAS core bugs were found (e.g. importing question pools), those non-STACk related bugs can make the experience of using the plugin in a PHP 7.2 installation not smooth as intended, if you find any bugs in a PHP 7.2 platform, please report it in Mantis. \ No newline at end of file diff --git a/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php b/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php index 8685ec5d..5b704a0c 100644 --- a/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php +++ b/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php @@ -1121,11 +1121,14 @@ public function manageErrorMessages() $session_error_message = ""; $session_info_message = ""; - if (sizeof($_SESSION["stack_authoring_errors"][$this->getQuestionGUI()->object->getId()])) + if (isset($_SESSION["stack_authoring_errors"][$this->getQuestionGUI()->object->getId()])) { - foreach ($_SESSION["stack_authoring_errors"][$this->getQuestionGUI()->object->getId()] as $session_error) + if (sizeof($_SESSION["stack_authoring_errors"][$this->getQuestionGUI()->object->getId()])) { - $session_error_message .= $session_error . "
"; + foreach ($_SESSION["stack_authoring_errors"][$this->getQuestionGUI()->object->getId()] as $session_error) + { + $session_error_message .= $session_error . "
"; + } } } diff --git a/classes/model/import/MoodleXML/class.assStackQuestionMoodleImport.php b/classes/model/import/MoodleXML/class.assStackQuestionMoodleImport.php index b03becdf..3ece33cb 100644 --- a/classes/model/import/MoodleXML/class.assStackQuestionMoodleImport.php +++ b/classes/model/import/MoodleXML/class.assStackQuestionMoodleImport.php @@ -96,6 +96,13 @@ public function importQuestions($raw_data) { $number_of_questions_created = 0; //For each question in the array + + //Check if is PHP 7.2 in case it is, data need some extra formatting + if (assStackQuestionUtils::_isPhP72()) + { + $raw_data = $this->php72Format($raw_data['question']); + } + foreach ($raw_data['question'] as $data) { // start with a new list of media objects for each question @@ -193,7 +200,7 @@ public function importQuestions($raw_data) $this->purgeMediaObjects(); } } - if (sizeof($this->error_log)) + if (!empty($this->error_log)) { ilUtil::sendFailure(implode('
', $this->error_log)); } @@ -286,7 +293,7 @@ private function cleanXML($xml_data) { foreach ($xml_data as $array) { - if (sizeof($array) > 1) + if (!empty($array)) { return $array; } @@ -721,7 +728,7 @@ private function getExtraInfoFromXML($data) /** * Create media objects from array converted file elements - * @param array $data [['_attributes' => ['name' => string, 'path' => string], '_content' => string], ...] + * @param array $data [['_attributes' => ['name' => string, 'path' => string], '_content' => string], ...] * @return array filename => object_id */ private function getMediaObjectsFromXML($data = array()) @@ -747,8 +754,8 @@ private function getMediaObjectsFromXML($data = array()) /** * Replace references to media objects in a text - * @param string text from moodleXML with local references - * @param array mapping of filenames to media object IDs + * @param string text from moodleXML with local references + * @param array mapping of filenames to media object IDs * @return string text with paths to media objects */ private function replaceMediaObjectReferences($text = "", $mapping = array()) @@ -886,7 +893,7 @@ public function checkQuestion(assStackQuestion $question) } //Step 5: Check tests - if (sizeof($question->getTests())) + if (!empty($question->getTests())) { foreach ($question->getTests() as $test) { @@ -1004,4 +1011,631 @@ public function getRTETags() { return $this->rte_tags; } + + public function php72Format($raw_data) + { + $full_data = array(); + + foreach ($raw_data as $question_data) + { + $data = array(); + //Check for not category + if (is_array($question_data['category'])) + { + continue; + } + + //Question Name + $data['name'][0]['text'] = $question_data['name'][0]['text'][0]["_content"]; + + //Question text + $data['questiontext'][0]['text'] = $question_data['questiontext'][0]['text']; + + //General feedback + $data['generalfeedback'][0]['text'] = $question_data['generalfeedback'][0]['text']; + + //default grade + $data['defaultgrade'] = $question_data['defaultgrade'][0]["_content"]; + + //penalty + $data['penalty'] = $question_data['penalty'][0]["_content"]; + + //hidden + if (isset($question_data['hidden'][0]["_content"])) + { + $data['hidden'] = $question_data['hidden'][0]["_content"]; + } else + { + $data['hidden'] = ""; + } + + //stackversion + if (isset($question_data['stackversion'][0]["_content"])) + { + $data['stackversion'][0]['text'] = $question_data['stackversion'][0]['text']; + } else + { + $data['stackversion'][0]['text'] = ""; + } + + //questionvariables 2 versions to solve problems with question variables tarting with comments + if (isset($question_data['questionvariables'][0]['text'][0]['_content'])) + { + $data['questionvariables'][0]['text'] = $question_data['questionvariables'][0]['text'][0]['_content']; + } elseif (isset($question_data['questionvariables'][0]['text']) AND is_string($question_data['questionvariables'][0]['text'])) + { + $data['questionvariables'][0]['text'] = $question_data['questionvariables'][0]['text']; + } else + { + $data['questionvariables'][0]['text'] = ""; + } + + //specificfeedback: + if (isset($question_data['specificfeedback'][0]['text'][0]['_content'])) + { + $data['specificfeedback'][0]['text'] = $question_data['specificfeedback'][0]['text'][0]['_content']; + } elseif (isset($question_data['specificfeedback'][0]['text']) AND is_string($question_data['specificfeedback'][0]['text'])) + { + $data['specificfeedback'][0]['text'] = $question_data['specificfeedback'][0]['text']; + } else + { + $data['specificfeedback'][0]['text'] = ""; + } + + //questionnote + if (isset($question_data['questionnote'][0]['text'][0]['_content'])) + { + $data['questionnote'][0]['text'] = $question_data['questionnote'][0]['text'][0]['_content']; + } elseif (isset($question_data['questionnote'][0]['text']) AND is_string($question_data['questionnote'][0]['text'])) + { + $data['questionnote'][0]['text'] = $question_data['questionnote'][0]['text']; + }else + { + $data['questionnote'][0]['text'] = ""; + } + + //questionsimplify + if (isset($question_data['questionsimplify'][0]["_content"])) + { + $data['questionsimplify'] = $question_data['questionsimplify'][0]["_content"]; + } else + { + $data['questionsimplify'] = ""; + } + + //assumepositive + if (isset($question_data['assumepositive'][0]["_content"])) + { + $data['assumepositive'] = $question_data['assumepositive'][0]["_content"]; + } else + { + $data['assumepositive'] = ""; + } + + //assumereal + if (isset($question_data['assumereal'][0]["_content"])) + { + $data['assumereal'] = $question_data['assumereal'][0]["_content"]; + } else + { + $data['assumereal'] = ""; + } + + //prtcorrect + if (isset($question_data['prtcorrect'][0]["_content"])) + { + $data['prtcorrect'][0]['text'] = $question_data['prtcorrect'][0]['text']; + } else + { + $data['prtcorrect'][0]['text'] = ""; + } + + //prtpartiallycorrect + if (isset($question_data['prtpartiallycorrect'][0]["_content"])) + { + $data['prtpartiallycorrect'][0]['text'] = $question_data['prtpartiallycorrect'][0]['text']; + } else + { + $data['prtpartiallycorrect'][0]['text'] = ""; + } + + //prtincorrect + if (isset($question_data['prtincorrect'][0]["_content"])) + { + $data['prtincorrect'][0]['text'] = $question_data['prtincorrect'][0]['text']; + } else + { + $data['prtincorrect'][0]['text'] = ""; + } + + //multiplicationsign + if (isset($question_data['multiplicationsign'][0]["_content"])) + { + $data['multiplicationsign'] = $question_data['multiplicationsign'][0]["_content"]; + } else + { + $data['multiplicationsign'] = ""; + } + + //sqrtsign + if (isset($question_data['sqrtsign'][0]["_content"])) + { + $data['sqrtsign'] = $question_data['sqrtsign'][0]["_content"]; + } else + { + $data['sqrtsign'] = ""; + } + + //complexno + if (isset($question_data['complexno'][0]["_content"])) + { + $data['complexno'] = $question_data['complexno'][0]["_content"]; + } else + { + $data['complexno'] = ""; + } + + //inversetrig + if (isset($question_data['inversetrig'][0]["_content"])) + { + $data['inversetrig'] = $question_data['inversetrig'][0]["_content"]; + } else + { + $data['inversetrig'] = ""; + } + + //matrixparens + if (isset($question_data['matrixparens'][0]["_content"])) + { + $data['matrixparens'] = $question_data['matrixparens'][0]["_content"]; + } else + { + $data['matrixparens'] = ""; + } + + //variantsselectionseed + if (isset($question_data['variantsselectionseed'])) + { + $data['variantsselectionseed'] = $question_data['variantsselectionseed']; + } else + { + $data['variantsselectionseed'] = ""; + } + + //Inputs + if (is_array($question_data['input'])) + { + foreach ($question_data['input'] as $input_raw) + { + $input_data = array(); + + //name + if (isset($input_raw['name'][0]["_content"])) + { + $input_data['name'] = $input_raw['name'][0]["_content"]; + } else + { + $input_data['name'] = ""; + } + + //type + if (isset($input_raw['type'][0]["_content"])) + { + $input_data['type'] = $input_raw['type'][0]["_content"]; + } else + { + $input_data['type'] = ""; + } + + //tans + if (isset($input_raw['tans'][0]["_content"])) + { + $input_data['tans'] = $input_raw['tans'][0]["_content"]; + } else + { + $input_data['tans'] = ""; + } + + //boxsize + if (isset($input_raw['boxsize'][0]["_content"])) + { + $input_data['boxsize'] = $input_raw['boxsize'][0]["_content"]; + } else + { + $input_data['boxsize'] = ""; + } + + //strictsyntax + if (isset($input_raw['strictsyntax'][0]["_content"])) + { + $input_data['strictsyntax'] = $input_raw['strictsyntax'][0]["_content"]; + } else + { + $input_data['strictsyntax'] = ""; + } + + //insertstars + if (isset($input_raw['insertstars'][0]["_content"])) + { + $input_data['insertstars'] = $input_raw['insertstars'][0]["_content"]; + } else + { + $input_data['insertstars'] = ""; + } + + //syntaxhint + if (isset($input_raw['syntaxhint'][0]["_content"])) + { + $input_data['syntaxhint'] = $input_raw['syntaxhint'][0]["_content"]; + } else + { + $input_data['syntaxhint'] = ""; + } + + //syntaxattribute + if (isset($input_raw['syntaxattribute'][0]["_content"])) + { + $input_data['syntaxattribute'] = $input_raw['syntaxattribute'][0]["_content"]; + } else + { + $input_data['syntaxattribute'] = ""; + } + + //forbidwords + if (isset($input_raw['forbidwords'][0]["_content"])) + { + $input_data['forbidwords'] = $input_raw['forbidwords'][0]["_content"]; + } else + { + $input_data['forbidwords'] = ""; + } + + //allowwords + if (isset($input_raw['allowwords'][0]["_content"])) + { + $input_data['allowwords'] = $input_raw['allowwords'][0]["_content"]; + } else + { + $input_data['allowwords'] = ""; + } + + //forbidfloat + if (isset($input_raw['forbidfloat'][0]["_content"])) + { + $input_data['forbidfloat'] = $input_raw['forbidfloat'][0]["_content"]; + } else + { + $input_data['forbidfloat'] = ""; + } + + //requirelowestterms + if (isset($input_raw['requirelowestterms'][0]["_content"])) + { + $input_data['requirelowestterms'] = $input_raw['requirelowestterms'][0]["_content"]; + } else + { + $input_data['requirelowestterms'] = ""; + } + + //checkanswertype + if (isset($input_raw['checkanswertype'][0]["_content"])) + { + $input_data['checkanswertype'] = $input_raw['checkanswertype'][0]["_content"]; + } else + { + $input_data['checkanswertype'] = ""; + } + + //mustverify + if (isset($input_raw['mustverify'][0]["_content"])) + { + $input_data['mustverify'] = $input_raw['mustverify'][0]["_content"]; + } else + { + $input_data['mustverify'] = ""; + } + + //showvalidation + if (isset($input_raw['showvalidation'][0]["_content"])) + { + $input_data['showvalidation'] = $input_raw['showvalidation'][0]["_content"]; + } else + { + $input_data['showvalidation'] = ""; + } + + //options + if (isset($input_raw['options'][0]["_content"])) + { + $input_data['options'] = $input_raw['options'][0]["_content"]; + } else + { + $input_data['options'] = ""; + } + + //Add to question + $data['input'][] = $input_data; + } + } + + //PRT + if (is_array($question_data['prt'])) + { + foreach ($question_data['prt'] as $prt_raw) + { + $prt_data = array(); + + //name + if (isset($prt_raw['name'][0]["_content"])) + { + $prt_data['name'] = $prt_raw['name'][0]["_content"]; + } else + { + $prt_data['name'] = ""; + } + + //value + if (isset($prt_raw['value'][0]["_content"])) + { + $prt_data['value'] = $prt_raw['value'][0]["_content"]; + } else + { + $prt_data['value'] = ""; + } + + //autosimplify + if (isset($prt_raw['autosimplify'][0]["_content"])) + { + $prt_data['autosimplify'] = $prt_raw['autosimplify'][0]["_content"]; + } else + { + $prt_data['autosimplify'] = ""; + } + + //feedbackvariables + if (isset($prt_raw['feedbackvariables'][0]["text"])) + { + $prt_data['feedbackvariables'][0]["text"] = $prt_raw['feedbackvariables'][0]["text"]; + } else + { + $prt_data['feedbackvariables'][0]["text"] = ""; + } + + //Nodes + if (is_array($prt_raw['node'])) + { + foreach ($prt_raw['node'] as $node_raw) + { + $node_data = array(); + + //name + if (isset($node_raw['name'][0]["_content"])) + { + $node_data['name'] = $node_raw['name'][0]["_content"]; + } else + { + $node_data['name'] = ""; + } + + //answertest + if (isset($node_raw['answertest'][0]["_content"])) + { + $node_data['answertest'] = $node_raw['answertest'][0]["_content"]; + } else + { + $node_data['answertest'] = ""; + } + + //sans + if (isset($node_raw['sans'][0]["_content"])) + { + $node_data['sans'] = $node_raw['sans'][0]["_content"]; + } else + { + $node_data['sans'] = ""; + } + + //tans + if (isset($node_raw['tans'][0]["_content"])) + { + $node_data['tans'] = $node_raw['tans'][0]["_content"]; + } else + { + $node_data['tans'] = ""; + } + + //testoptions + if (isset($node_raw['testoptions'][0]["_content"])) + { + $node_data['testoptions'] = $node_raw['testoptions'][0]["_content"]; + } else + { + $node_data['testoptions'] = ""; + } + + //quiet + if (isset($node_raw['quiet'][0]["_content"])) + { + $node_data['quiet'] = $node_raw['quiet'][0]["_content"]; + } else + { + $node_data['quiet'] = ""; + } + + //truescoremode + if (isset($node_raw['truescoremode'][0]["_content"])) + { + $node_data['truescoremode'] = $node_raw['truescoremode'][0]["_content"]; + } else + { + $node_data['truescoremode'] = ""; + } + + //truescore + if (isset($node_raw['truescore'][0]["_content"])) + { + $node_data['truescore'] = $node_raw['truescore'][0]["_content"]; + } else + { + $node_data['truescore'] = ""; + } + + //truepenalty + if (isset($node_raw['truepenalty'][0]["_content"])) + { + $node_data['truepenalty'] = $node_raw['truepenalty'][0]["_content"]; + } else + { + $node_data['truepenalty'] = ""; + } + + //truenextnode + if (isset($node_raw['truenextnode'][0]["_content"])) + { + $node_data['truenextnode'] = $node_raw['truenextnode'][0]["_content"]; + } else + { + $node_data['truenextnode'] = ""; + } + + //trueanswernote + if (isset($node_raw['trueanswernote'][0]["_content"])) + { + $node_data['trueanswernote'] = $node_raw['trueanswernote'][0]["_content"]; + } else + { + $node_data['trueanswernote'] = ""; + } + + //truefeedback + if (isset($node_raw['truefeedback'][0]["text"][0]["_content"])) + { + $node_data['truefeedback'][0]["text"] = $node_raw['truefeedback'][0]["text"][0]["_content"]; + } else + { + $node_data['truefeedback'][0]["text"] = ""; + } + + //falsescoremode + if (isset($node_raw['falsescoremode'][0]["_content"])) + { + $node_data['falsescoremode'] = $node_raw['falsescoremode'][0]["_content"]; + } else + { + $node_data['falsescoremode'] = ""; + } + + //falsescore + if (isset($node_raw['falsescore'][0]["_content"])) + { + $node_data['falsescore'] = $node_raw['falsescore'][0]["_content"]; + } else + { + $node_data['falsescore'] = ""; + } + + //falsepenalty + if (isset($node_raw['falsepenalty'][0]["_content"])) + { + $node_data['falsepenalty'] = $node_raw['falsepenalty'][0]["_content"]; + } else + { + $node_data['falsepenalty'] = ""; + } + + //falsenextnode + if (isset($node_raw['falsenextnode'][0]["_content"])) + { + $node_data['falsenextnode'] = $node_raw['falsenextnode'][0]["_content"]; + } else + { + $node_data['falsenextnode'] = ""; + } + + //falseanswernote + if (isset($node_raw['falseanswernote'][0]["_content"])) + { + $node_data['falseanswernote'] = $node_raw['falseanswernote'][0]["_content"]; + } else + { + $node_data['falseanswernote'] = ""; + } + + //falsefeedback + if (isset($node_raw['falsefeedback'][0]["text"][0]["_content"])) + { + $node_data['falsefeedback'][0]["text"] = $node_raw['falsefeedback'][0]["text"][0]["_content"]; + } else + { + $node_data['falsefeedback'][0]["text"] = ""; + } + + //Add to prt + $prt_data['node'][] = $node_data; + } + } + + //Add to question + $data['prt'][] = $prt_data; + + //qtest + if (is_array($question_data['qtest'])) + { + foreach ($question_data['qtest'] as $qtest_raw) + { + $qtest_data = array(); + + //testcase + if (isset($qtest_raw['testcase'][0]["_content"])) + { + $qtest_data['testcase'] = $qtest_raw['testcase'][0]["_content"]; + } else + { + $qtest_data['testcase'] = ""; + } + + //testinput + if (isset($qtest_raw['testinput'][0]['name'][0]["_content"]) AND isset($qtest_raw['testinput'][0]['value'][0]["_content"])) + { + $qtest_data['testinput'][0]['name'] = $qtest_raw['testinput'][0]['name'][0]["_content"]; + $qtest_data['testinput'][0]['value'] = $qtest_raw['testinput'][0]['value'][0]["_content"]; + } else + { + $qtest_data['testinput'][0]['name'] = ""; + $qtest_data['testinput'][0]['value'] = ""; + } + + //expected + if (isset($qtest_raw['expected'][0]['name'][0]["_content"]) AND isset($qtest_raw['expected'][0]['expectedscore'][0]["_content"]) AND isset($qtest_raw['expected'][0]['expectedanswernote'][0]["_content"])) + { + $qtest_data['expected'][0]['name'] = $qtest_raw['expected'][0]['name'][0]["_content"]; + $qtest_data['expected'][0]['expectedscore'] = $qtest_raw['expected'][0]['expectedscore'][0]["_content"]; + $qtest_data['expected'][0]['expectedpenalty'] = $qtest_raw['expected'][0]['expectedpenalty'][0]["_content"]; + $qtest_data['expected'][0]['expectedanswernote'] = $qtest_raw['expected'][0]['expectedanswernote'][0]["_content"]; + + } else + { + $qtest_data['expected'][0]['name'] = ""; + $qtest_data['expected'][0]['expectedscore'] = ""; + $qtest_data['expected'][0]['expectedpenalty'] = ""; + $qtest_data['expected'][0]['expectedanswernote'] = ""; + } + + + //Add to question + $data['qtest'][] = $qtest_data; + } + } + + } + } + + //Add to full data + $full_data['question'][] = $data; + + } + + return $full_data; + } + } diff --git a/classes/model/question_display/class.assStackQuestionDisplay.php b/classes/model/question_display/class.assStackQuestionDisplay.php index 9f39dc72..ba035ec2 100644 --- a/classes/model/question_display/class.assStackQuestionDisplay.php +++ b/classes/model/question_display/class.assStackQuestionDisplay.php @@ -266,7 +266,7 @@ private function replacementForValidationPlaceholders($input, $input_name) private function replacementForPRTPlaceholders($prt, $prt_name, $in_test) { $string = ""; - if (sizeof($this->getInlineFeedback())) + if (!empty($this->getInlineFeedback())) { //feedback //feedback diff --git a/classes/stack/cas/cassession.class.php b/classes/stack/cas/cassession.class.php index fb7886d8..12c52948 100644 --- a/classes/stack/cas/cassession.class.php +++ b/classes/stack/cas/cassession.class.php @@ -531,7 +531,7 @@ private function construct_maxima_command() { } // Special handling for the conditionally evaluated strings. - if (count($cs->get_conditions()) > 0) { + if (!empty($cs->get_conditions())) { $conditions = array(); foreach ($cs->get_conditions() as $cond) { // No need to evaluate again if it is already evaluated. diff --git a/classes/stack/cas/casstring.class.php b/classes/stack/cas/casstring.class.php index ca560f28..404e4254 100644 --- a/classes/stack/cas/casstring.class.php +++ b/classes/stack/cas/casstring.class.php @@ -555,7 +555,7 @@ public function __construct($rawstring, $conditions = null) { if (!($conditions === null || is_array($conditions))) { throw new stack_exception('stack_cas_casstring: conditions must be null or an array.'); } - if (count($conditions) != 0) { + if (!empty($conditions)) { $this->conditions = $conditions; } } diff --git a/classes/stack/cas/castext.class.php b/classes/stack/cas/castext.class.php index b77401f6..db3bec56 100644 --- a/classes/stack/cas/castext.class.php +++ b/classes/stack/cas/castext.class.php @@ -356,10 +356,10 @@ private function instantiate() { return false; } - // Deal with castext without any CAS variables. - if (null !== $this->session && count($this->session->get_session()) > 0) { - $this->session->instantiate(); - } + // Deal with castext without any CAS variables. + if (null !== $this->session && !empty($this->session->get_session())) { + $this->session->instantiate(); + } // Handle blocks. $requiresrerun = false; diff --git a/classes/stack/input/checkbox/checkbox.class.php b/classes/stack/input/checkbox/checkbox.class.php index fc5dbd49..78cebe4d 100644 --- a/classes/stack/input/checkbox/checkbox.class.php +++ b/classes/stack/input/checkbox/checkbox.class.php @@ -154,11 +154,13 @@ public function response_to_contents($response) { } $contents = array(); - foreach ($this->ddlvalues as $key => $val) { - if (array_key_exists($this->name.'_'.$key, $response)) { - $contents[] = (int) $response[$this->name.'_'.$key]; - } - } + if(is_array($this->ddlvalues)){ + foreach ($this->ddlvalues as $key => $val) { + if (array_key_exists($this->name.'_'.$key, $response)) { + $contents[] = (int) $response[$this->name.'_'.$key]; + } + } + } return $contents; } diff --git a/classes/utils/class.assStackQuestionUtils.php b/classes/utils/class.assStackQuestionUtils.php index 5655e4a0..446ad929 100644 --- a/classes/utils/class.assStackQuestionUtils.php +++ b/classes/utils/class.assStackQuestionUtils.php @@ -750,5 +750,17 @@ public static function _replaceFeedbackPlaceHolders($feedback){ } + public static function _isPhP72() + { + $php_version = phpversion(); + $version = substr($php_version, 0, 3); + if ($version < 7.2) + { + return FALSE; + } else + { + return TRUE; + } + } } diff --git a/plugin.php b/plugin.php index 052525d7..b3d68e02 100644 --- a/plugin.php +++ b/plugin.php @@ -9,7 +9,7 @@ // code version; must be changed for all code changes -$version = "3.1.3"; +$version = "3.1.4"; // ilias min and max version; must always reflect the versions that should // run with the plugin From b5ffff70112617dd8acb8eca68726796e29eaa69 Mon Sep 17 00:00:00 2001 From: jcopado Date: Mon, 26 Aug 2019 10:54:19 +0200 Subject: [PATCH 10/23] 3.1.5 --- README.md | 6 +- .../class.assStackQuestionAuthoringGUI.php | 10 +- ...class.assStackQuestionDeployedSeedsGUI.php | 2 +- .../class.assStackQuestionFeedbackGUI.php | 2 +- .../test/class.assStackQuestionTestGUI.php | 2 +- classes/class.assStackQuestion.php | 18 +- classes/class.assStackQuestionGUI.php | 34 +- .../class.assStackQuestionMoodleXMLExport.php | 297 ++++++++++-------- .../class.assStackQuestionStackQuestion.php | 4 +- .../test/class.assStackQuestionTest.php | 4 +- .../class.assStackQuestionDisplay.php | 20 +- classes/stack/cas/connector.dbcache.class.php | 2 +- classes/utils/class.assStackQuestionUtils.php | 4 +- plugin.php | 2 +- 14 files changed, 233 insertions(+), 174 deletions(-) diff --git a/README.md b/README.md index a016c372..4c41cf45 100644 --- a/README.md +++ b/README.md @@ -106,4 +106,8 @@ Now all feedback Types are always displayed in the authoring interface also if n Version 3.1.4 (2019-08-23) for ILIAS 5.4 ---------------------------------------- -This version includes support for PHP 7.2 in ILIAS 5.4 platform, during the process of update this plugin some ILIAS core bugs were found (e.g. importing question pools), those non-STACk related bugs can make the experience of using the plugin in a PHP 7.2 installation not smooth as intended, if you find any bugs in a PHP 7.2 platform, please report it in Mantis. \ No newline at end of file +This version includes support for PHP 7.2 in ILIAS 5.4 platform, during the process of update this plugin some ILIAS core bugs were found (e.g. importing question pools), those non-STACk related bugs can make the experience of using the plugin in a PHP 7.2 installation not smooth as intended, if you find any bugs in a PHP 7.2 platform, please report it in Mantis. + +Version 3.1.5 (2019-08-26) for ILIAS 5.4 +---------------------------------------- +Some bugs in PHP 7.2 installations has been solved. \ No newline at end of file diff --git a/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php b/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php index 5b704a0c..4e38a53b 100644 --- a/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php +++ b/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php @@ -229,7 +229,7 @@ public function addInputs() $inputs_section_header->setTitle($this->getPlugin()->txt('inputs')); $this->getForm()->addItem($inputs_section_header); - if (sizeof($this->getQuestionGUI()->object->getInputs())) + if (!empty($this->getQuestionGUI()->object->getInputs())) { //In case of edition foreach ($this->getQuestionGUI()->object->getInputs() as $input_name => $input) @@ -256,7 +256,7 @@ public function addPRTs() { $prts = new ilTabsFormPropertyGUI($this->getPlugin()->txt('prts'), "question_prts", 12, FALSE); - if (sizeof($this->getQuestionGUI()->object->getPotentialResponsesTrees())) + if (!empty($this->getQuestionGUI()->object->getPotentialResponsesTrees())) { foreach ($this->getQuestionGUI()->object->getPotentialResponsesTrees() as $prt_name => $prt) { @@ -755,7 +755,7 @@ public function getNodesPart(assStackQuestionPRT $prt, $container_width = "") $nodes = new ilTabsFormPropertyGUI($this->getPlugin()->txt('prt_nodes'), 'prt_' . $prt->getPRTName() . '_nodes', $container_width, FALSE); $q_nodes = $prt->getPRTNodes(); - if (sizeof($q_nodes)) + if (!empty($q_nodes)) { foreach ($q_nodes as $node) { @@ -768,7 +768,7 @@ public function getNodesPart(assStackQuestionPRT $prt, $container_width = "") } } //Add tab per node in the current PRT - if (sizeof($q_nodes)) + if (!empty($q_nodes)) { foreach ($q_nodes as $node) { @@ -1123,7 +1123,7 @@ public function manageErrorMessages() if (isset($_SESSION["stack_authoring_errors"][$this->getQuestionGUI()->object->getId()])) { - if (sizeof($_SESSION["stack_authoring_errors"][$this->getQuestionGUI()->object->getId()])) + if (!empty($_SESSION["stack_authoring_errors"][$this->getQuestionGUI()->object->getId()])) { foreach ($_SESSION["stack_authoring_errors"][$this->getQuestionGUI()->object->getId()] as $session_error) { diff --git a/classes/GUI/question_authoring/class.assStackQuestionDeployedSeedsGUI.php b/classes/GUI/question_authoring/class.assStackQuestionDeployedSeedsGUI.php index 1cebfb06..136413dd 100644 --- a/classes/GUI/question_authoring/class.assStackQuestionDeployedSeedsGUI.php +++ b/classes/GUI/question_authoring/class.assStackQuestionDeployedSeedsGUI.php @@ -98,7 +98,7 @@ private function getQuestionNotesForSeeds() $q_note = $deployed_seed->getQuestionNote(); $include = TRUE; - if (sizeof($valid_seeds)) + if (!empty($valid_seeds)) { foreach ($valid_seeds as $valid_seed) { diff --git a/classes/GUI/question_display/class.assStackQuestionFeedbackGUI.php b/classes/GUI/question_display/class.assStackQuestionFeedbackGUI.php index 61491cf4..e6ccf243 100644 --- a/classes/GUI/question_display/class.assStackQuestionFeedbackGUI.php +++ b/classes/GUI/question_display/class.assStackQuestionFeedbackGUI.php @@ -51,7 +51,7 @@ function __construct(ilassStackQuestionPlugin $plugin, $feedback_data, $specific //Set feedback data $this->setFeedback($feedback_data); - if (sizeof($this->getFeedback('prt')) > 1) + if (!empty($this->getFeedback('prt'))) { $this->show_user_response = TRUE; } else diff --git a/classes/GUI/test/class.assStackQuestionTestGUI.php b/classes/GUI/test/class.assStackQuestionTestGUI.php index 010bd135..7605039f 100644 --- a/classes/GUI/test/class.assStackQuestionTestGUI.php +++ b/classes/GUI/test/class.assStackQuestionTestGUI.php @@ -100,7 +100,7 @@ public function showUnitTestsPanel($a_mode = FALSE) $toolbar->addButtonInstance($run_all_tests); $toolbar->setFormAction($ctrl->getLinkTargetByClass("assSTACKQuestionGUI")); - if (sizeof($this->getTests())) + if (!empty($this->getTests())) { include_once './Services/Accordion/classes/class.ilAccordionGUI.php'; $unit_tests_accordion = new ilAccordionGUI(); diff --git a/classes/class.assStackQuestion.php b/classes/class.assStackQuestion.php index fd8cebb2..3bfab54e 100644 --- a/classes/class.assStackQuestion.php +++ b/classes/class.assStackQuestion.php @@ -879,7 +879,7 @@ public function saveAdditionalQuestionDataToDb($edit_question = "", $adding_to_t } //INPUTS - if (sizeof($this->inputs)) + if (!empty($this->inputs)) { foreach ($this->inputs as $input) { @@ -897,7 +897,7 @@ public function saveAdditionalQuestionDataToDb($edit_question = "", $adding_to_t } //POTENTIAL RESPONSE TREES - if (sizeof($this->potential_responses_trees)) + if (!empty($this->potential_responses_trees)) { foreach ($this->potential_responses_trees as $prt) { @@ -992,7 +992,7 @@ function beforeSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjI } //Inputs - if (sizeof($this->inputs)) + if (!empty($this->inputs)) { $inputs = assStackQuestionInput::_read($origQuestionId); @@ -1025,7 +1025,7 @@ function beforeSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjI } //PRT - if (sizeof($this->potential_responses_trees)) + if (!empty($this->potential_responses_trees)) { $prts = assStackQuestionPRT::_read($origQuestionId); @@ -1125,7 +1125,7 @@ function beforeCopy($origQuestionId) } //Inputs - if (sizeof($this->inputs)) + if (!empty($this->inputs)) { foreach ($this->inputs as $key => $input) { @@ -1138,7 +1138,7 @@ function beforeCopy($origQuestionId) } //PRT - if (sizeof($this->potential_responses_trees)) + if (!empty($this->potential_responses_trees)) { foreach ($this->potential_responses_trees as $prt_key => $prt) @@ -1240,7 +1240,7 @@ public function loadFromDb($question_id) //load inputs $this->getPlugin()->includeClass('model/ilias_object/class.assStackQuestionInput.php'); $this->setInputs(assStackQuestionInput::_read($question_id)); - if (sizeof($this->getInputs()) == 0) + if (empty($this->getInputs())) { //Create options $input = new assStackQuestionInput(-1, $question_id, "ans1", "algebraic", ""); @@ -1793,7 +1793,7 @@ public function getQuestionSeedForCurrentTestRun($active_id, $pass) } //Determine if seed already exists and return it; - if (sizeof($this->getPotentialResponsesTrees())) + if (!empty($this->getPotentialResponsesTrees())) { foreach ($this->getPotentialResponsesTrees() as $prt) { @@ -1819,7 +1819,7 @@ public function getQuestionSeedForCurrentTestRun($active_id, $pass) //get seed and save it to DB $question_seed = $this->getStackQuestion()->getSeed(); - if (sizeof($this->getPotentialResponsesTrees())) + if (!empty($this->getPotentialResponsesTrees())) { foreach ($this->getPotentialResponsesTrees() as $prt) { diff --git a/classes/class.assStackQuestionGUI.php b/classes/class.assStackQuestionGUI.php index 30fbd737..374a3d41 100644 --- a/classes/class.assStackQuestionGUI.php +++ b/classes/class.assStackQuestionGUI.php @@ -277,26 +277,33 @@ public function deletionManagement() public function checkPRTForDeletion(assStackQuestionPRT $prt) { - if (sizeof($this->object->getPotentialResponsesTrees()) < 2) + if (is_array($this->object->getPotentialResponsesTrees())) { - $this->object->setErrors($this->object->getPlugin()->txt('deletion_error_not_enought_prts')); + if (sizeof($this->object->getPotentialResponsesTrees()) < 2) + { + $this->object->setErrors($this->object->getPlugin()->txt('deletion_error_not_enought_prts')); - return TRUE; + return TRUE; + } } + return FALSE; } public function checkPRTNodeForDeletion(assStackQuestionPRT $prt, assStackQuestionPRTNode $node) { - - if (sizeof($prt->getPRTNodes()) < 2) + if (is_array($prt->getPRTNodes())) { - $this->object->setErrors($this->object->getPlugin()->txt('deletion_error_not_enought_prt_nodes')); + if (sizeof($prt->getPRTNodes()) < 2) + { + $this->object->setErrors($this->object->getPlugin()->txt('deletion_error_not_enought_prt_nodes')); - return TRUE; + return TRUE; + } } + if ((int)$prt->getFirstNodeName() == (int)$node->getNodeName()) { $this->object->setErrors($this->object->getPlugin()->txt('deletion_error_first_node')); @@ -343,11 +350,14 @@ public function writeQuestionSpecificPostData() } else { //If doesn' exist, check if must be deleted - if (sizeof($this->object->getInputs()) < 2) + if (is_array($this->object->getInputs())) { - //If there are less than two inputs you cannot delete it - //Add placeholder to question text - $this->object->setQuestion($this->object->getQuestion() . " [[input:{$input_name}]] [[validation:{$input_name}]]"); + if (sizeof($this->object->getInputs()) < 2) + { + //If there are less than two inputs you cannot delete it + //Add placeholder to question text + $this->object->setQuestion($this->object->getQuestion() . " [[input:{$input_name}]] [[validation:{$input_name}]]"); + } } else { //Delete input from object @@ -934,11 +944,11 @@ public function getSpecificFeedbackOutput($userSolution) /** * Returns the answer generic feedback depending on the results of the question * - * @deprecated Use getGenericFeedbackOutput instead. * @param integer $active_id Active ID of the user * @param integer $pass Active pass * @return string HTML Code with the answer specific feedback * @access public + * @deprecated Use getGenericFeedbackOutput instead. */ function getAnswerFeedbackOutput($active_id, $pass) { diff --git a/classes/export/MoodleXML/class.assStackQuestionMoodleXMLExport.php b/classes/export/MoodleXML/class.assStackQuestionMoodleXMLExport.php index c957b532..c66bf9db 100644 --- a/classes/export/MoodleXML/class.assStackQuestionMoodleXMLExport.php +++ b/classes/export/MoodleXML/class.assStackQuestionMoodleXMLExport.php @@ -25,9 +25,11 @@ function __construct($stack_questions) global $DIC; $lng = $DIC->language(); - if (is_array($stack_questions) AND sizeof($stack_questions)) { + if (is_array($stack_questions) AND sizeof($stack_questions)) + { $this->setStackQuestions($stack_questions); - } else { + } else + { throw new stack_exception($lng->txt('qpl_qst_xqcas_moodlexml_no_questions_selected')); } } @@ -61,7 +63,8 @@ function toMoodleXML() // set xml header $a_xml_writer->xmlHeader(); $a_xml_writer->xmlStartTag("quiz"); - foreach ($this->getStackQuestions() as $question_id => $question) { + foreach ($this->getStackQuestions() as $question_id => $question) + { $a_xml_writer->xmlComment(" question: " . $question_id . " "); $a_xml_writer->xmlStartTag("question", array("type" => "stack")); @@ -88,15 +91,19 @@ function toMoodleXML() //Grade and penalty $a_xml_writer->xmlElement("defaultgrade", NULL, $question->getPoints()); - if ($question->getExtraInfo()->getPenalty()) { + if ($question->getExtraInfo()->getPenalty()) + { $a_xml_writer->xmlElement("penalty", NULL, $question->getExtraInfo()->getPenalty()); - } else { + } else + { $a_xml_writer->xmlElement("penalty", NULL, "0"); } - if ($question->getExtraInfo()->getPenalty()) { + if ($question->getExtraInfo()->getPenalty()) + { $a_xml_writer->xmlElement("hidden", NULL, $question->getExtraInfo()->getHidden()); - } else { + } else + { $a_xml_writer->xmlElement("hidden", NULL, "0"); } @@ -148,139 +155,173 @@ function toMoodleXML() $a_xml_writer->xmlElement("variantsselectionseed", NULL, $question->getOptions()->getVariantsSelectionSeeds()); //Inputs - if (sizeof($question->getInputs())) { - foreach ($question->getInputs() as $input) { - $a_xml_writer->xmlStartTag("input"); - - $a_xml_writer->xmlElement("name", NULL, $input->getInputName()); - $a_xml_writer->xmlElement("type", NULL, $input->getInputType()); - $a_xml_writer->xmlElement("tans", NULL, $input->getTeacherAnswer()); - $a_xml_writer->xmlElement("boxsize", NULL, $input->getBoxSize()); - $a_xml_writer->xmlElement("strictsyntax", NULL, (int)$input->getStrictSyntax()); - $a_xml_writer->xmlElement("insertstars", NULL, (int)$input->getInsertStars()); - $a_xml_writer->xmlElement("syntaxhint", NULL, $input->getSyntaxHint()); - $a_xml_writer->xmlElement("forbidwords", NULL, $input->getForbidWords()); - $a_xml_writer->xmlElement("allowwords", NULL, $input->getAllowWords()); - $a_xml_writer->xmlElement("forbidfloat", NULL, (int)$input->getForbidFloat()); - $a_xml_writer->xmlElement("requirelowestterms", NULL, (int)$input->getRequireLowestTerms()); - $a_xml_writer->xmlElement("checkanswertype", NULL, (int)$input->getCheckAnswerType()); - $a_xml_writer->xmlElement("mustverify", NULL, (int)$input->getMustVerify()); - $a_xml_writer->xmlElement("showvalidation", NULL, (int)$input->getShowValidation()); - $a_xml_writer->xmlElement("options", NULL, $input->getOptions()); - - $a_xml_writer->xmlEndTag("input"); + if (is_array($question->getInputs())) + { + if (sizeof($question->getInputs())) + { + foreach ($question->getInputs() as $input) + { + $a_xml_writer->xmlStartTag("input"); + + $a_xml_writer->xmlElement("name", NULL, $input->getInputName()); + $a_xml_writer->xmlElement("type", NULL, $input->getInputType()); + $a_xml_writer->xmlElement("tans", NULL, $input->getTeacherAnswer()); + $a_xml_writer->xmlElement("boxsize", NULL, $input->getBoxSize()); + $a_xml_writer->xmlElement("strictsyntax", NULL, (int)$input->getStrictSyntax()); + $a_xml_writer->xmlElement("insertstars", NULL, (int)$input->getInsertStars()); + $a_xml_writer->xmlElement("syntaxhint", NULL, $input->getSyntaxHint()); + $a_xml_writer->xmlElement("forbidwords", NULL, $input->getForbidWords()); + $a_xml_writer->xmlElement("allowwords", NULL, $input->getAllowWords()); + $a_xml_writer->xmlElement("forbidfloat", NULL, (int)$input->getForbidFloat()); + $a_xml_writer->xmlElement("requirelowestterms", NULL, (int)$input->getRequireLowestTerms()); + $a_xml_writer->xmlElement("checkanswertype", NULL, (int)$input->getCheckAnswerType()); + $a_xml_writer->xmlElement("mustverify", NULL, (int)$input->getMustVerify()); + $a_xml_writer->xmlElement("showvalidation", NULL, (int)$input->getShowValidation()); + $a_xml_writer->xmlElement("options", NULL, $input->getOptions()); + + $a_xml_writer->xmlEndTag("input"); + } } } + //PRT - if (sizeof($question->getPotentialResponsesTrees())) { - foreach ($question->getPotentialResponsesTrees() as $prt) { - $a_xml_writer->xmlStartTag("prt"); - - $a_xml_writer->xmlElement("name", NULL, $prt->getPRTName()); - $a_xml_writer->xmlElement("value", NULL, $prt->getPRTValue()); - $a_xml_writer->xmlElement("autosimplify", NULL, $prt->getAutoSimplify()); - - $a_xml_writer->xmlStartTag("feedbackvariables", array("format" => "html")); - $a_xml_writer->xmlElement("text", NULL, $prt->getPRTFeedbackVariables()); - $a_xml_writer->xmlEndTag("feedbackvariables"); - - //Nodes - if (sizeof($prt->getPRTNodes())) { - foreach ($prt->getPRTNodes() as $node) { - $a_xml_writer->xmlStartTag("node"); - - $a_xml_writer->xmlElement("name", NULL, $node->getNodeName()); - $a_xml_writer->xmlElement("answertest", NULL, $node->getAnswerTest()); - $a_xml_writer->xmlElement("sans", NULL, $node->getStudentAnswer()); - $a_xml_writer->xmlElement("tans", NULL, $node->getTeacherAnswer()); - $a_xml_writer->xmlElement("testoptions", NULL, $node->getTestOptions()); - $a_xml_writer->xmlElement("quiet", NULL, $node->getQuiet()); - - $a_xml_writer->xmlElement("truescoremode", NULL, $node->getTrueScoreMode()); - $a_xml_writer->xmlElement("truescore", NULL, $node->getTrueScore()); - $a_xml_writer->xmlElement("truepenalty", NULL, $node->getTruePenalty()); - $a_xml_writer->xmlElement("truenextnode", NULL, $node->getTrueNextNode()); - $a_xml_writer->xmlElement("trueanswernote", NULL, $node->getTrueAnswerNote()); - $a_xml_writer->xmlElement("truefeedbackformat", NULL, $node->getTrueFeedbackFormat()); - - $a_xml_writer->xmlStartTag("truefeedback", array("format" => "html")); - $media = $this->getRTEMedia($node->getTrueFeedback()); - $this->addRTEText($a_xml_writer, $node->getTrueFeedback()); - $this->addRTEMedia($a_xml_writer, $media); - $a_xml_writer->xmlEndTag("truefeedback"); - - $a_xml_writer->xmlElement("falsescoremode", NULL, $node->getFalseScoreMode()); - $a_xml_writer->xmlElement("falsescore", NULL, $node->getFalseScore()); - $a_xml_writer->xmlElement("falsepenalty", NULL, $node->getFalsePenalty()); - $a_xml_writer->xmlElement("falsenextnode", NULL, $node->getFalseNextNode()); - $a_xml_writer->xmlElement("falseanswernote", NULL, $node->getFalseAnswerNote()); - $a_xml_writer->xmlElement("falsefeedbackformat", NULL, $node->getFalseFeedbackFormat()); - - - $a_xml_writer->xmlStartTag("falsefeedback", array("format" => "html")); - $media = $this->getRTEMedia($node->getFalseFeedback()); - $this->addRTEText($a_xml_writer, $node->getFalseFeedback()); - $this->addRTEMedia($a_xml_writer, $media); - $a_xml_writer->xmlEndTag("falsefeedback"); - - $a_xml_writer->xmlEndTag("node"); + if (is_array($question->getPotentialResponsesTrees())) + { + if (sizeof($question->getPotentialResponsesTrees())) + { + foreach ($question->getPotentialResponsesTrees() as $prt) + { + $a_xml_writer->xmlStartTag("prt"); + + $a_xml_writer->xmlElement("name", NULL, $prt->getPRTName()); + $a_xml_writer->xmlElement("value", NULL, $prt->getPRTValue()); + $a_xml_writer->xmlElement("autosimplify", NULL, $prt->getAutoSimplify()); + + $a_xml_writer->xmlStartTag("feedbackvariables", array("format" => "html")); + $a_xml_writer->xmlElement("text", NULL, $prt->getPRTFeedbackVariables()); + $a_xml_writer->xmlEndTag("feedbackvariables"); + + //Nodes + if (sizeof($prt->getPRTNodes())) + { + foreach ($prt->getPRTNodes() as $node) + { + $a_xml_writer->xmlStartTag("node"); + + $a_xml_writer->xmlElement("name", NULL, $node->getNodeName()); + $a_xml_writer->xmlElement("answertest", NULL, $node->getAnswerTest()); + $a_xml_writer->xmlElement("sans", NULL, $node->getStudentAnswer()); + $a_xml_writer->xmlElement("tans", NULL, $node->getTeacherAnswer()); + $a_xml_writer->xmlElement("testoptions", NULL, $node->getTestOptions()); + $a_xml_writer->xmlElement("quiet", NULL, $node->getQuiet()); + + $a_xml_writer->xmlElement("truescoremode", NULL, $node->getTrueScoreMode()); + $a_xml_writer->xmlElement("truescore", NULL, $node->getTrueScore()); + $a_xml_writer->xmlElement("truepenalty", NULL, $node->getTruePenalty()); + $a_xml_writer->xmlElement("truenextnode", NULL, $node->getTrueNextNode()); + $a_xml_writer->xmlElement("trueanswernote", NULL, $node->getTrueAnswerNote()); + $a_xml_writer->xmlElement("truefeedbackformat", NULL, $node->getTrueFeedbackFormat()); + + $a_xml_writer->xmlStartTag("truefeedback", array("format" => "html")); + $media = $this->getRTEMedia($node->getTrueFeedback()); + $this->addRTEText($a_xml_writer, $node->getTrueFeedback()); + $this->addRTEMedia($a_xml_writer, $media); + $a_xml_writer->xmlEndTag("truefeedback"); + + $a_xml_writer->xmlElement("falsescoremode", NULL, $node->getFalseScoreMode()); + $a_xml_writer->xmlElement("falsescore", NULL, $node->getFalseScore()); + $a_xml_writer->xmlElement("falsepenalty", NULL, $node->getFalsePenalty()); + $a_xml_writer->xmlElement("falsenextnode", NULL, $node->getFalseNextNode()); + $a_xml_writer->xmlElement("falseanswernote", NULL, $node->getFalseAnswerNote()); + $a_xml_writer->xmlElement("falsefeedbackformat", NULL, $node->getFalseFeedbackFormat()); + + + $a_xml_writer->xmlStartTag("falsefeedback", array("format" => "html")); + $media = $this->getRTEMedia($node->getFalseFeedback()); + $this->addRTEText($a_xml_writer, $node->getFalseFeedback()); + $this->addRTEMedia($a_xml_writer, $media); + $a_xml_writer->xmlEndTag("falsefeedback"); + + $a_xml_writer->xmlEndTag("node"); + } } + $a_xml_writer->xmlEndTag("prt"); } - $a_xml_writer->xmlEndTag("prt"); } } + //deployed seeds - if (sizeof($question->getDeployedSeeds())) { - foreach ($question->getDeployedSeeds() as $seed) { - $a_xml_writer->xmlElement("deployedseed", NULL, $seed->getSeed()); + if (is_array($question->getDeployedSeeds())) + { + if (sizeof($question->getDeployedSeeds())) + { + foreach ($question->getDeployedSeeds() as $seed) + { + $a_xml_writer->xmlElement("deployedseed", NULL, $seed->getSeed()); + } } } + //tests - if (sizeof($question->getTests())) { - foreach ($question->getTests() as $test) { - $a_xml_writer->xmlStartTag("qtest"); - $a_xml_writer->xmlElement("testcase", NULL, $test->getTestCase()); - //test input - foreach ($test->getTestInputs() as $test_input) { - $a_xml_writer->xmlStartTag("testinput"); - $a_xml_writer->xmlElement("name", NULL, $test_input->getTestInputName()); - $a_xml_writer->xmlElement("value", NULL, $test_input->getTestInputValue()); - $a_xml_writer->xmlEndTag("testinput"); - } - //test expected - foreach ($test->getTestExpected() as $test_input) { - $a_xml_writer->xmlStartTag("expected"); - $a_xml_writer->xmlElement("name", NULL, $test_input->getTestPRTName()); - $a_xml_writer->xmlElement("expectedscore", NULL, $test_input->getExpectedScore()); - $a_xml_writer->xmlElement("expectedpenalty", NULL, $test_input->getExpectedPenalty()); - $a_xml_writer->xmlElement("expectedanswernote", NULL, $test_input->getExpectedAnswerNote()); - $a_xml_writer->xmlEndTag("expected"); + if (is_array($question->getTests())) + { + if (sizeof($question->getTests())) + { + foreach ($question->getTests() as $test) + { + $a_xml_writer->xmlStartTag("qtest"); + $a_xml_writer->xmlElement("testcase", NULL, $test->getTestCase()); + //test input + foreach ($test->getTestInputs() as $test_input) + { + $a_xml_writer->xmlStartTag("testinput"); + $a_xml_writer->xmlElement("name", NULL, $test_input->getTestInputName()); + $a_xml_writer->xmlElement("value", NULL, $test_input->getTestInputValue()); + $a_xml_writer->xmlEndTag("testinput"); + } + //test expected + foreach ($test->getTestExpected() as $test_input) + { + $a_xml_writer->xmlStartTag("expected"); + $a_xml_writer->xmlElement("name", NULL, $test_input->getTestPRTName()); + $a_xml_writer->xmlElement("expectedscore", NULL, $test_input->getExpectedScore()); + $a_xml_writer->xmlElement("expectedpenalty", NULL, $test_input->getExpectedPenalty()); + $a_xml_writer->xmlElement("expectedanswernote", NULL, $test_input->getExpectedAnswerNote()); + $a_xml_writer->xmlEndTag("expected"); + } + $a_xml_writer->xmlEndTag("qtest"); } - $a_xml_writer->xmlEndTag("qtest"); } } + $a_xml_writer->xmlEndTag("question"); } $a_xml_writer->xmlEndTag("quiz"); $xml = $a_xml_writer->xmlDumpMem(FALSE); - if (sizeof($this->getStackQuestions()) > 1) { - ilUtil::deliverData($xml, "stack_question_" . $question_id . "_and_others.xml", "xml"); - } elseif (sizeof($this->getStackQuestions()) == 1) { - ilUtil::deliverData($xml, "stack_question_" . $question_id . ".xml", "xml"); + if (is_array($this->getStackQuestions())) + { + if (sizeof($this->getStackQuestions()) > 1) + { + ilUtil::deliverData($xml, "stack_question_" . $question_id . "_and_others.xml", "xml"); + } elseif (sizeof($this->getStackQuestions()) == 1) + { + ilUtil::deliverData($xml, "stack_question_" . $question_id . ".xml", "xml"); + } } + return $xml; } /** * Get the media files used in an RTE text - * @param string text to analyze - * @param assStackQuestion question - * @return array name => file content + * @param string text to analyze + * @param assStackQuestion question + * @return array name => file content */ private function getRTEMedia($a_text, $stack_question = "") { @@ -293,30 +334,30 @@ private function getRTEMedia($a_text, $stack_question = "") $id = $matches[1][$i]; $name = $matches[2][$i]; - $new_match =explode('?',$name); + $new_match = explode('?', $name); - if (is_file(ilUtil::getWebspaceDir()."/mobs/mm_".$id.'/'.$new_match[0])) + if (is_file(ilUtil::getWebspaceDir() . "/mobs/mm_" . $id . '/' . $new_match[0])) { - $media[$new_match[0]] = file_get_contents(ilUtil::getWebspaceDir()."/mobs/mm_".$id.'/'.$new_match[0]); + $media[$new_match[0]] = file_get_contents(ilUtil::getWebspaceDir() . "/mobs/mm_" . $id . '/' . $new_match[0]); } } + return $media; } /** * Add an RTE text * This will change the media references and wrap the text in CDATA - * @param ilXmlWriter XML writer - * @param string text to add - * @param string tag for the element - * @param array attributes + * @param ilXmlWriter XML writer + * @param string text to add + * @param string tag for the element + * @param array attributes */ private function addRTEText($a_xml_writer, $a_text, $a_tag = 'text', $a_attr = null) { - $text = preg_replace( - '/src=".*\/mobs\/mm_([0-9]+)\/([^"]+)"/', 'src="@@PLUGINFILE@@/$2"', $a_text); + $text = preg_replace('/src=".*\/mobs\/mm_([0-9]+)\/([^"]+)"/', 'src="@@PLUGINFILE@@/$2"', $a_text); - $text = ''; + $text = ''; $a_xml_writer->xmlElement($a_tag, NULL, $text, false, false); } @@ -324,19 +365,15 @@ private function addRTEText($a_xml_writer, $a_text, $a_tag = 'text', $a_attr = n /** * Add media files as elements - * @param ilXmlWriter XML writer - * @param array name => content - * @param string tag for the element + * @param ilXmlWriter XML writer + * @param array name => content + * @param string tag for the element */ - private function addRTEMedia($a_xml_writer, $a_media, $a_tag = 'file') + private function addRTEMedia($a_xml_writer, $a_media, $a_tag = 'file') { foreach ($a_media as $name => $content) { - $attr = array ( - 'name' => $name, - 'path' => '/', - 'encoding' => 'base64' - ); + $attr = array('name' => $name, 'path' => '/', 'encoding' => 'base64'); $a_xml_writer->xmlElement('file', $attr, base64_encode($content), false, false); } } diff --git a/classes/model/class.assStackQuestionStackQuestion.php b/classes/model/class.assStackQuestionStackQuestion.php index e75217da..fe0064d6 100644 --- a/classes/model/class.assStackQuestionStackQuestion.php +++ b/classes/model/class.assStackQuestionStackQuestion.php @@ -271,7 +271,7 @@ public function createSeed($ilias_question, $seed = -1, $authorized = TRUE) global $DIC; $lng = $DIC->language(); - switch (sizeof($ilias_question->getDeployedSeeds())) + switch (!empty($ilias_question->getDeployedSeeds())) { //No deployed seeds for this question. case 0: @@ -442,7 +442,7 @@ public function createInputs(assStackQuestion $question) $stack_inputs[$input_name] = $this->getStackFactory()->get("input_object", $input_parameters); } - if (sizeof($stack_inputs)) + if (!empty($stack_inputs)) { $this->setInputs($stack_inputs); } diff --git a/classes/model/ilias_object/test/class.assStackQuestionTest.php b/classes/model/ilias_object/test/class.assStackQuestionTest.php index 776b7851..36974198 100644 --- a/classes/model/ilias_object/test/class.assStackQuestionTest.php +++ b/classes/model/ilias_object/test/class.assStackQuestionTest.php @@ -153,7 +153,7 @@ public static function _read($question_id, $test_case = '') //Reading test data $test->setTestInputs(assStackQuestionTestInput::_read($question_id, $test->getTestCase())); $test->setTestExpected(assStackQuestionTestExpected::_read($question_id, $test->getTestCase())); - $test->setNumberOfTests(sizeof($test->getTestInputs())); + $test->setNumberOfTests(!empty($test->getTestInputs())); $tests[$test->getTestCase()] = $test; } @@ -203,7 +203,7 @@ public function checkTest($solve_problems = TRUE) return false; } //Arrays filled in: - if (sizeof($this->getTestInputs()) AND sizeof($this->getTestExpected())) { + if (!empty($this->getTestInputs()) AND sizeof($this->getTestExpected())) { return true; } } diff --git a/classes/model/question_display/class.assStackQuestionDisplay.php b/classes/model/question_display/class.assStackQuestionDisplay.php index ba035ec2..236709fc 100644 --- a/classes/model/question_display/class.assStackQuestionDisplay.php +++ b/classes/model/question_display/class.assStackQuestionDisplay.php @@ -167,12 +167,16 @@ private function replacementForInputPlaceholders($input, $input_name, $in_test, //In assStackQuestionDisplay the User response should be store with the "value" format for assStackQuestionUtils::_getUserResponse. $student_answer = $this->getUserResponse($input_name, $in_test); //Bug https://www.ilias.de/mantis/view.php?id=22129 about matrix syntax hint - if (!sizeof($student_answer) AND ($input->get_parameter('syntaxHint') != '') AND is_a($input, 'stack_matrix_input')) + if (is_array($student_answer)) { - $student_answer = assStackQuestionUtils::_changeUserResponseStyle(array($input_name => $input->get_parameter('syntaxHint')), $this->getQuestion()->getQuestionId(), array($input_name => $input), 'reduced_to_value'); - $student_answer = $student_answer["xqcas_input_" . $input_name . "_value"]; + if (!sizeof($student_answer) AND ($input->get_parameter('syntaxHint') != '') AND is_a($input, 'stack_matrix_input')) + { + $student_answer = assStackQuestionUtils::_changeUserResponseStyle(array($input_name => $input->get_parameter('syntaxHint')), $this->getQuestion()->getQuestionId(), array($input_name => $input), 'reduced_to_value'); + $student_answer = $student_answer["xqcas_input_" . $input_name . "_value"]; + } } + //Create input state if ($in_test) { @@ -478,12 +482,16 @@ public function replacementForValidationInput($input, $input_name, $in_test, $re //In assStackQuestionDisplay the User response should be store with the "value" format for assStackQuestionUtils::_getUserResponse. $student_answer = $this->getUserResponse($input_name, $in_test); //Bug https://www.ilias.de/mantis/view.php?id=22129 about matrix syntax hint - if (!sizeof($student_answer) AND ($input->get_parameter('syntaxHint') != '') AND is_a($input, 'stack_matrix_input')) + if (is_array($student_answer)) { - $student_answer = assStackQuestionUtils::_changeUserResponseStyle(array($input_name => $input->get_parameter('syntaxHint')), $this->getQuestion()->getQuestionId(), array($input_name => $input), 'reduced_to_value'); - $student_answer = $student_answer["xqcas_input_" . $input_name . "_value"]; + if (!sizeof($student_answer) AND ($input->get_parameter('syntaxHint') != '') AND is_a($input, 'stack_matrix_input')) + { + $student_answer = assStackQuestionUtils::_changeUserResponseStyle(array($input_name => $input->get_parameter('syntaxHint')), $this->getQuestion()->getQuestionId(), array($input_name => $input), 'reduced_to_value'); + $student_answer = $student_answer["xqcas_input_" . $input_name . "_value"]; + } } + $input_state = $this->getQuestion()->getInputStates($input_name); $input_size = (string)$input->get_parameter("boxWidth"); diff --git a/classes/stack/cas/connector.dbcache.class.php b/classes/stack/cas/connector.dbcache.class.php index 11b70d1a..c92d310f 100644 --- a/classes/stack/cas/connector.dbcache.class.php +++ b/classes/stack/cas/connector.dbcache.class.php @@ -119,7 +119,7 @@ protected function get_cached_result($command) // If there was more than one record in the cache (due to a race condition) // drop the duplicates. ////fim: #9 Use ILIAS DB instead of Moodle DB - if (sizeof($data) > 1) + if (!empty($data)) { unset($data[0]); foreach ($data as $record) diff --git a/classes/utils/class.assStackQuestionUtils.php b/classes/utils/class.assStackQuestionUtils.php index 446ad929..45600359 100644 --- a/classes/utils/class.assStackQuestionUtils.php +++ b/classes/utils/class.assStackQuestionUtils.php @@ -146,11 +146,11 @@ public static function _getUserResponse($question_id, array $inputs, array $prev $current_response = array(); $user_response_from_db = array(); - if (sizeof($previous_response)) + if (!empty($previous_response)) { foreach ($previous_response["prt"] as $prt_name => $prt_info) { - if (sizeof($prt_info["response"])) + if (!empty($prt_info["response"])) { foreach ($prt_info["response"] as $input_name => $input_info) { diff --git a/plugin.php b/plugin.php index b3d68e02..2bd8993b 100644 --- a/plugin.php +++ b/plugin.php @@ -9,7 +9,7 @@ // code version; must be changed for all code changes -$version = "3.1.4"; +$version = "3.1.5"; // ilias min and max version; must always reflect the versions that should // run with the plugin From d2f759606a9a1355d077da2b18b76e87d8ea85dc Mon Sep 17 00:00:00 2001 From: jcopado Date: Tue, 10 Sep 2019 14:52:19 +0200 Subject: [PATCH 11/23] 3.1.6 --- README.md | 6 +++++- classes/class.assStackQuestionGUI.php | 10 ++++++++-- plugin.php | 2 +- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4c41cf45..6955a3da 100644 --- a/README.md +++ b/README.md @@ -110,4 +110,8 @@ This version includes support for PHP 7.2 in ILIAS 5.4 platform, during the proc Version 3.1.5 (2019-08-26) for ILIAS 5.4 ---------------------------------------- -Some bugs in PHP 7.2 installations has been solved. \ No newline at end of file +Some bugs in PHP 7.2 installations has been solved. + +Version 3.1.6 (2019-09-10) for ILIAS 5.4 +---------------------------------------- +Solved some bugs related to Copy of PRTs \ No newline at end of file diff --git a/classes/class.assStackQuestionGUI.php b/classes/class.assStackQuestionGUI.php index 374a3d41..63f89508 100644 --- a/classes/class.assStackQuestionGUI.php +++ b/classes/class.assStackQuestionGUI.php @@ -248,7 +248,7 @@ public function deletionManagement() if (is_a($paste_prt, 'assStackQuestionPRT')) { - $paste_prt->setPRTId(""); + $paste_prt->setPRTId(-1); $paste_prt->setQuestionId($this->object->getId()); $paste_prt->setPRTName($generated_prt_name); $paste_prt->save(); @@ -257,12 +257,18 @@ public function deletionManagement() { if (is_a($prt_node, 'assStackQuestionPRTNode')) { - $prt_node->setNodeId(""); + $prt_node->setNodeId(-1); $prt_node->setQuestionId($this->object->getId()); $prt_node->setPRTName($generated_prt_name); $prt_node->save(); } } + + //Solve #26077 + //Include placeholder in specific feedback + $current_specific_feedback = $this->object->getOptions()->getSpecificFeedback(); + $new_specific_feedback = "

" . $current_specific_feedback . "[[feedback:" . $generated_prt_name . "]]

"; + $_POST["options_specific_feedback"] = $new_specific_feedback; } unset($_SESSION['copy_prt']); ilUtil::sendInfo($lng->txt("qpl_qst_xqcas_prt_paste"), TRUE); diff --git a/plugin.php b/plugin.php index 2bd8993b..03aac235 100644 --- a/plugin.php +++ b/plugin.php @@ -9,7 +9,7 @@ // code version; must be changed for all code changes -$version = "3.1.5"; +$version = "3.1.6"; // ilias min and max version; must always reflect the versions that should // run with the plugin From 07cacc42e04ee3bbc0f5d95fddd91d6a03037df3 Mon Sep 17 00:00:00 2001 From: jcopado Date: Fri, 20 Sep 2019 12:11:45 +0200 Subject: [PATCH 12/23] 3.1.6 --- README.md | 6 +++++- classes/model/class.assStackQuestionStackQuestion.php | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6955a3da..02d407e1 100644 --- a/README.md +++ b/README.md @@ -114,4 +114,8 @@ Some bugs in PHP 7.2 installations has been solved. Version 3.1.6 (2019-09-10) for ILIAS 5.4 ---------------------------------------- -Solved some bugs related to Copy of PRTs \ No newline at end of file +Solved some bugs related to Copy of PRTs + +Bugs currently solved +---------------------------------------- +Bug about deployed seeds creation: Now more than one seed per question can be created. \ No newline at end of file diff --git a/classes/model/class.assStackQuestionStackQuestion.php b/classes/model/class.assStackQuestionStackQuestion.php index fe0064d6..0a2a2fe8 100644 --- a/classes/model/class.assStackQuestionStackQuestion.php +++ b/classes/model/class.assStackQuestionStackQuestion.php @@ -271,7 +271,7 @@ public function createSeed($ilias_question, $seed = -1, $authorized = TRUE) global $DIC; $lng = $DIC->language(); - switch (!empty($ilias_question->getDeployedSeeds())) + switch (sizeof($ilias_question->getDeployedSeeds())) { //No deployed seeds for this question. case 0: From 06122dd3ef1668006ba48e31738270e9369b2714 Mon Sep 17 00:00:00 2001 From: jcopado Date: Mon, 30 Sep 2019 13:36:52 +0200 Subject: [PATCH 13/23] 3.1.6 Solved #26179 --- README.md | 3 ++- classes/utils/class.assStackQuestionUtils.php | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 02d407e1..2930c2b3 100644 --- a/README.md +++ b/README.md @@ -118,4 +118,5 @@ Solved some bugs related to Copy of PRTs Bugs currently solved ---------------------------------------- -Bug about deployed seeds creation: Now more than one seed per question can be created. \ No newline at end of file +Bug about deployed seeds creation: Now more than one seed per question can be created. +https://mantis.ilias.de/view.php?id=26179 About crashing in test results \ No newline at end of file diff --git a/classes/utils/class.assStackQuestionUtils.php b/classes/utils/class.assStackQuestionUtils.php index 45600359..bbd993b8 100644 --- a/classes/utils/class.assStackQuestionUtils.php +++ b/classes/utils/class.assStackQuestionUtils.php @@ -670,6 +670,8 @@ public static function _getContentStylesAvailable() */ public static function _getFeedbackStyledText($a_text, $a_format) { + require_once('./Customizing/global/plugins/Modules/TestQuestionPool/Questions/assStackQuestion/classes/model/configuration/class.assStackQuestionConfig.php'); + //Get Styles assigned to Formats $config_options = assStackQuestionConfig::_getStoredSettings("feedback"); require_once "./Services/Style/Content/classes/class.ilObjStyleSheet.php"; @@ -717,6 +719,8 @@ public static function _getActiveContentStyleId() } public static function _replaceFeedbackPlaceHolders($feedback){ + require_once('./Customizing/global/plugins/Modules/TestQuestionPool/Questions/assStackQuestion/classes/model/configuration/class.assStackQuestionConfig.php'); + //Get Styles assigned to Formats $config_options = assStackQuestionConfig::_getStoredSettings("feedback"); From 65e85be304004b57c1b7cb6cbe084239240e1cb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Copado?= Date: Tue, 19 Nov 2019 11:17:44 +0100 Subject: [PATCH 14/23] previous 3.1.7 --- README.md | 10 +++++++--- .../class.assStackQuestionAuthoringGUI.php | 2 +- classes/class.assStackQuestionGUI.php | 8 +++++++- classes/utils/class.assStackQuestionUtils.php | 2 +- classes/utils/instant_validation.php | 4 ++++ classes/utils/validation.php | 6 +++++- 6 files changed, 25 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 2930c2b3..89010d35 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,11 @@ Version 3.1.6 (2019-09-10) for ILIAS 5.4 ---------------------------------------- Solved some bugs related to Copy of PRTs -Bugs currently solved +Version 3.1.7 ---------------------------------------- -Bug about deployed seeds creation: Now more than one seed per question can be created. -https://mantis.ilias.de/view.php?id=26179 About crashing in test results \ No newline at end of file +- Bugs solved: + - Bug about deployed seeds creation: Now more than one seed per question can be created. + - Solved problem when importing from MoodleXML questions with specific feedback variables in a PHP 7.2 platform. + - Solved #23309 and #22729 about reestructuring a PRT. Now first node will be set as node 1 instead of 0. Previous questions with node 0 remains with node 0, so If you want to use a different node as root, you can copy and paste the Node 0, in the same prt and delete the old node 0. + - https://mantis.ilias.de/view.php?id=26179 About crashing in test results + diff --git a/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php b/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php index 4e38a53b..6bb81cb2 100644 --- a/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php +++ b/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php @@ -275,7 +275,7 @@ public function addPRTs() $new_prt->checkPRT(TRUE); //https://mantis.ilias.de/view.php?id=25290 - $new_prt_node = new assStackQuestionPRTNode(-1, $this->getQuestionGUI()->object->getId(), 'new_prt', '0', -1, -1); + $new_prt_node = new assStackQuestionPRTNode(-1, $this->getQuestionGUI()->object->getId(), 'new_prt', '1', -1, -1); $new_prt_node->setAnswerTest($this->default["prt_node_answer_test"]); $new_prt_node->setQuiet($this->default["prt_node_quiet"]); $new_prt_node->setTestOptions($this->default["prt_node_options"]); diff --git a/classes/class.assStackQuestionGUI.php b/classes/class.assStackQuestionGUI.php index 63f89508..8dd98da0 100644 --- a/classes/class.assStackQuestionGUI.php +++ b/classes/class.assStackQuestionGUI.php @@ -415,7 +415,7 @@ public function writeQuestionSpecificPostData() { //the prt name given is not used in this question $new_prt = new assStackQuestionPRT(-1, $this->object->getId()); - $new_prt_node = new assStackQuestionPRTNode(-1, $this->object->getId(), ilUtil::stripSlashes($_POST['prt_new_prt_name']), '0', -1, -1); + $new_prt_node = new assStackQuestionPRTNode(-1, $this->object->getId(), ilUtil::stripSlashes($_POST['prt_new_prt_name']), '1', -1, -1); $new_prt->setPRTNodes(array('0' => $new_prt_node)); $new_prt->writePostData('new_prt', ilUtil::stripSlashes($_POST['prt_new_prt_name']), $this->getRTETags()); @@ -667,6 +667,12 @@ function getSolutionOutput($active_id, $pass = NULL, $graphicalOutput = FALSE, $ { //User Solution //Returns user solution HTML + //#25174 + if(isset($_GET["cmd"])){ + if($_GET["cmd"] == "outCorrectSolution"){ + $show_feedback = TRUE; + } + } $solution_output = $this->getQuestionOutput($solutions, FALSE, $show_feedback, TRUE); //2.3.12 add feedback to solution $solution_output .= $this->getSpecificFeedbackOutput($solutions); diff --git a/classes/utils/class.assStackQuestionUtils.php b/classes/utils/class.assStackQuestionUtils.php index bbd993b8..1ddc1615 100644 --- a/classes/utils/class.assStackQuestionUtils.php +++ b/classes/utils/class.assStackQuestionUtils.php @@ -627,7 +627,7 @@ public static function _adaptUserResponseTo($user_response, $question_id, $forma { if ($format == "only_input_names") { - $adapted_user_response[str_replace("xqcas_" . $question_id . "_", "", $input_name)] = $input_value; + $adapted_user_response[str_replace("xqcas_" . $question_id . "_", "", $input_name)] = ilUtil::stripScriptHTML($input_value); } } diff --git a/classes/utils/instant_validation.php b/classes/utils/instant_validation.php index bcb484a2..3456a867 100644 --- a/classes/utils/instant_validation.php +++ b/classes/utils/instant_validation.php @@ -39,6 +39,10 @@ function checkUserResponse($question_id, $input_name, $user_response) $active_id = $_GET['active_id']; require_once "./Modules/Test/classes/class.ilObjTest.php"; $pass = ilObjTest::_getPass($active_id); + + //Secure input + $user_response = ilutil::stripScriptHTML($user_response); + if (is_int($active_id) AND is_int($pass)) { $stack_question = new assStackQuestionStackQuestion($active_id, $pass); diff --git a/classes/utils/validation.php b/classes/utils/validation.php index 3ce70703..96c982d9 100644 --- a/classes/utils/validation.php +++ b/classes/utils/validation.php @@ -35,7 +35,11 @@ function checkUserResponse($question_id, $input_name, $user_response) $active_id = $_GET['active_id']; require_once "./Modules/Test/classes/class.ilObjTest.php"; $pass = ilObjTest::_getPass($active_id); - if (is_int($active_id) AND is_int($pass)) + + //Secure input + $user_response = ilutil::stripScriptHTML($user_response); + + if (is_int($active_id) AND is_int($pass)) { $stack_question = new assStackQuestionStackQuestion($active_id, $pass); $stack_question->init($ilias_question, 8); From e681e9599dbe2c0ec45fda0015d6301e217c929d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Copado?= Date: Wed, 27 Nov 2019 15:09:15 +0100 Subject: [PATCH 15/23] 3.1.7 --- README.md | 4 +- .../class.assStackQuestionDisplay.php | 1067 ++++++++--------- .../class.assStackQuestionFeedback.php | 14 + .../stack/input/dropdown/dropdown.class.php | 5 +- plugin.php | 2 +- 5 files changed, 520 insertions(+), 572 deletions(-) diff --git a/README.md b/README.md index 89010d35..4970f30c 100644 --- a/README.md +++ b/README.md @@ -116,11 +116,13 @@ Version 3.1.6 (2019-09-10) for ILIAS 5.4 ---------------------------------------- Solved some bugs related to Copy of PRTs -Version 3.1.7 +Version 3.1.7 (2019-11-27) for ILIAS 5.4 ---------------------------------------- - Bugs solved: - Bug about deployed seeds creation: Now more than one seed per question can be created. - Solved problem when importing from MoodleXML questions with specific feedback variables in a PHP 7.2 platform. - Solved #23309 and #22729 about reestructuring a PRT. Now first node will be set as node 1 instead of 0. Previous questions with node 0 remains with node 0, so If you want to use a different node as root, you can copy and paste the Node 0, in the same prt and delete the old node 0. - https://mantis.ilias.de/view.php?id=26179 About crashing in test results + - Solved #25225 about validation after checking + - Solved #25318 about dropdown best solution problem diff --git a/classes/model/question_display/class.assStackQuestionDisplay.php b/classes/model/question_display/class.assStackQuestionDisplay.php index 236709fc..de93cb6a 100644 --- a/classes/model/question_display/class.assStackQuestionDisplay.php +++ b/classes/model/question_display/class.assStackQuestionDisplay.php @@ -19,575 +19,504 @@ class assStackQuestionDisplay { - /** - * Plugin instance for templates and language management - * @var ilassStackQuestionPlugin - */ - private $plugin; - - /** - * STACK version of the question - * @var assStackQuestionStackQuestion - */ - private $question; - - /** - * - * @var ilTemplate - */ - private $template; - - /** - * - * @var array - */ - private $user_response; - - /** - * - * @var string - */ - private $question_text; - - /** - * @var array - * This array has the following structure: - * ['prts'] = array of PRT feedback with $prt_name as key, contains 2 fields. - * - ['general'] that can have the following values: 1 for correct, 0 for partially correct and -1 for incorrect. - * - ['specific'] that have an string with the specific feedback for that PRT instantiated. - * ['show'] = Boolean, true when feedback must be shown and false if not. - */ - private $inline_feedback; - - - /** - * Sets all information needed for question display, - * Be aware of $question, here is not an assStackQuestion but an assStackQuestionStackQuestion object - * @param ilassStackQuestionPlugin $plugin - * @param assStackQuestionStackQuestion $question - * @param array OR boolean $user_response - */ - function __construct(ilassStackQuestionPlugin $plugin, assStackQuestionStackQuestion $question, $user_response = NULL, $inline_feedback = TRUE) - { - //Set plugin object - $this->setPlugin($plugin); - //Set question object to be displayed - $this->setQuestion($question); - //Set user solutions - //In assStackQuestionDisplay the User response should be stored with the "value" format for assStackQuestionUtils::_getUserResponse. - $this->setUserResponse($user_response); - //Set specific data and variables for the display - //Set question text - $this->setQuestionText($question->getQuestionTextInstantiated()); - //Set template for question display - $this->setTemplate($plugin->getTemplate("tpl.il_as_qpl_xqcas_question_display.html")); - - //2.3 Set the inline feedback data - $this->setInlineFeedback($inline_feedback); - } - - /** - * ### MAIN METHOD OF THIS CLASS ### - * This method is called from assStackQuestionGUI or assStackQuestionPreview to get the question Display. - * @return array STACK Questiontion display data - */ - public function getQuestionDisplayData($in_test = FALSE) - { - $display_data = array(); - - //Set Question text instantiated - if ($in_test) - { - $display_data['question_text'] = $this->getQuestionText(); - } else - { - $display_data['question_text'] = $this->getQuestion()->getQuestionTextInstantiated(); - } - - //Specific feedback - $display_data['question_specific_feedback'] = $this->getQuestion()->getSpecificFeedbackInstantiated(); - - //Set question_id - $display_data['question_id'] = (string)$this->getQuestion()->getQuestionId(); - - //Step 1: Get the replacement per each placeholder. - foreach ($this->getQuestion()->getInputs() as $input_name => $input) - { - //Step 1.1: Replacement for input placeholders - $display_data['inputs'][$input_name]['display'] = $this->replacementForInputPlaceholders($input, $input_name, $in_test, FALSE); - $display_data['inputs'][$input_name]['display_rendered'] = $this->replacementForInputPlaceholders($input, $input_name, $in_test, TRUE); - $display_data['inputs'][$input_name]['validation'] = $this->replacementForValidationInput($input, $input_name, $in_test, TRUE); - if (is_a($input, "stack_equiv_input") OR is_a($input, "stack_textarea_input")) - { - $display_data['inputs'][$input_name]['text_area'] = TRUE; - } else - { - $display_data['inputs'][$input_name]['text_area'] = FALSE; - } - if (is_a($input, "stack_radio_input") OR is_a($input, "stack_dropdown_input") OR is_a($input, "stack_checkbox_input") OR is_a($input, "stack_notes_input")) - { - $display_data['inputs'][$input_name]['show_validation'] = 0; - } else - { - $display_data['inputs'][$input_name]['show_validation'] = $input->get_parameter("showValidation"); - } - //Step 1.2: Replacement for validation placeholders - if ((int)$this->getQuestion()->getInputs($input_name)->get_parameter("showValidation")) - { - $display_data['validation'][$input_name] = $this->replacementForValidationPlaceholders($input, $input_name); - } else - { - $display_data['validation'][$input_name] = ""; - } - //Step 1.3 set matrix info - if (is_a($input, "stack_matrix_input")) - { - $display_data['inputs'][$input_name]['matrix_w'] = $input->width; - $display_data['inputs'][$input_name]['matrix_h'] = $input->height; - } - } - //Step 2: Get the replacement per each Feedback placeholder - foreach ($this->getQuestion()->getPRTs() as $prt_name => $prt) - { - //Step 1.1: Replacement for input placeholders - $display_data['prts'][$prt_name]['display'] = $this->replacementForPRTPlaceholders($prt, $prt_name, $in_test); - } - - return $display_data; - } - - /** - * Replace input placeholders by correspondant HTML code for the input - * @param stack_input $input - * @param string $input_name - */ - private function replacementForInputPlaceholders($input, $input_name, $in_test, $render_display = FALSE) - { - //Get student answer for this inputF - //In assStackQuestionDisplay the User response should be store with the "value" format for assStackQuestionUtils::_getUserResponse. - $student_answer = $this->getUserResponse($input_name, $in_test); - //Bug https://www.ilias.de/mantis/view.php?id=22129 about matrix syntax hint - if (is_array($student_answer)) - { - if (!sizeof($student_answer) AND ($input->get_parameter('syntaxHint') != '') AND is_a($input, 'stack_matrix_input')) - { - $student_answer = assStackQuestionUtils::_changeUserResponseStyle(array($input_name => $input->get_parameter('syntaxHint')), $this->getQuestion()->getQuestionId(), array($input_name => $input), 'reduced_to_value'); - $student_answer = $student_answer["xqcas_input_" . $input_name . "_value"]; - } - } - - - //Create input state - if ($in_test) - { - $state = $this->getQuestion()->getInputState($input_name, $student_answer[$input_name], $input->get_parameter('forbidWords', '')); - - } else - { - $state = $this->getQuestion()->getInputState($input_name, $student_answer, $input->get_parameter('forbidWords', '')); - } - if ($render_display) - { - //Solve problem with string input type - if (is_array($student_answer)) - { - if (get_class($input) == 'stack_matrix_input') - { - //https://mantis.ilias.de/view.php?id=25256 - return $state->contentsdisplayed; - } else - { - if ($student_answer[$input_name] == NULL) - { - return ""; - } - } - } - - return $state->contentsdisplayed; - } - //Get teacher answer value for equivalence reasoning input firstline problem #22847 - $ta_value = $this->getQuestion()->getSession()->get_value_key($input->get_teacher_answer()); - - //Return renderised input - if (get_class($input) == 'stack_algebraic_input') - { - $input_info = new stdClass(); - $input_info->input = $input; - $input_info->name = $input_name; - $input_info->state = $state; - $input_info->teacher_answer = $ta_value; - - return $input_info; - } else - { - if (is_subclass_of($input, 'stack_dropdown_input')) - { - return $input->render($state, 'xqcas_' . $this->getQuestion()->getQuestionId() . '_' . $input_name, FALSE, $ta_value); - } else - { - return $input->render($state, 'xqcas_' . $this->getQuestion()->getQuestionId() . '_' . $input_name, FALSE, $ta_value); - } - } - } - - /** - * Replace validation placeholders by validation button. - * This is different thatn STACK because at the moment instant validtaion is not - * supported by STACK Questionestion plugin. - * @param stack_input $input - * @param string $input_name - */ - private function replacementForValidationPlaceholders($input, $input_name) - { - if (!is_a($input, 'stack_boolean_input') AND !is_subclass_of($input, 'stack_dropdown_input') AND !is_a($input, 'stack_dropdown_input')) - { - if ($input->get_parameter("showValidation")) - { - if ($this->getQuestion()->getInstantValidation()) - { - return 'instant'; - } else - { - return 'button'; - } - } else - { - return 'hidden'; - } - } else - { - return FALSE; - } - } - - /** - * Replace Feedback placeholders by feedback in case it is needed - * @param $prt - * @param $prt_name - * @param $in_test - */ - private function replacementForPRTPlaceholders($prt, $prt_name, $in_test) - { - $string = ""; - if (!empty($this->getInlineFeedback())) - { - //feedback - //feedback - if (strlen($this->inline_feedback['prt'][$prt_name]['status']['message'])) - { - //Generic feedback - $string .= $this->inline_feedback['prt'][$prt_name]['status']['message']; - } - //Specific feedback - $string .= $this->inline_feedback['prt'][$prt_name]['feedback']; - $string .= $this->inline_feedback['prt'][$prt_name]['errors']; - } - - return assStackQuestionUtils::_getFeedbackStyledText($string, "feedback_default"); - } - - /* - * GETTERS AND SETTERS - */ - - /** - * @return ilassStackQuestionPlugin - */ - public function getPlugin() - { - return $this->plugin; - } - - /** - * @return assStackQuestionStackQuestion - */ - public function getQuestion() - { - return $this->question; - } - - /** - * @param string $selector - * @return array - */ - public function getUserResponse($selector = '', $in_test = FALSE) - { - $user_answer = array(); - - //In assStackQuestionDisplay the User response should be stored with the "value" format for assStackQuestionUtils::_getUserResponse. - if ($selector) - { - if (is_array($this->user_response)) - { - if ($in_test) - { - if (array_key_exists($selector, $this->user_response)) - { - foreach ($this->getQuestion()->getInputs() as $input_name => $input) - { - if ($input_name == $selector) - { - $user_answer[$selector] = array($selector => $this->user_response[$selector]); - } - } - } else - { - return array($selector => ''); - } - - return $user_answer[$selector]; - } else - { - //preview mode - foreach ($this->getQuestion()->getInputs() as $input_name => $input) - { - if ($input_name == $selector) - { - if (is_a($input, 'stack_matrix_input')) - { - $matrix_input = array(); - foreach ($this->user_response as $sub_key => $response) - { - if (strpos($sub_key, $input_name . "_") !== FALSE) - { - $matrix_input[$sub_key] = $response; - } - } - $user_answer[$selector] = $matrix_input; - } elseif (is_subclass_of($input, "stack_dropdown_input")) - { - $user_answer[$selector] = $this->user_response; - } else - { - $user_answer[$selector] = array($selector => $this->user_response[$selector]); - } - } - } - - return $user_answer[$selector]; - } - } else - { - return array(); - } - } else - { - return $this->user_response; - } - } - - /** - * @return string - */ - public function getQuestionText() - { - return $this->question_text; - } - - /** - * @return ilTemplate - */ - public function getTemplate() - { - return $this->template; - } - - - /** - * @return array - */ - public function getInlineFeedback($selector1 = '', $selector2 = '', $selector3 = '') - { - if ($selector1 AND !$selector2) - { - return $this->inline_feedback[$selector1]; - } elseif ($selector1 AND $selector2) - { - return $this->inline_feedback[$selector1][$selector2]; - } elseif ($selector1 AND $selector2 AND $selector3) - { - return $this->inline_feedback[$selector1][$selector2][$selector3]; - } else - { - return $this->inline_feedback; - } - } - - /** - * @param ilassStackQuestionPlugin $plugin - */ - public function setPlugin(ilassStackQuestionPlugin $plugin) - { - $this->plugin = $plugin; - } - - /** - * @param assStackQuestionStackQuestion $question - */ - public function setQuestion(assStackQuestionStackQuestion $question) - { - $this->question = $question; - } - - /** - * @param $user_response - * @param string $selector - */ - public function setUserResponse($user_response, $selector = '') - { - //In assStackQuestionDisplay the User response should be stored with the "value" format for assStackQuestionUtils::_getUserResponse. - if ($selector) - { - $this->user_response[$selector] = $user_response; - } else - { - $this->user_response = $user_response; - } - } - - /** - * @param $question_text - */ - public function setQuestionText($question_text) - { - $this->question_text = $question_text; - } - - /** - * @param ilTemplate $template - */ - public function setTemplate(ilTemplate $template) - { - $this->template = $template; - } - - /** - * @param array $inline_feedback - */ - public function setInlineFeedback($inline_feedback, $selector = '') - { - if ($selector) - { - $this->inline_feedback[$selector] = $inline_feedback; - } else - { - $this->inline_feedback = $inline_feedback; - } - } - - public function replacementForValidationInput($input, $input_name, $in_test, $render_display = FALSE) - { - //Get student answer for this inputF - //In assStackQuestionDisplay the User response should be store with the "value" format for assStackQuestionUtils::_getUserResponse. - $student_answer = $this->getUserResponse($input_name, $in_test); - //Bug https://www.ilias.de/mantis/view.php?id=22129 about matrix syntax hint - if (is_array($student_answer)) - { - if (!sizeof($student_answer) AND ($input->get_parameter('syntaxHint') != '') AND is_a($input, 'stack_matrix_input')) - { - $student_answer = assStackQuestionUtils::_changeUserResponseStyle(array($input_name => $input->get_parameter('syntaxHint')), $this->getQuestion()->getQuestionId(), array($input_name => $input), 'reduced_to_value'); - $student_answer = $student_answer["xqcas_input_" . $input_name . "_value"]; - } - } - - - $input_state = $this->getQuestion()->getInputStates($input_name); - $input_size = (string)$input->get_parameter("boxWidth"); - - if (is_a($input, "stack_algebraic_input") OR is_a($input, "stack_numerical_input") OR is_a($input, "stack_singlechar_input") OR is_a($input, "stack_boolean_input") OR is_a($input, "stack_units_input")) - { - if (is_array($student_answer[$input_name])) - { - $student_answer_value = $student_answer[$input_name][$input_name . "_val"]; - } elseif (is_string($student_answer[$input_name])) - { - $student_answer_value = $student_answer[$input_name]; - } - - $input_html = '' . $student_answer_value . ''; - - $validation_message = stack_string('studentValidation_yourLastAnswer', $input_state->contentsdisplayed); - - return "
" . $input_html . $validation_message . "
"; - } - if (is_a($input, "stack_matrix_input")) - { - $matrix_input_rows = (int)$input->height; - $matrix_input_columns = (int)$input->width; - - $user_matrix = ""; - for ($i = 0; $i < $matrix_input_rows; $i++) - { - $user_matrix .= ""; - for ($j = 0; $j < $matrix_input_columns; $j++) - { - $user_matrix .= ""; - } - $user_matrix .= ""; - } - $user_matrix .= "
"; - //https://mantis.ilias.de/view.php?id=25256 - if ($in_test) - { - $user_filled_input = '' . $student_answer[$input_name][$input_name . "_sub_" . $i . "_" . $j] . ''; - } else - { - $user_filled_input = '' . $student_answer[$input_name . "_sub_" . $i . "_" . $j] . ''; - } - $user_matrix .= $user_filled_input; - $user_matrix .= "
"; - - $validation_message = stack_string('studentValidation_yourLastAnswer', $input_state->contentsdisplayed); - - return "
" . $user_matrix . $validation_message . "
"; - } - if (is_a($input, "stack_checkbox_input")) - { - return ""; - } - if (is_a($input, "stack_radio_input")) - { - return ""; - } - if (is_a($input, "stack_dropdown_input")) - { - return ""; - } - if (is_a($input, "stack_equiv_input") or is_a($input, "stack_textarea_input")) - { - $feedback = ""; - $textarea_html = ""; - foreach ($input_state->contents as $key => $val) - { - $textarea_html .= '' . $val . '
'; - } - - $feedback .= html_writer::tag('p', ""); - - if ($input::INVALID == $input_state->status) - { - $feedback .= html_writer::tag('p', ""); - } - - if (!($input_state->lvars === '' or $input_state->lvars === '[]')) - { - $feedback .= ""; - } - $feedback .= "
" . $textarea_html . "" . stack_string('studentValidation_yourLastAnswer', $input_state->contentsdisplayed) . "
" . stack_string('studentValidation_invalidAnswer') . "
" . $input->tag_listofvariables($input_state->lvars) . "
"; - - return "
" . $feedback . "
"; - - } - if (is_a($input, "stack_notes_input")) - { - $string = assStackQuestionUtils::_getFeedbackStyledText($this->getPlugin()->txt("notes_best_solution_message"), "feedback_default"); - $result["value"] = $string; - $result["display"] = ""; - - return $result; - } - } + /** + * Plugin instance for templates and language management + * @var ilassStackQuestionPlugin + */ + private $plugin; + + /** + * STACK version of the question + * @var assStackQuestionStackQuestion + */ + private $question; + + /** + * + * @var ilTemplate + */ + private $template; + + /** + * + * @var array + */ + private $user_response; + + /** + * + * @var string + */ + private $question_text; + + /** + * @var array + * This array has the following structure: + * ['prts'] = array of PRT feedback with $prt_name as key, contains 2 fields. + * - ['general'] that can have the following values: 1 for correct, 0 for partially correct and -1 for incorrect. + * - ['specific'] that have an string with the specific feedback for that PRT instantiated. + * ['show'] = Boolean, true when feedback must be shown and false if not. + */ + private $inline_feedback; + + + /** + * Sets all information needed for question display, + * Be aware of $question, here is not an assStackQuestion but an assStackQuestionStackQuestion object + * @param ilassStackQuestionPlugin $plugin + * @param assStackQuestionStackQuestion $question + * @param array OR boolean $user_response + */ + function __construct(ilassStackQuestionPlugin $plugin, assStackQuestionStackQuestion $question, $user_response = NULL, $inline_feedback = TRUE) + { + //Set plugin object + $this->setPlugin($plugin); + //Set question object to be displayed + $this->setQuestion($question); + //Set user solutions + //In assStackQuestionDisplay the User response should be stored with the "value" format for assStackQuestionUtils::_getUserResponse. + $this->setUserResponse($user_response); + //Set specific data and variables for the display + //Set question text + $this->setQuestionText($question->getQuestionTextInstantiated()); + //Set template for question display + $this->setTemplate($plugin->getTemplate("tpl.il_as_qpl_xqcas_question_display.html")); + + //2.3 Set the inline feedback data + $this->setInlineFeedback($inline_feedback); + } + + /** + * ### MAIN METHOD OF THIS CLASS ### + * This method is called from assStackQuestionGUI or assStackQuestionPreview to get the question Display. + * @return array STACK Questiontion display data + */ + public function getQuestionDisplayData($in_test = FALSE) + { + $display_data = array(); + + //Set Question text instantiated + if ($in_test) { + $display_data['question_text'] = $this->getQuestionText(); + } else { + $display_data['question_text'] = $this->getQuestion()->getQuestionTextInstantiated(); + } + + //Specific feedback + $display_data['question_specific_feedback'] = $this->getQuestion()->getSpecificFeedbackInstantiated(); + + //Set question_id + $display_data['question_id'] = (string)$this->getQuestion()->getQuestionId(); + + //Step 1: Get the replacement per each placeholder. + foreach ($this->getQuestion()->getInputs() as $input_name => $input) { + //Step 1.1: Replacement for input placeholders + $display_data['inputs'][$input_name]['display'] = $this->replacementForInputPlaceholders($input, $input_name, $in_test, FALSE); + $display_data['inputs'][$input_name]['display_rendered'] = $this->replacementForInputPlaceholders($input, $input_name, $in_test, TRUE); + $display_data['inputs'][$input_name]['validation'] = $this->replacementForValidationInput($input, $input_name, $in_test, TRUE); + if (is_a($input, "stack_equiv_input") OR is_a($input, "stack_textarea_input")) { + $display_data['inputs'][$input_name]['text_area'] = TRUE; + } else { + $display_data['inputs'][$input_name]['text_area'] = FALSE; + } + if (is_a($input, "stack_radio_input") OR is_a($input, "stack_dropdown_input") OR is_a($input, "stack_checkbox_input") OR is_a($input, "stack_notes_input")) { + $display_data['inputs'][$input_name]['show_validation'] = 0; + } else { + $display_data['inputs'][$input_name]['show_validation'] = $input->get_parameter("showValidation"); + } + //Step 1.2: Replacement for validation placeholders + if ((int)$this->getQuestion()->getInputs($input_name)->get_parameter("showValidation")) { + $display_data['validation'][$input_name] = $this->replacementForValidationPlaceholders($input, $input_name); + } else { + $display_data['validation'][$input_name] = ""; + } + //Step 1.3 set matrix info + if (is_a($input, "stack_matrix_input")) { + $display_data['inputs'][$input_name]['matrix_w'] = $input->width; + $display_data['inputs'][$input_name]['matrix_h'] = $input->height; + } + } + //Step 2: Get the replacement per each Feedback placeholder + foreach ($this->getQuestion()->getPRTs() as $prt_name => $prt) { + //Step 1.1: Replacement for input placeholders + $display_data['prts'][$prt_name]['display'] = $this->replacementForPRTPlaceholders($prt, $prt_name, $in_test); + } + + return $display_data; + } + + /** + * Replace input placeholders by correspondant HTML code for the input + * @param stack_input $input + * @param string $input_name + */ + private function replacementForInputPlaceholders($input, $input_name, $in_test, $render_display = FALSE) + { + //Get student answer for this inputF + //In assStackQuestionDisplay the User response should be store with the "value" format for assStackQuestionUtils::_getUserResponse. + $student_answer = $this->getUserResponse($input_name, $in_test); + //Bug https://www.ilias.de/mantis/view.php?id=22129 about matrix syntax hint + if (is_array($student_answer)) { + if (!sizeof($student_answer) AND ($input->get_parameter('syntaxHint') != '') AND is_a($input, 'stack_matrix_input')) { + $student_answer = assStackQuestionUtils::_changeUserResponseStyle(array($input_name => $input->get_parameter('syntaxHint')), $this->getQuestion()->getQuestionId(), array($input_name => $input), 'reduced_to_value'); + $student_answer = $student_answer["xqcas_input_" . $input_name . "_value"]; + } + } + + + //Create input state + if ($in_test) { + $state = $this->getQuestion()->getInputState($input_name, $student_answer[$input_name], $input->get_parameter('forbidWords', '')); + + } else { + $state = $this->getQuestion()->getInputState($input_name, $student_answer, $input->get_parameter('forbidWords', '')); + } + if ($render_display) { + //Solve problem with string input type + if (is_array($student_answer)) { + if (get_class($input) == 'stack_matrix_input') { + //https://mantis.ilias.de/view.php?id=25256 + return $state->contentsdisplayed; + } else { + if ($student_answer[$input_name] == NULL) { + return ""; + } + } + } + + return $state->contentsdisplayed; + } + //Get teacher answer value for equivalence reasoning input firstline problem #22847 + $ta_value = $this->getQuestion()->getSession()->get_value_key($input->get_teacher_answer()); + + //Return renderised input + if (get_class($input) == 'stack_algebraic_input') { + $input_info = new stdClass(); + $input_info->input = $input; + $input_info->name = $input_name; + $input_info->state = $state; + $input_info->teacher_answer = $ta_value; + + return $input_info; + } else { + if (is_subclass_of($input, 'stack_dropdown_input')) { + return $input->render($state, 'xqcas_' . $this->getQuestion()->getQuestionId() . '_' . $input_name, FALSE, $ta_value); + } else { + return $input->render($state, 'xqcas_' . $this->getQuestion()->getQuestionId() . '_' . $input_name, FALSE, $ta_value); + } + } + } + + /** + * Replace validation placeholders by validation button. + * This is different thatn STACK because at the moment instant validtaion is not + * supported by STACK Questionestion plugin. + * @param stack_input $input + * @param string $input_name + */ + private function replacementForValidationPlaceholders($input, $input_name) + { + if (!is_a($input, 'stack_boolean_input') AND !is_subclass_of($input, 'stack_dropdown_input') AND !is_a($input, 'stack_dropdown_input')) { + if ($input->get_parameter("showValidation")) { + if ($this->getQuestion()->getInstantValidation()) { + return 'instant'; + } else { + return 'button'; + } + } else { + return 'hidden'; + } + } else { + return FALSE; + } + } + + /** + * Replace Feedback placeholders by feedback in case it is needed + * @param $prt + * @param $prt_name + * @param $in_test + */ + private function replacementForPRTPlaceholders($prt, $prt_name, $in_test) + { + $string = ""; + if (!empty($this->getInlineFeedback())) { + //feedback + //feedback + if (strlen($this->inline_feedback['prt'][$prt_name]['status']['message'])) { + //Generic feedback + $string .= $this->inline_feedback['prt'][$prt_name]['status']['message']; + } + //Specific feedback + $string .= $this->inline_feedback['prt'][$prt_name]['feedback']; + $string .= $this->inline_feedback['prt'][$prt_name]['errors']; + } + + return assStackQuestionUtils::_getFeedbackStyledText($string, "feedback_default"); + } + + /* + * GETTERS AND SETTERS + */ + + /** + * @return ilassStackQuestionPlugin + */ + public function getPlugin() + { + return $this->plugin; + } + + /** + * @return assStackQuestionStackQuestion + */ + public function getQuestion() + { + return $this->question; + } + + /** + * @param string $selector + * @return array + */ + public function getUserResponse($selector = '', $in_test = FALSE) + { + $user_answer = array(); + + //In assStackQuestionDisplay the User response should be stored with the "value" format for assStackQuestionUtils::_getUserResponse. + if ($selector) { + if (is_array($this->user_response)) { + if ($in_test) { + if (array_key_exists($selector, $this->user_response)) { + foreach ($this->getQuestion()->getInputs() as $input_name => $input) { + if ($input_name == $selector) { + $user_answer[$selector] = array($selector => $this->user_response[$selector]); + } + } + } else { + return array($selector => ''); + } + + return $user_answer[$selector]; + } else { + //preview mode + foreach ($this->getQuestion()->getInputs() as $input_name => $input) { + if ($input_name == $selector) { + if (is_a($input, 'stack_matrix_input')) { + $matrix_input = array(); + foreach ($this->user_response as $sub_key => $response) { + if (strpos($sub_key, $input_name . "_") !== FALSE) { + $matrix_input[$sub_key] = $response; + } + } + $user_answer[$selector] = $matrix_input; + } elseif (is_subclass_of($input, "stack_dropdown_input")) { + $user_answer[$selector] = $this->user_response; + } else { + $user_answer[$selector] = array($selector => $this->user_response[$selector]); + } + } + } + + return $user_answer[$selector]; + } + } else { + return array(); + } + } else { + return $this->user_response; + } + } + + /** + * @return string + */ + public function getQuestionText() + { + return $this->question_text; + } + + /** + * @return ilTemplate + */ + public function getTemplate() + { + return $this->template; + } + + + /** + * @return array + */ + public function getInlineFeedback($selector1 = '', $selector2 = '', $selector3 = '') + { + if ($selector1 AND !$selector2) { + return $this->inline_feedback[$selector1]; + } elseif ($selector1 AND $selector2) { + return $this->inline_feedback[$selector1][$selector2]; + } elseif ($selector1 AND $selector2 AND $selector3) { + return $this->inline_feedback[$selector1][$selector2][$selector3]; + } else { + return $this->inline_feedback; + } + } + + /** + * @param ilassStackQuestionPlugin $plugin + */ + public function setPlugin(ilassStackQuestionPlugin $plugin) + { + $this->plugin = $plugin; + } + + /** + * @param assStackQuestionStackQuestion $question + */ + public function setQuestion(assStackQuestionStackQuestion $question) + { + $this->question = $question; + } + + /** + * @param $user_response + * @param string $selector + */ + public function setUserResponse($user_response, $selector = '') + { + //In assStackQuestionDisplay the User response should be stored with the "value" format for assStackQuestionUtils::_getUserResponse. + if ($selector) { + $this->user_response[$selector] = $user_response; + } else { + $this->user_response = $user_response; + } + } + + /** + * @param $question_text + */ + public function setQuestionText($question_text) + { + $this->question_text = $question_text; + } + + /** + * @param ilTemplate $template + */ + public function setTemplate(ilTemplate $template) + { + $this->template = $template; + } + + /** + * @param array $inline_feedback + */ + public function setInlineFeedback($inline_feedback, $selector = '') + { + if ($selector) { + $this->inline_feedback[$selector] = $inline_feedback; + } else { + $this->inline_feedback = $inline_feedback; + } + } + + public function replacementForValidationInput($input, $input_name, $in_test, $render_display = FALSE) + { + //Get student answer for this inputF + //In assStackQuestionDisplay the User response should be store with the "value" format for assStackQuestionUtils::_getUserResponse. + $student_answer = $this->getUserResponse($input_name, $in_test); + //Bug https://www.ilias.de/mantis/view.php?id=22129 about matrix syntax hint + if (is_array($student_answer)) { + if (!sizeof($student_answer) AND ($input->get_parameter('syntaxHint') != '') AND is_a($input, 'stack_matrix_input')) { + $student_answer = assStackQuestionUtils::_changeUserResponseStyle(array($input_name => $input->get_parameter('syntaxHint')), $this->getQuestion()->getQuestionId(), array($input_name => $input), 'reduced_to_value'); + $student_answer = $student_answer["xqcas_input_" . $input_name . "_value"]; + } + } + + + $input_state = $this->getQuestion()->getInputStates($input_name); + $input_size = (string)$input->get_parameter("boxWidth"); + + if (is_a($input, "stack_algebraic_input") OR is_a($input, "stack_numerical_input") OR is_a($input, "stack_singlechar_input") OR is_a($input, "stack_boolean_input") OR is_a($input, "stack_units_input")) { + if (is_array($student_answer[$input_name])) { + $student_answer_value = $student_answer[$input_name][$input_name . "_val"]; + } elseif (is_string($student_answer[$input_name])) { + $student_answer_value = $student_answer[$input_name]; + } + + $input_html = '' . $student_answer_value . ''; + + $validation_message = stack_string('studentValidation_yourLastAnswer', $input_state->contentsdisplayed); + + #25225 add validation div wrapping + $validation_div = '
'; + return $validation_div . "
" . $input_html . $validation_message . "
"; + } + if (is_a($input, "stack_matrix_input")) { + $matrix_input_rows = (int)$input->height; + $matrix_input_columns = (int)$input->width; + + $user_matrix = ""; + for ($i = 0; $i < $matrix_input_rows; $i++) { + $user_matrix .= ""; + for ($j = 0; $j < $matrix_input_columns; $j++) { + $user_matrix .= ""; + } + $user_matrix .= ""; + } + $user_matrix .= "
"; + //https://mantis.ilias.de/view.php?id=25256 + if ($in_test) { + $user_filled_input = '' . $student_answer[$input_name][$input_name . "_sub_" . $i . "_" . $j] . ''; + } else { + $user_filled_input = '' . $student_answer[$input_name . "_sub_" . $i . "_" . $j] . ''; + } + $user_matrix .= $user_filled_input; + $user_matrix .= "
"; + + $validation_message = stack_string('studentValidation_yourLastAnswer', $input_state->contentsdisplayed); + +#25225 add validation div wrapping + $validation_div = '
'; + return $validation_div; + } + if (is_a($input, "stack_checkbox_input")) { + return ""; + } + if (is_a($input, "stack_radio_input")) { + return ""; + } + if (is_a($input, "stack_dropdown_input")) { + return ""; + } + if (is_a($input, "stack_equiv_input") or is_a($input, "stack_textarea_input")) { + $feedback = ""; + $textarea_html = ""; + foreach ($input_state->contents as $key => $val) { + $textarea_html .= '' . $val . '
'; + } + + $feedback .= html_writer::tag('p', ""); + + if ($input::INVALID == $input_state->status) { + $feedback .= html_writer::tag('p', ""); + } + + if (!($input_state->lvars === '' or $input_state->lvars === '[]')) { + $feedback .= ""; + } + $feedback .= "
" . $textarea_html . "" . stack_string('studentValidation_yourLastAnswer', $input_state->contentsdisplayed) . "
" . stack_string('studentValidation_invalidAnswer') . "
" . $input->tag_listofvariables($input_state->lvars) . "
"; + + return "
" . $feedback . "
"; + + } + if (is_a($input, "stack_notes_input")) { + $string = assStackQuestionUtils::_getFeedbackStyledText($this->getPlugin()->txt("notes_best_solution_message"), "feedback_default"); + $result["value"] = $string; + $result["display"] = ""; + + return $result; + } + } } \ No newline at end of file diff --git a/classes/model/question_evaluation/class.assStackQuestionFeedback.php b/classes/model/question_evaluation/class.assStackQuestionFeedback.php index 01c69fbf..13f5815a 100644 --- a/classes/model/question_evaluation/class.assStackQuestionFeedback.php +++ b/classes/model/question_evaluation/class.assStackQuestionFeedback.php @@ -473,6 +473,20 @@ public function getCorrectResponsePlaceholders($input_name = "") } if (is_a($input, "stack_dropdown_input")) { + //#25318 + $teacher_solution = $input->get_teacher_answer_display($input_state->contentsmodified, $input_state->contentsdisplayed); + if (is_string($teacher_solution)) { + if (strlen($teacher_solution)) { + $html = ""; + + $result["value"] = $html; + $result["display"] = ""; + + return $result; + } + } $html = ""; diff --git a/classes/stack/input/dropdown/dropdown.class.php b/classes/stack/input/dropdown/dropdown.class.php index aa4f598b..40e76759 100644 --- a/classes/stack/input/dropdown/dropdown.class.php +++ b/classes/stack/input/dropdown/dropdown.class.php @@ -448,7 +448,10 @@ public function maxima_to_response_array($in) { */ public function get_teacher_answer_display($value, $display) { // Can we really ignore the $value and $display inputs here and rely on the internal state? - return stack_string('teacheranswershow_disp', array('display' => $this->teacheranswerdisplay)); + //fau: #45 #25318 change this to do not return "a correct answer" + //return stack_string('teacheranswershow_disp', array('display' => $this->teacheranswerdisplay)); + return $this->teacheranswerdisplay; + //fau. } /** diff --git a/plugin.php b/plugin.php index 03aac235..ce661a46 100644 --- a/plugin.php +++ b/plugin.php @@ -9,7 +9,7 @@ // code version; must be changed for all code changes -$version = "3.1.6"; +$version = "3.1.7"; // ilias min and max version; must always reflect the versions that should // run with the plugin From f48e07391e49b73182aa2c1df9f1db6a82606e07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Copado?= Date: Wed, 4 Dec 2019 12:53:39 +0100 Subject: [PATCH 16/23] 3.1.7 Solve quotes issue. --- classes/stack/input/dropdown/dropdown.class.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/classes/stack/input/dropdown/dropdown.class.php b/classes/stack/input/dropdown/dropdown.class.php index 40e76759..f35a8471 100644 --- a/classes/stack/input/dropdown/dropdown.class.php +++ b/classes/stack/input/dropdown/dropdown.class.php @@ -450,7 +450,10 @@ public function get_teacher_answer_display($value, $display) { // Can we really ignore the $value and $display inputs here and rely on the internal state? //fau: #45 #25318 change this to do not return "a correct answer" //return stack_string('teacheranswershow_disp', array('display' => $this->teacheranswerdisplay)); - return $this->teacheranswerdisplay; + //Solves quotes issue + $ta = str_replace('"', "", $this->teacheranswerdisplay); + $ta = str_replace("'", "", $ta); + return $ta; //fau. } From 528c8134640398ea2cf49063e4cc41e534f9dcc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Copado?= Date: Fri, 6 Dec 2019 16:08:00 +0100 Subject: [PATCH 17/23] 3.1.7 Solve some import problems if using PHP 7.2 --- .../class.assStackQuestionMoodleImport.php | 3034 ++++++++--------- 1 file changed, 1416 insertions(+), 1618 deletions(-) diff --git a/classes/model/import/MoodleXML/class.assStackQuestionMoodleImport.php b/classes/model/import/MoodleXML/class.assStackQuestionMoodleImport.php index 3ece33cb..fddb6f08 100644 --- a/classes/model/import/MoodleXML/class.assStackQuestionMoodleImport.php +++ b/classes/model/import/MoodleXML/class.assStackQuestionMoodleImport.php @@ -19,1623 +19,1421 @@ */ class assStackQuestionMoodleImport { - /** - * Plugin instance for language management - * @var ilassStackQuestionPlugin - */ - private $plugin; - - /** - * ILIAS version of the question - * The current question - * @var assStackQuestion - */ - private $question; - - /** - * Question_id for the first question to import - * (When only one question, use this as Question_Id) - * @var int When first question this var is higher than 0. - */ - private $first_question; - - private $error_log; - - /** - * @var string allowed html tags, e.g. "..." - */ - private $rte_tags = ""; - - - /** - * media objects created for an imported question - * This list will be cleared for every new question - * @var array id => object - */ - private $media_objects = array(); - - - /** - * Set all the parameters for this question, including the creation of - * the first assStackQuestion object. - * @param ilassStackQuestionPlugin $plugin - * @param $first_question_id int the question_id for the first question to import. - */ - function __construct($plugin, $first_question_id, $parent_obj) - { - //Set Plugin and first question id. - $this->setPlugin($plugin); - $this->setFirstQuestion($first_question_id); - - //Creation of the first question. - $this->getPlugin()->includeClass('class.assStackQuestion.php'); - $this->setQuestion($parent_obj); - - //Initialization and load of stack wrapper classes - $this->getPlugin()->includeClass('utils/class.assStackQuestionInitialization.php'); - } - - /** - * ### MAIN METHOD OF THIS CLASS ### - * This method is called from assStackQuestion to import the questions from an MoodleXML file. - * @param $xml_file string the MoodleXML file - * @return mixed Status of the import - */ - public function import($xml_file) - { - //Step 1: Get data from XML. - $raw_data = $this->getDataFromXML($xml_file); - //Step 2: Import questions. - $import_status = $this->importQuestions($raw_data); - - //Step 3: Return status. - return $import_status; - } - - public function importQuestions($raw_data) - { - $number_of_questions_created = 0; - //For each question in the array - - //Check if is PHP 7.2 in case it is, data need some extra formatting - if (assStackQuestionUtils::_isPhP72()) - { - $raw_data = $this->php72Format($raw_data['question']); - } - - foreach ($raw_data['question'] as $data) - { - // start with a new list of media objects for each question - $this->clearMediaObjects(); - - //Check for not category - if (is_array($data['category'])) - { - continue; - } - - //Step 2.1: Create standard question - $ok = $this->createStandardQuestion($data); - if ($ok === FALSE) - { - //Do not continue creating question - $this->purgeMediaObjects(); - continue; - } - - //Step 2.2: Get Options from data and set as Options OBJ in cas_question - $question_options = $this->getOptionsFromXML($data); - $this->getQuestion()->setOptions($question_options); - - //Step 2.3: Get Inputs from data and set as Input OBJ in cas_question - $ok = $question_inputs = $this->getInputsFromXML($data['input']); - $this->getQuestion()->setInputs($question_inputs); - if ($ok === FALSE) - { - //Delete current question data - $this->getQuestion()->delete($this->getQuestion()->getId()); - $this->purgeMediaObjects(); - //Do not continue creating question - continue; - } - - //Step 2.4.A: Get PRT from data and set as PRT OBJ in cas_question - //Step 2.4.B: Get Nodes from each PRT and set as Node OBJ in each PRT. - $ok = $question_PRTs = $this->getPRTsFromXML($data['prt']); - $this->getQuestion()->setPotentialResponsesTrees($question_PRTs); - if ($ok === FALSE) - { - //Delete current question data - $this->getQuestion()->delete($this->getQuestion()->getId()); - $this->purgeMediaObjects(); - //Do not continue creating question - continue; - } - - //Step 2.5.A: Get Test from from data and set as Test OBJ in cas_question - //Step 2.5.B: Get Test Inputs and Expected from data and set as TestInput/Expected OBJ in cas_question - if (isset($data['qtest'])) - { - $question_tests = $this->getTestsFromXML($data['qtest']); - $this->getQuestion()->setTests($question_tests); - } else - { - $this->getQuestion()->setTests(array()); - } - - //Step 2.6: Get deployed seeds - if (isset($data['deployedseed'])) - { - $question_seeds = $this->getDeployedSeedsFromXML($data['deployedseed']); - $this->getQuestion()->setDeployedSeeds($question_seeds); - } else - { - $this->getQuestion()->setDeployedSeeds(array()); - } - - //Step 2.7: Get extra fields - $extra_info = $this->getExtraInfoFromXML($data); - $this->getQuestion()->setExtraInfo($extra_info); - - //Step 2.8: Fix possible errors - $question_is_ok = $this->checkQuestion($this->getQuestion()); - - //Step 2.9: Insert into DB or delete if question is not OK - if ($question_is_ok) - { - //Delete options from created question. - $this->deletePredefinedQuestionData($this->getQuestion()->getId()); - - //Save STACK Question data. - $this->getQuestion()->saveToDB($this->getQuestion()->getId(), TRUE); - $this->saveMediaObjectUsages($this->getQuestion()->getId()); - $number_of_questions_created++; - - //Set $question to a new question - $this->getQuestion()->setId(-1); - } else - { - //Delete current question data - $this->getQuestion()->delete($this->getQuestion()->getId()); - $this->purgeMediaObjects(); - } - } - if (!empty($this->error_log)) - { - ilUtil::sendFailure(implode('
', $this->error_log)); - } - - //Number of questions created info - if ($number_of_questions_created > 1) - { - ilUtil::sendSuccess($number_of_questions_created . ' ' . $this->getPlugin()->txt('import_number_of_questions_created')); - } elseif ($number_of_questions_created) - { - ilUtil::sendSuccess($number_of_questions_created . ' ' . $this->getPlugin()->txt('import_number_of_questions_created_1')); - } - } - - public function deletePredefinedQuestionData($question_id) - { - global $DIC; - $db = $DIC->database(); - - $query = 'DELETE FROM xqcas_options WHERE question_id = ' . $question_id; - $db->manipulate($query); - - $query = 'DELETE FROM xqcas_inputs WHERE question_id = ' . $question_id; - $db->manipulate($query); - } - /* - * PARSER - */ - - /** - * - * @param string $xml_file - * @return array - */ - private function getDataFromXML($xml_file) - { - $xml = simplexml_load_file($xml_file); - $raw_array = $this->xml2array($xml); - - return $raw_array; - } - - /** - * XML Parser - * @param SimpleXMLElement $xml - * @return array - */ - private function xml2array($xml) - { - $arr = array(); - foreach ($xml as $element) - { - $tag = $element->getName(); - $e = get_object_vars($element); - //Deployed seed bug fixing - if ($element->getName() == "deployedseed") - { - $arr[$tag][] = strip_tags((string)$element); - } else - { - if (!empty($e)) - { - if ($element instanceof SimpleXMLElement) - { - $elem_arr = $this->xml2array($element); - if (empty($elem_arr)) - { - $elem_arr['_content'] = (string)$element; - } - foreach ($element->attributes() as $name => $value) - { - $elem_arr['_attributes'][$name] = (string)$value; - } - $arr[$tag][] = $elem_arr; - } else - { - $arr[$tag][] = (string)$e; - } - } else - { - $arr[$tag] = (string)$element; - } - } - } - - return $arr; - } - - private function cleanXML($xml_data) - { - foreach ($xml_data as $array) - { - if (!empty($array)) - { - return $array; - } - } - } - - /* - * BUSTACK QuestionTION FUNCTIONS - */ - - /** - * Stablish the data in order to create an Standard Question - * @param array $data - */ - private function createStandardQuestion($data) - { - //Question id management. - if ($this->getQuestion()->getId() == $this->getFirstQuestion()) - { - //Nothing to do, first question - } else - { - $this->getQuestion()->setId(-1); - } - - if (!isset($data['name'][0]['text']) OR $data['name'][0]['text'] == '') - { - $this->error_log[] = $this->getPlugin()->txt('error_import_no_title'); - - return FALSE; - } - - if (!isset($data['questiontext'][0]['text']) OR $data['questiontext'][0]['text'] == '') - { - $this->error_log[] = $this->getPlugin()->txt('error_import_no_question_text') . ' ' . $data['name'][0]['text']; - - return FALSE; - } - - if (!isset($data['defaultgrade']) OR $data['defaultgrade'] == '') - { - $this->error_log[] = $this->getPlugin()->txt('error_import_no_points') . ' ' . $data['name'][0]['text']; - - return FALSE; - } - - $mapping = $this->getMediaObjectsFromXML($data['questiontext'][0]['file']); - $questiontext = $this->replaceMediaObjectReferences($data['questiontext'][0]['text'], $mapping); - - //Other parameters settings. - $this->getQuestion()->setTitle(strip_tags($data['name'][0]['text'])); - $this->getQuestion()->setQuestion(assStackQuestionUtils::_casTextConverter($questiontext, $this->getQuestion()->getTitle(), TRUE), $this->getQuestion()->getTitle(), true, $this->getRTETags()); - $this->getQuestion()->setPoints($data['defaultgrade']); - - //Save standard data. - $this->getQuestion()->saveQuestionDataToDb(); - } - - private function checkQuestionType($data) - { - $has_name = array_key_exists('name', $data); - $has_question_variables = array_key_exists('questionvariables', $data); - $has_inputs = array_key_exists('input', $data); - $has_prts = array_key_exists('prt', $data); - - if ($has_name AND $has_question_variables AND $has_inputs AND $has_prts) - { - return TRUE; - } else - { - ilUtil::sendInfo($this->cas_question->getPlugin()->txt('error_importing_question_malformed')); - - return FALSE; - } - } - - /** - * Get Options from XML - * NOTICE: - * * Formats are set always as 1 (1 means HTML) - * * Due to lack of inverse_trig parameteter in MoodleXML files inverse_trig is always set as cos-1. - * * SOLVED if field doesn't exist, set to cos-1 - * @param array $data - */ - private function getOptionsFromXML($data) - { - $this->getPlugin()->includeClass('model/ilias_object/class.assStackQuestionOptions.php'); - $question_options = new assStackQuestionOptions(-1, $this->getQuestion()->getId()); - - //Question Variables - if (isset($data['questionvariables'][0]['text'])) - { - $question_options->setQuestionVariables($data['questionvariables'][0]['text']); - } - - //Specific feedback - $mapping = $this->getMediaObjectsFromXML($data['specificfeedback'][0]['file']); - $specificfeedback = assStackQuestionUtils::_casTextConverter($this->replaceMediaObjectReferences($data['specificfeedback'][0]['text'], $mapping), $this->getQuestion()->getTitle(), TRUE); - $question_options->setSpecificFeedback(ilUtil::secureString($specificfeedback, true, $this->getRTETags())); - $question_options->setSpecificFeedbackFormat(1); - - //Question note: - $question_note = assStackQuestionUtils::_casTextConverter($data['questionnote'][0]['text'], $this->getQuestion()->getTitle(), TRUE); - $question_options->setQuestionNote($question_note); - - //Question simplify? Assume possitive? - $question_options->setQuestionSimplify((int)$data['questionsimplify']); - $question_options->setAssumePositive((int)$data['assumepositive']); - - //PRT Messages - $question_options->setPRTCorrectFormat(1); - $question_options->setPRTPartiallyCorrectFormat(1); - $question_options->setPRTIncorrectFormat(1); - - $mapping = $this->getMediaObjectsFromXML($data['prtcorrect'][0]['file']); - $prtcorrect = $this->replaceMediaObjectReferences($data['prtcorrect'][0]['text'], $mapping); - $question_options->setPRTCorrect(ilUtil::secureString($prtcorrect, true, $this->getRTETags())); - - $mapping = $this->getMediaObjectsFromXML($data['prtpartiallycorrect'][0]['file']); - $prtpartiallycorrect = $this->replaceMediaObjectReferences($data['prtpartiallycorrect'][0]['text'], $mapping); - $question_options->setPRTPartiallyCorrect(ilUtil::secureString($prtpartiallycorrect, true, $this->getRTETags())); - - $mapping = $this->getMediaObjectsFromXML($data['prtincorrect'][0]['file']); - $prtincorrect = $this->replaceMediaObjectReferences($data['prtincorrect'][0]['text'], $mapping); - $question_options->setPRTIncorrect(ilUtil::secureString($prtincorrect, true, $this->getRTETags())); - - //Multiplication, SQRT, Complex No, Variants seeds - $question_options->setMultiplicationSign(strip_tags($data['multiplicationsign'])); - $question_options->setSqrtSign(strip_tags($data['sqrtsign'])); - $question_options->setComplexNumbers(strip_tags($data['complexno'])); - $question_options->setInverseTrig(isset($data['inversetrig']) ? strip_tags($data['inversetrig']) : 'cos-1'); - $question_options->setMatrixParens(isset($data['matrixparens']) ? strip_tags($data['matrixparens']) : '['); - $question_options->setVariantsSelectionSeeds(strip_tags($data['variantsselectionseed'])); - - return $question_options; - } - - /** - * Get Inputs from XML and returns an array with them. - * NOTICE: - * * Options are setted as "" - * @param array $data - * @return \assStackQuestionInput - */ - private function getInputsFromXML($data) - { - $this->getPlugin()->includeClass('model/ilias_object/class.assStackQuestionInput.php'); - - $inputs = array(); - if (is_array($data)) - { - foreach ($data as $input) - { - - //Main attributes needed to create an InputOBJ - $input_name = strip_tags($input['name']); - $input_type = strip_tags($input['type']); - $input_teacher_answer = strip_tags($input['tans']); - $new_input = new assStackQuestionInput(-1, $this->getQuestion()->getId(), $input_name, $input_type, $input_teacher_answer); - - //Setting the rest of the attributes - $new_input->setBoxSize((int)$input['boxsize']); - $new_input->setStrictSyntax((int)$input['strictsyntax']); - $new_input->setInsertStars((int)$input['insertstars']); - $new_input->setSyntaxHint(strip_tags($input['syntaxhint'])); - $new_input->setForbidWords(strip_tags($input['forbidwords'])); - $new_input->setAllowWords(strip_tags($input['allowwords'])); - $new_input->setForbidFloat((int)$input['forbidfloat']); - $new_input->setRequireLowestTerms((int)$input['requirelowestterms']); - $new_input->setCheckAnswerType((int)$input['checkanswertype']); - $new_input->setMustVerify((int)$input['mustverify']); - $new_input->setShowValidation((int)$input['showvalidation']); - $new_input->setOptions(strip_tags($input['options'])); - - $inputs[$input_name] = $new_input; - } - } else - { - $this->error_log[] = $this->getPlugin()->txt('error_import_no_inputs') . ' ' . $this->getQuestion()->getTitle(); - - return FALSE; - } - - if (!is_array($inputs)) - { - $this->error_log[] = $this->getPlugin()->txt('error_import_no_inputs') . ' ' . $this->getQuestion()->getTitle(); - - return FALSE; - } - - //array of assStackQuestionInputs - return $inputs; - } - - /** - * Get PRTs from XML and returns an array with them - * NOTICE: - * * This method calls getPRTNodesFromXML - * * prt_nodes[first] should be unset after prt->first_node is set. - * @param array $data - * @return \assStackQuestionPRT - */ - private function getPRTsFromXML($data) - { - $this->getPlugin()->includeClass('model/ilias_object/class.assStackQuestionPRT.php'); - $prts = array(); - - if (is_array($data)) - { - foreach ($data as $prt) - { - //Creation of the PRT - $new_prt = new assStackQuestionPRT(-1, $this->getQuestion()->getId()); - $prt_name = strip_tags($prt['name']); - $new_prt->setPRTName($prt_name); - $new_prt->setPRTValue(strip_tags($prt['value'])); - $new_prt->setAutoSimplify(strip_tags($prt['autosimplify'])); - $new_prt->setPRTFeedbackVariables($prt['feedbackvariables'][0]['text']); - - //Creation of Nodes - $prt_nodes = $this->getPRTNodesFromXML($prt['node'], $new_prt->getPRTName()); - - //Set the first node and later unset from array - $new_prt->setFirstNodeName($prt_nodes['first']); - - unset($prt_nodes['first']); - $new_prt->setPRTNodes($prt_nodes); - - $prts[] = $new_prt; - } - - } else - { - $this->error_log[] = $this->getPlugin()->txt('error_import_no_prt') . ' ' . $this->getQuestion()->getTitle(); - - return FALSE; - } - - if (!is_array($prts)) - { - $this->error_log[] = $this->getPlugin()->txt('error_import_no_prt') . ' ' . $this->getQuestion()->getTitle(); - - return FALSE; - } - - //array of assStackQuestionPRT - return $prts; - } - - /** - * Get PRTNodes from XML and returns an array with them and also with the first node of the PRT - * NOTICE: - * * Feedback format is set as 1 (Possible error in STACK because in description of DB - * * this field will be used for store the format of the feedback but is an int) - * @param array $data - * @param string $prt_name - * @return \assStackQuestionPRTNode - */ - private function getPRTNodesFromXML($data, $prt_name) - { - $this->getPlugin()->includeClass('model/ilias_object/class.assStackQuestionPRTNode.php'); - $prt_nodes = array(); - - //First node var - $is_first_node = true; - foreach ($data as $prt_node) - { - //Main attributes for creating the PRTNode OBJ - $node_name = strip_tags($prt_node['name']); - - $true_next_node = strip_tags($prt_node['truenextnode']); - $false_next_node = strip_tags($prt_node['falsenextnode']); - $new_node = new assStackQuestionPRTNode(-1, $this->getQuestion()->getId(), $prt_name, $node_name, $true_next_node, $false_next_node); - - //Setting Answers - $new_node->setAnswerTest(strip_tags($prt_node['answertest'])); - $new_node->setStudentAnswer($prt_node['sans']); - $new_node->setTeacherAnswer($prt_node['tans']); - - //Other options - $new_node->setTestOptions($prt_node['testoptions']); - $new_node->setQuiet((int)$prt_node['quiet']); - - //True child - $new_node->setTrueScoreMode(strip_tags($prt_node['truescoremode'])); - $new_node->setTrueScore(strip_tags($prt_node['truescore'])); - $new_node->setTruePenalty(strip_tags($prt_node['truepenalty'])); - $new_node->setTrueAnswerNote($prt_node['trueanswernote']); - if (isset($prt_node['truefeedbackformat'])) - { - $new_node->setTrueFeedbackFormat($prt_node['truefeedbackformat']); - } else - { - $new_node->setTrueFeedbackFormat(1); - } - - $mapping = $this->getMediaObjectsFromXML($prt_node['truefeedback'][0]['file']); - $truefeedback = assStackQuestionUtils::_casTextConverter($this->replaceMediaObjectReferences($prt_node['truefeedback'][0]['text'], $mapping), $this->getQuestion()->getTitle(), TRUE); - $new_node->setTrueFeedback(ilUtil::secureString($truefeedback, true, $this->getRTETags())); - - //False child - $new_node->setFalseScoreMode(strip_tags($prt_node['falsescoremode'])); - $new_node->setFalseScore(strip_tags($prt_node['falsescore'])); - $new_node->setFalsePenalty(strip_tags($prt_node['falsepenalty'])); - $new_node->setFalseAnswerNote($prt_node['falseanswernote']); - if (isset($prt_node['falsefeedbackformat'])) - { - $new_node->setFalseFeedbackFormat($prt_node['falsefeedbackformat']); - } else - { - $new_node->setFalseFeedbackFormat(1); - } - - $mapping = $this->getMediaObjectsFromXML($prt_node['falsefeedback'][0]['file']); - $falsefeedback = assStackQuestionUtils::_casTextConverter($this->replaceMediaObjectReferences($prt_node['falsefeedback'][0]['text'], $mapping), $this->getQuestion()->getTitle(), TRUE); - $new_node->setFalseFeedback(ilUtil::secureString($falsefeedback, true, $this->getRTETags())); - - if ($is_first_node) - { - $prt_nodes['first'] = $new_node->getNodeName(); - $is_first_node = false; - } - - $prt_nodes[] = $new_node; - } - - //array of assStackQuestionPRTNode - return $prt_nodes; - } - - private function getTestsFromXML($data) - { - $this->getPlugin()->includeClass('model/ilias_object/test/class.assStackQuestionTest.php'); - $tests = array(); - - foreach ($data as $test) - { - //Main attributes needed to create an TestOBJ - $test_case = (int)$test['testcase']; - $new_test = new assStackQuestionTest(-1, $this->getQuestion()->getId(), $test_case); - - //Creation of inputs - $test_inputs = $this->getTestInputsFromXML($test['testinput'], $this->getQuestion()->getId(), $test_case); - $new_test->setTestInputs($test_inputs); - - //Creation of expected results - $test_expected = $this->getTestExpectedFromXML($test['expected'], $this->getQuestion()->getId(), $test_case); - $new_test->setTestExpected($test_expected); - - $tests[] = $new_test; - } - - //array of assStackQuestionTest - return $tests; - } - - private function getTestInputsFromXML($data, $question_id, $test_case) - { - $this->getPlugin()->includeClass('model/ilias_object/test/class.assStackQuestionTestInput.php'); - $test_inputs = array(); - - foreach ($data as $input) - { - $new_test_input = new assStackQuestionTestInput(-1, $this->getQuestion()->getId(), $test_case); - - $new_test_input->setTestInputName($input['name']); - $new_test_input->setTestInputValue($input['value']); - - $test_inputs[] = $new_test_input; - } - - //array of assStackQuestionTestInput - return $test_inputs; - } - - private function getTestExpectedFromXML($data, $question_id, $test_case) - { - $this->getPlugin()->includeClass('model/ilias_object/test/class.assStackQuestionTestExpected.php'); - $test_expected = array(); - - foreach ($data as $expected) - { - //Getting the PRT name - $prt_name = strip_tags($expected['name']); - $new_test_expected = new assStackQuestionTestExpected(-1, $this->getQuestion()->getId(), $test_case, $prt_name); - - $new_test_expected->setExpectedScore(strip_tags($expected['expectedscore'])); - $new_test_expected->setExpectedPenalty(strip_tags($expected['expectedpenalty'])); - $new_test_expected->setExpectedAnswerNote($expected['expectedanswernote']); - - $test_expected[] = $new_test_expected; - } - - //array of assStackQuestionTestExpected - return $test_expected; - } - - private function getDeployedSeedsFromXML($data) - { - $this->getPlugin()->includeClass('model/ilias_object/class.assStackQuestionDeployedSeed.php'); - $deployed_seeds = array(); - - foreach ($data as $deployed_seed_string) - { - $deployed_seed = new assStackQuestionDeployedSeed(-1, $this->getQuestion()->getId(), (int)$deployed_seed_string); - $deployed_seeds[] = $deployed_seed; - } - - //array of assStackQuestionDeployedSeed - return $deployed_seeds; - } - - private function getExtraInfoFromXML($data) - { - $this->getPlugin()->includeClass('model/ilias_object/class.assStackQuestionExtraInfo.php'); - $extra_info = new assStackQuestionExtraInfo(-1, $this->getQuestion()->getId()); - - //General feedback property - $mapping = $this->getMediaObjectsFromXML($data['generalfeedback'][0]['file']); - $how_to_solve = assStackQuestionUtils::_casTextConverter($this->replaceMediaObjectReferences($data['generalfeedback'][0]['text'], $mapping), $this->getQuestion()->getTitle(), TRUE); - $extra_info->setHowToSolve(ilUtil::secureString($how_to_solve, true, $this->getRTETags())); - //Penalty property - $penalty = $data['penalty']; - $extra_info->setPenalty($penalty); - //Hidden property - $hidden = $data['hidden']; - $extra_info->setHidden($hidden); - - //assStackQuestionExtraInfo - return $extra_info; - } - - /** - * Create media objects from array converted file elements - * @param array $data [['_attributes' => ['name' => string, 'path' => string], '_content' => string], ...] - * @return array filename => object_id - */ - private function getMediaObjectsFromXML($data = array()) - { - $mapping = array(); - foreach ((array)$data as $file) - { - $name = $file['_attributes']['name']; - $path = $file['_attributes']['path']; - $src = $file['_content']; - - $temp = ilUtil::ilTempnam(); - file_put_contents($temp, base64_decode($src)); - $media_object = ilObjMediaObject::_saveTempFileAsMediaObject($name, $temp, false); - @unlink($temp); - - $this->media_objects[$media_object->getId()] = $media_object; - $mapping[$name] = $media_object->getId(); - } - - return $mapping; - } - - /** - * Replace references to media objects in a text - * @param string text from moodleXML with local references - * @param array mapping of filenames to media object IDs - * @return string text with paths to media objects - */ - private function replaceMediaObjectReferences($text = "", $mapping = array()) - { - foreach ($mapping as $name => $id) - { - $text = str_replace('src="@@PLUGINFILE@@/' . $name, 'src="' . ILIAS_HTTP_PATH . '/data/' . CLIENT_ID . '/mobs/mm_' . $id . "/" . $name . '"', $text); - } - - return $text; - } - - /** - * Clear the list of media objects - * This should be called for every new question import - */ - private function clearMediaObjects() - { - $this->media_objects = array(); - } - - /** - * Save the usages of media objects in a question - * @param integer $question_id - */ - private function saveMediaObjectUsages($question_id) - { - foreach ($this->media_objects as $id => $media_object) - { - ilObjMediaObject::_saveUsage($media_object->getId(), "qpl:html", $question_id); - } - $this->media_objects = array(); - } - - /** - * Purge the media objects colleted for a not imported question - */ - private function purgeMediaObjects() - { - foreach ($this->media_objects as $id => $media_object) - { - $media_object->delete(); - } - $this->media_objects = array(); - } - - - /** - * Check if the question has all data needed to work properly - * In this method is done the check for new syntax in CASText from STACK 4.0 - * @return boolean if question has been properly created - */ - public function checkQuestion(assStackQuestion $question) - { - //Step 1: Check if there is one option object and at least one input, one prt with at least one node; - if (!is_a($question->getOptions(), 'assStackQuestionOptions')) - { - return false; - } - if (is_array($question->getInputs())) - { - foreach ($question->getInputs() as $input) - { - if (!is_a($input, 'assStackQuestionInput')) - { - return false; - } - } - } else - { - return false; - } - if (is_array($question->getPotentialResponsesTrees())) - { - foreach ($question->getPotentialResponsesTrees() as $prt) - { - if (!is_a($prt, 'assStackQuestionPRT')) - { - return false; - } else - { - foreach ($prt->getPRTNodes() as $node) - { - if (!is_a($node, 'assStackQuestionPRTNode')) - { - return false; - } - } - } - } - } else - { - return false; - } - - //Step 2: Check options - $options_are_ok = $question->getOptions()->checkOptions(TRUE); - - //Step 3: Check inputs - foreach ($question->getInputs() as $input) - { - $inputs_are_ok = $input->checkInput(TRUE); - if ($inputs_are_ok == FALSE) - { - break; - } - } - - //Step 4A: Check PRT - if (is_array($question->getPotentialResponsesTrees())) - { - foreach ($question->getPotentialResponsesTrees() as $PRT) - { - $PRTs_are_ok = $PRT->checkPRT(TRUE); - if ($PRTs_are_ok == FALSE) - { - break; - } else - { - //Step 4B: Check Nodes - if (is_array($PRT->getPRTNodes())) - { - foreach ($PRT->getPRTNodes() as $node) - { - $Nodes_are_ok = $node->checkPRTNode(TRUE); - if ($Nodes_are_ok == FALSE) - { - break; - } - } - } - //Step 4C: Check if nodes make a PRT - } - } - } - - //Step 5: Check tests - if (!empty($question->getTests())) - { - foreach ($question->getTests() as $test) - { - if (!is_a($test, 'assStackQuestionTest')) - { - return false; - } else - { - $tests_creation_is_ok = $test->checkTest(TRUE); - //Step 5B: Check inputs - foreach ($test->getTestInputs() as $input) - { - $test_inputs_are_ok = $input->checkTestInput(TRUE); - if ($test_inputs_are_ok == FALSE) - { - break; - } - } - //Step 5C: Check expected - foreach ($test->getTestExpected() as $expected) - { - $test_expected_are_ok = $expected->checkTestExpected(TRUE); - if ($test_expected_are_ok == FALSE) - { - break; - } - } - if ($tests_creation_is_ok AND $test_inputs_are_ok AND $test_expected_are_ok) - { - $test_are_ok = TRUE; - } else - { - $test_are_ok = FALSE; - } - } - } - } else - { - $test_are_ok = TRUE; - } - - if ($options_are_ok AND $inputs_are_ok AND $PRTs_are_ok AND $Nodes_are_ok AND $test_are_ok) - { - return true; - } else - { - return false; - } - } - - /* - * GETTERS AND SETTERS - */ - - /** - * @param \ilassStackQuestionPlugin $plugin - */ - public function setPlugin($plugin) - { - $this->plugin = $plugin; - } - - /** - * @return \ilassStackQuestionPlugin - */ - public function getPlugin() - { - return $this->plugin; - } - - /** - * @param \assStackQuestion $question - */ - public function setQuestion($question) - { - $this->question = $question; - } - - /** - * @return \assStackQuestion - */ - public function getQuestion() - { - return $this->question; - } - - /** - * @param int $first_question - */ - public function setFirstQuestion($first_question) - { - $this->first_question = $first_question; - } - - /** - * @return int - */ - public function getFirstQuestion() - { - return $this->first_question; - } - - /** - * @return string allowed html tags, e.g. "..." - */ - public function setRTETags($tags) - { - $this->rte_tags = $tags; - } - - /** - * @return string allowed html tags, e.g. "..." - */ - public function getRTETags() - { - return $this->rte_tags; - } - - public function php72Format($raw_data) - { - $full_data = array(); - - foreach ($raw_data as $question_data) - { - $data = array(); - //Check for not category - if (is_array($question_data['category'])) - { - continue; - } - - //Question Name - $data['name'][0]['text'] = $question_data['name'][0]['text'][0]["_content"]; - - //Question text - $data['questiontext'][0]['text'] = $question_data['questiontext'][0]['text']; - - //General feedback - $data['generalfeedback'][0]['text'] = $question_data['generalfeedback'][0]['text']; - - //default grade - $data['defaultgrade'] = $question_data['defaultgrade'][0]["_content"]; - - //penalty - $data['penalty'] = $question_data['penalty'][0]["_content"]; - - //hidden - if (isset($question_data['hidden'][0]["_content"])) - { - $data['hidden'] = $question_data['hidden'][0]["_content"]; - } else - { - $data['hidden'] = ""; - } - - //stackversion - if (isset($question_data['stackversion'][0]["_content"])) - { - $data['stackversion'][0]['text'] = $question_data['stackversion'][0]['text']; - } else - { - $data['stackversion'][0]['text'] = ""; - } - - //questionvariables 2 versions to solve problems with question variables tarting with comments - if (isset($question_data['questionvariables'][0]['text'][0]['_content'])) - { - $data['questionvariables'][0]['text'] = $question_data['questionvariables'][0]['text'][0]['_content']; - } elseif (isset($question_data['questionvariables'][0]['text']) AND is_string($question_data['questionvariables'][0]['text'])) - { - $data['questionvariables'][0]['text'] = $question_data['questionvariables'][0]['text']; - } else - { - $data['questionvariables'][0]['text'] = ""; - } - - //specificfeedback: - if (isset($question_data['specificfeedback'][0]['text'][0]['_content'])) - { - $data['specificfeedback'][0]['text'] = $question_data['specificfeedback'][0]['text'][0]['_content']; - } elseif (isset($question_data['specificfeedback'][0]['text']) AND is_string($question_data['specificfeedback'][0]['text'])) - { - $data['specificfeedback'][0]['text'] = $question_data['specificfeedback'][0]['text']; - } else - { - $data['specificfeedback'][0]['text'] = ""; - } - - //questionnote - if (isset($question_data['questionnote'][0]['text'][0]['_content'])) - { - $data['questionnote'][0]['text'] = $question_data['questionnote'][0]['text'][0]['_content']; - } elseif (isset($question_data['questionnote'][0]['text']) AND is_string($question_data['questionnote'][0]['text'])) - { - $data['questionnote'][0]['text'] = $question_data['questionnote'][0]['text']; - }else - { - $data['questionnote'][0]['text'] = ""; - } - - //questionsimplify - if (isset($question_data['questionsimplify'][0]["_content"])) - { - $data['questionsimplify'] = $question_data['questionsimplify'][0]["_content"]; - } else - { - $data['questionsimplify'] = ""; - } - - //assumepositive - if (isset($question_data['assumepositive'][0]["_content"])) - { - $data['assumepositive'] = $question_data['assumepositive'][0]["_content"]; - } else - { - $data['assumepositive'] = ""; - } - - //assumereal - if (isset($question_data['assumereal'][0]["_content"])) - { - $data['assumereal'] = $question_data['assumereal'][0]["_content"]; - } else - { - $data['assumereal'] = ""; - } - - //prtcorrect - if (isset($question_data['prtcorrect'][0]["_content"])) - { - $data['prtcorrect'][0]['text'] = $question_data['prtcorrect'][0]['text']; - } else - { - $data['prtcorrect'][0]['text'] = ""; - } - - //prtpartiallycorrect - if (isset($question_data['prtpartiallycorrect'][0]["_content"])) - { - $data['prtpartiallycorrect'][0]['text'] = $question_data['prtpartiallycorrect'][0]['text']; - } else - { - $data['prtpartiallycorrect'][0]['text'] = ""; - } - - //prtincorrect - if (isset($question_data['prtincorrect'][0]["_content"])) - { - $data['prtincorrect'][0]['text'] = $question_data['prtincorrect'][0]['text']; - } else - { - $data['prtincorrect'][0]['text'] = ""; - } - - //multiplicationsign - if (isset($question_data['multiplicationsign'][0]["_content"])) - { - $data['multiplicationsign'] = $question_data['multiplicationsign'][0]["_content"]; - } else - { - $data['multiplicationsign'] = ""; - } - - //sqrtsign - if (isset($question_data['sqrtsign'][0]["_content"])) - { - $data['sqrtsign'] = $question_data['sqrtsign'][0]["_content"]; - } else - { - $data['sqrtsign'] = ""; - } - - //complexno - if (isset($question_data['complexno'][0]["_content"])) - { - $data['complexno'] = $question_data['complexno'][0]["_content"]; - } else - { - $data['complexno'] = ""; - } - - //inversetrig - if (isset($question_data['inversetrig'][0]["_content"])) - { - $data['inversetrig'] = $question_data['inversetrig'][0]["_content"]; - } else - { - $data['inversetrig'] = ""; - } - - //matrixparens - if (isset($question_data['matrixparens'][0]["_content"])) - { - $data['matrixparens'] = $question_data['matrixparens'][0]["_content"]; - } else - { - $data['matrixparens'] = ""; - } - - //variantsselectionseed - if (isset($question_data['variantsselectionseed'])) - { - $data['variantsselectionseed'] = $question_data['variantsselectionseed']; - } else - { - $data['variantsselectionseed'] = ""; - } - - //Inputs - if (is_array($question_data['input'])) - { - foreach ($question_data['input'] as $input_raw) - { - $input_data = array(); - - //name - if (isset($input_raw['name'][0]["_content"])) - { - $input_data['name'] = $input_raw['name'][0]["_content"]; - } else - { - $input_data['name'] = ""; - } - - //type - if (isset($input_raw['type'][0]["_content"])) - { - $input_data['type'] = $input_raw['type'][0]["_content"]; - } else - { - $input_data['type'] = ""; - } - - //tans - if (isset($input_raw['tans'][0]["_content"])) - { - $input_data['tans'] = $input_raw['tans'][0]["_content"]; - } else - { - $input_data['tans'] = ""; - } - - //boxsize - if (isset($input_raw['boxsize'][0]["_content"])) - { - $input_data['boxsize'] = $input_raw['boxsize'][0]["_content"]; - } else - { - $input_data['boxsize'] = ""; - } - - //strictsyntax - if (isset($input_raw['strictsyntax'][0]["_content"])) - { - $input_data['strictsyntax'] = $input_raw['strictsyntax'][0]["_content"]; - } else - { - $input_data['strictsyntax'] = ""; - } - - //insertstars - if (isset($input_raw['insertstars'][0]["_content"])) - { - $input_data['insertstars'] = $input_raw['insertstars'][0]["_content"]; - } else - { - $input_data['insertstars'] = ""; - } - - //syntaxhint - if (isset($input_raw['syntaxhint'][0]["_content"])) - { - $input_data['syntaxhint'] = $input_raw['syntaxhint'][0]["_content"]; - } else - { - $input_data['syntaxhint'] = ""; - } - - //syntaxattribute - if (isset($input_raw['syntaxattribute'][0]["_content"])) - { - $input_data['syntaxattribute'] = $input_raw['syntaxattribute'][0]["_content"]; - } else - { - $input_data['syntaxattribute'] = ""; - } - - //forbidwords - if (isset($input_raw['forbidwords'][0]["_content"])) - { - $input_data['forbidwords'] = $input_raw['forbidwords'][0]["_content"]; - } else - { - $input_data['forbidwords'] = ""; - } - - //allowwords - if (isset($input_raw['allowwords'][0]["_content"])) - { - $input_data['allowwords'] = $input_raw['allowwords'][0]["_content"]; - } else - { - $input_data['allowwords'] = ""; - } - - //forbidfloat - if (isset($input_raw['forbidfloat'][0]["_content"])) - { - $input_data['forbidfloat'] = $input_raw['forbidfloat'][0]["_content"]; - } else - { - $input_data['forbidfloat'] = ""; - } - - //requirelowestterms - if (isset($input_raw['requirelowestterms'][0]["_content"])) - { - $input_data['requirelowestterms'] = $input_raw['requirelowestterms'][0]["_content"]; - } else - { - $input_data['requirelowestterms'] = ""; - } - - //checkanswertype - if (isset($input_raw['checkanswertype'][0]["_content"])) - { - $input_data['checkanswertype'] = $input_raw['checkanswertype'][0]["_content"]; - } else - { - $input_data['checkanswertype'] = ""; - } - - //mustverify - if (isset($input_raw['mustverify'][0]["_content"])) - { - $input_data['mustverify'] = $input_raw['mustverify'][0]["_content"]; - } else - { - $input_data['mustverify'] = ""; - } - - //showvalidation - if (isset($input_raw['showvalidation'][0]["_content"])) - { - $input_data['showvalidation'] = $input_raw['showvalidation'][0]["_content"]; - } else - { - $input_data['showvalidation'] = ""; - } - - //options - if (isset($input_raw['options'][0]["_content"])) - { - $input_data['options'] = $input_raw['options'][0]["_content"]; - } else - { - $input_data['options'] = ""; - } - - //Add to question - $data['input'][] = $input_data; - } - } - - //PRT - if (is_array($question_data['prt'])) - { - foreach ($question_data['prt'] as $prt_raw) - { - $prt_data = array(); - - //name - if (isset($prt_raw['name'][0]["_content"])) - { - $prt_data['name'] = $prt_raw['name'][0]["_content"]; - } else - { - $prt_data['name'] = ""; - } - - //value - if (isset($prt_raw['value'][0]["_content"])) - { - $prt_data['value'] = $prt_raw['value'][0]["_content"]; - } else - { - $prt_data['value'] = ""; - } - - //autosimplify - if (isset($prt_raw['autosimplify'][0]["_content"])) - { - $prt_data['autosimplify'] = $prt_raw['autosimplify'][0]["_content"]; - } else - { - $prt_data['autosimplify'] = ""; - } - - //feedbackvariables - if (isset($prt_raw['feedbackvariables'][0]["text"])) - { - $prt_data['feedbackvariables'][0]["text"] = $prt_raw['feedbackvariables'][0]["text"]; - } else - { - $prt_data['feedbackvariables'][0]["text"] = ""; - } - - //Nodes - if (is_array($prt_raw['node'])) - { - foreach ($prt_raw['node'] as $node_raw) - { - $node_data = array(); - - //name - if (isset($node_raw['name'][0]["_content"])) - { - $node_data['name'] = $node_raw['name'][0]["_content"]; - } else - { - $node_data['name'] = ""; - } - - //answertest - if (isset($node_raw['answertest'][0]["_content"])) - { - $node_data['answertest'] = $node_raw['answertest'][0]["_content"]; - } else - { - $node_data['answertest'] = ""; - } - - //sans - if (isset($node_raw['sans'][0]["_content"])) - { - $node_data['sans'] = $node_raw['sans'][0]["_content"]; - } else - { - $node_data['sans'] = ""; - } - - //tans - if (isset($node_raw['tans'][0]["_content"])) - { - $node_data['tans'] = $node_raw['tans'][0]["_content"]; - } else - { - $node_data['tans'] = ""; - } - - //testoptions - if (isset($node_raw['testoptions'][0]["_content"])) - { - $node_data['testoptions'] = $node_raw['testoptions'][0]["_content"]; - } else - { - $node_data['testoptions'] = ""; - } - - //quiet - if (isset($node_raw['quiet'][0]["_content"])) - { - $node_data['quiet'] = $node_raw['quiet'][0]["_content"]; - } else - { - $node_data['quiet'] = ""; - } - - //truescoremode - if (isset($node_raw['truescoremode'][0]["_content"])) - { - $node_data['truescoremode'] = $node_raw['truescoremode'][0]["_content"]; - } else - { - $node_data['truescoremode'] = ""; - } - - //truescore - if (isset($node_raw['truescore'][0]["_content"])) - { - $node_data['truescore'] = $node_raw['truescore'][0]["_content"]; - } else - { - $node_data['truescore'] = ""; - } - - //truepenalty - if (isset($node_raw['truepenalty'][0]["_content"])) - { - $node_data['truepenalty'] = $node_raw['truepenalty'][0]["_content"]; - } else - { - $node_data['truepenalty'] = ""; - } - - //truenextnode - if (isset($node_raw['truenextnode'][0]["_content"])) - { - $node_data['truenextnode'] = $node_raw['truenextnode'][0]["_content"]; - } else - { - $node_data['truenextnode'] = ""; - } - - //trueanswernote - if (isset($node_raw['trueanswernote'][0]["_content"])) - { - $node_data['trueanswernote'] = $node_raw['trueanswernote'][0]["_content"]; - } else - { - $node_data['trueanswernote'] = ""; - } - - //truefeedback - if (isset($node_raw['truefeedback'][0]["text"][0]["_content"])) - { - $node_data['truefeedback'][0]["text"] = $node_raw['truefeedback'][0]["text"][0]["_content"]; - } else - { - $node_data['truefeedback'][0]["text"] = ""; - } - - //falsescoremode - if (isset($node_raw['falsescoremode'][0]["_content"])) - { - $node_data['falsescoremode'] = $node_raw['falsescoremode'][0]["_content"]; - } else - { - $node_data['falsescoremode'] = ""; - } - - //falsescore - if (isset($node_raw['falsescore'][0]["_content"])) - { - $node_data['falsescore'] = $node_raw['falsescore'][0]["_content"]; - } else - { - $node_data['falsescore'] = ""; - } - - //falsepenalty - if (isset($node_raw['falsepenalty'][0]["_content"])) - { - $node_data['falsepenalty'] = $node_raw['falsepenalty'][0]["_content"]; - } else - { - $node_data['falsepenalty'] = ""; - } - - //falsenextnode - if (isset($node_raw['falsenextnode'][0]["_content"])) - { - $node_data['falsenextnode'] = $node_raw['falsenextnode'][0]["_content"]; - } else - { - $node_data['falsenextnode'] = ""; - } - - //falseanswernote - if (isset($node_raw['falseanswernote'][0]["_content"])) - { - $node_data['falseanswernote'] = $node_raw['falseanswernote'][0]["_content"]; - } else - { - $node_data['falseanswernote'] = ""; - } - - //falsefeedback - if (isset($node_raw['falsefeedback'][0]["text"][0]["_content"])) - { - $node_data['falsefeedback'][0]["text"] = $node_raw['falsefeedback'][0]["text"][0]["_content"]; - } else - { - $node_data['falsefeedback'][0]["text"] = ""; - } - - //Add to prt - $prt_data['node'][] = $node_data; - } - } - - //Add to question - $data['prt'][] = $prt_data; - - //qtest - if (is_array($question_data['qtest'])) - { - foreach ($question_data['qtest'] as $qtest_raw) - { - $qtest_data = array(); - - //testcase - if (isset($qtest_raw['testcase'][0]["_content"])) - { - $qtest_data['testcase'] = $qtest_raw['testcase'][0]["_content"]; - } else - { - $qtest_data['testcase'] = ""; - } - - //testinput - if (isset($qtest_raw['testinput'][0]['name'][0]["_content"]) AND isset($qtest_raw['testinput'][0]['value'][0]["_content"])) - { - $qtest_data['testinput'][0]['name'] = $qtest_raw['testinput'][0]['name'][0]["_content"]; - $qtest_data['testinput'][0]['value'] = $qtest_raw['testinput'][0]['value'][0]["_content"]; - } else - { - $qtest_data['testinput'][0]['name'] = ""; - $qtest_data['testinput'][0]['value'] = ""; - } - - //expected - if (isset($qtest_raw['expected'][0]['name'][0]["_content"]) AND isset($qtest_raw['expected'][0]['expectedscore'][0]["_content"]) AND isset($qtest_raw['expected'][0]['expectedanswernote'][0]["_content"])) - { - $qtest_data['expected'][0]['name'] = $qtest_raw['expected'][0]['name'][0]["_content"]; - $qtest_data['expected'][0]['expectedscore'] = $qtest_raw['expected'][0]['expectedscore'][0]["_content"]; - $qtest_data['expected'][0]['expectedpenalty'] = $qtest_raw['expected'][0]['expectedpenalty'][0]["_content"]; - $qtest_data['expected'][0]['expectedanswernote'] = $qtest_raw['expected'][0]['expectedanswernote'][0]["_content"]; - - } else - { - $qtest_data['expected'][0]['name'] = ""; - $qtest_data['expected'][0]['expectedscore'] = ""; - $qtest_data['expected'][0]['expectedpenalty'] = ""; - $qtest_data['expected'][0]['expectedanswernote'] = ""; - } - - - //Add to question - $data['qtest'][] = $qtest_data; - } - } - - } - } - - //Add to full data - $full_data['question'][] = $data; - - } - - return $full_data; - } + /** + * Plugin instance for language management + * @var ilassStackQuestionPlugin + */ + private $plugin; + + /** + * ILIAS version of the question + * The current question + * @var assStackQuestion + */ + private $question; + + /** + * Question_id for the first question to import + * (When only one question, use this as Question_Id) + * @var int When first question this var is higher than 0. + */ + private $first_question; + + private $error_log; + + /** + * @var string allowed html tags, e.g. "..." + */ + private $rte_tags = ""; + + + /** + * media objects created for an imported question + * This list will be cleared for every new question + * @var array id => object + */ + private $media_objects = array(); + + + /** + * Set all the parameters for this question, including the creation of + * the first assStackQuestion object. + * @param ilassStackQuestionPlugin $plugin + * @param $first_question_id int the question_id for the first question to import. + */ + function __construct($plugin, $first_question_id, $parent_obj) + { + //Set Plugin and first question id. + $this->setPlugin($plugin); + $this->setFirstQuestion($first_question_id); + + //Creation of the first question. + $this->getPlugin()->includeClass('class.assStackQuestion.php'); + $this->setQuestion($parent_obj); + + //Initialization and load of stack wrapper classes + $this->getPlugin()->includeClass('utils/class.assStackQuestionInitialization.php'); + } + + /** + * ### MAIN METHOD OF THIS CLASS ### + * This method is called from assStackQuestion to import the questions from an MoodleXML file. + * @param $xml_file string the MoodleXML file + * @return mixed Status of the import + */ + public function import($xml_file) + { + //Step 1: Get data from XML. + $raw_data = $this->getDataFromXML($xml_file); + //Step 2: Import questions. + $import_status = $this->importQuestions($raw_data); + + //Step 3: Return status. + return $import_status; + } + + public function importQuestions($raw_data) + { + $number_of_questions_created = 0; + //For each question in the array + + //Check if is PHP 7.2 in case it is, data need some extra formatting + if (assStackQuestionUtils::_isPhP72()) { + $raw_data = $this->php72Format($raw_data['question']); + } + + foreach ($raw_data['question'] as $data) { + // start with a new list of media objects for each question + $this->clearMediaObjects(); + + //Check for not category + if (is_array($data['category'])) { + continue; + } + + //Step 2.1: Create standard question + $ok = $this->createStandardQuestion($data); + if ($ok === FALSE) { + //Do not continue creating question + $this->purgeMediaObjects(); + continue; + } + + //Step 2.2: Get Options from data and set as Options OBJ in cas_question + $question_options = $this->getOptionsFromXML($data); + $this->getQuestion()->setOptions($question_options); + + //Step 2.3: Get Inputs from data and set as Input OBJ in cas_question + $ok = $question_inputs = $this->getInputsFromXML($data['input']); + $this->getQuestion()->setInputs($question_inputs); + if ($ok === FALSE) { + //Delete current question data + $this->getQuestion()->delete($this->getQuestion()->getId()); + $this->purgeMediaObjects(); + //Do not continue creating question + continue; + } + + //Step 2.4.A: Get PRT from data and set as PRT OBJ in cas_question + //Step 2.4.B: Get Nodes from each PRT and set as Node OBJ in each PRT. + $ok = $question_PRTs = $this->getPRTsFromXML($data['prt']); + $this->getQuestion()->setPotentialResponsesTrees($question_PRTs); + if ($ok === FALSE) { + //Delete current question data + $this->getQuestion()->delete($this->getQuestion()->getId()); + $this->purgeMediaObjects(); + //Do not continue creating question + continue; + } + + //Step 2.5.A: Get Test from from data and set as Test OBJ in cas_question + //Step 2.5.B: Get Test Inputs and Expected from data and set as TestInput/Expected OBJ in cas_question + if (isset($data['qtest'])) { + $question_tests = $this->getTestsFromXML($data['qtest']); + $this->getQuestion()->setTests($question_tests); + } else { + $this->getQuestion()->setTests(array()); + } + + //Step 2.6: Get deployed seeds + if (isset($data['deployedseed'])) { + $question_seeds = $this->getDeployedSeedsFromXML($data['deployedseed']); + $this->getQuestion()->setDeployedSeeds($question_seeds); + } else { + $this->getQuestion()->setDeployedSeeds(array()); + } + + //Step 2.7: Get extra fields + $extra_info = $this->getExtraInfoFromXML($data); + $this->getQuestion()->setExtraInfo($extra_info); + + //Step 2.8: Fix possible errors + $question_is_ok = $this->checkQuestion($this->getQuestion()); + + //Step 2.9: Insert into DB or delete if question is not OK + if ($question_is_ok) { + //Delete options from created question. + $this->deletePredefinedQuestionData($this->getQuestion()->getId()); + + //Save STACK Question data. + $this->getQuestion()->saveToDB($this->getQuestion()->getId(), TRUE); + $this->saveMediaObjectUsages($this->getQuestion()->getId()); + $number_of_questions_created++; + + //Set $question to a new question + $this->getQuestion()->setId(-1); + } else { + //Delete current question data + $this->getQuestion()->delete($this->getQuestion()->getId()); + $this->purgeMediaObjects(); + } + } + if (!empty($this->error_log)) { + ilUtil::sendFailure(implode('
', $this->error_log)); + } + + //Number of questions created info + if ($number_of_questions_created > 1) { + ilUtil::sendSuccess($number_of_questions_created . ' ' . $this->getPlugin()->txt('import_number_of_questions_created')); + } elseif ($number_of_questions_created) { + ilUtil::sendSuccess($number_of_questions_created . ' ' . $this->getPlugin()->txt('import_number_of_questions_created_1')); + } + } + + public function deletePredefinedQuestionData($question_id) + { + global $DIC; + $db = $DIC->database(); + + $query = 'DELETE FROM xqcas_options WHERE question_id = ' . $question_id; + $db->manipulate($query); + + $query = 'DELETE FROM xqcas_inputs WHERE question_id = ' . $question_id; + $db->manipulate($query); + } + /* + * PARSER + */ + + /** + * + * @param string $xml_file + * @return array + */ + private function getDataFromXML($xml_file) + { + $xml = simplexml_load_file($xml_file); + $raw_array = $this->xml2array($xml); + + return $raw_array; + } + + /** + * XML Parser + * @param SimpleXMLElement $xml + * @return array + */ + private function xml2array($xml) + { + $arr = array(); + foreach ($xml as $element) { + $tag = $element->getName(); + $e = get_object_vars($element); + //Deployed seed bug fixing + if ($element->getName() == "deployedseed") { + $arr[$tag][] = strip_tags((string)$element); + } else { + if (!empty($e)) { + if ($element instanceof SimpleXMLElement) { + $elem_arr = $this->xml2array($element); + if (empty($elem_arr)) { + $elem_arr['_content'] = (string)$element; + } + foreach ($element->attributes() as $name => $value) { + $elem_arr['_attributes'][$name] = (string)$value; + } + $arr[$tag][] = $elem_arr; + } else { + $arr[$tag][] = (string)$e; + } + } else { + $arr[$tag] = (string)$element; + } + } + } + + return $arr; + } + + private function cleanXML($xml_data) + { + foreach ($xml_data as $array) { + if (!empty($array)) { + return $array; + } + } + } + + /* + * BUSTACK QuestionTION FUNCTIONS + */ + + /** + * Stablish the data in order to create an Standard Question + * @param array $data + */ + private function createStandardQuestion($data) + { + //Question id management. + if ($this->getQuestion()->getId() == $this->getFirstQuestion()) { + //Nothing to do, first question + } else { + $this->getQuestion()->setId(-1); + } + + if (!isset($data['name'][0]['text']) OR $data['name'][0]['text'] == '') { + $this->error_log[] = $this->getPlugin()->txt('error_import_no_title'); + + return FALSE; + } + + if (!isset($data['questiontext'][0]['text']) OR $data['questiontext'][0]['text'] == '') { + $this->error_log[] = $this->getPlugin()->txt('error_import_no_question_text') . ' ' . $data['name'][0]['text']; + + return FALSE; + } + + if (!isset($data['defaultgrade']) OR $data['defaultgrade'] == '') { + $this->error_log[] = $this->getPlugin()->txt('error_import_no_points') . ' ' . $data['name'][0]['text']; + + return FALSE; + } + + $mapping = $this->getMediaObjectsFromXML($data['questiontext'][0]['file']); + $questiontext = $this->replaceMediaObjectReferences($data['questiontext'][0]['text'], $mapping); + + //Other parameters settings. + $this->getQuestion()->setTitle(strip_tags($data['name'][0]['text'])); + $this->getQuestion()->setQuestion(assStackQuestionUtils::_casTextConverter($questiontext, $this->getQuestion()->getTitle(), TRUE), $this->getQuestion()->getTitle(), true, $this->getRTETags()); + $this->getQuestion()->setPoints($data['defaultgrade']); + + //Save standard data. + $this->getQuestion()->saveQuestionDataToDb(); + } + + private function checkQuestionType($data) + { + $has_name = array_key_exists('name', $data); + $has_question_variables = array_key_exists('questionvariables', $data); + $has_inputs = array_key_exists('input', $data); + $has_prts = array_key_exists('prt', $data); + + if ($has_name AND $has_question_variables AND $has_inputs AND $has_prts) { + return TRUE; + } else { + ilUtil::sendInfo($this->cas_question->getPlugin()->txt('error_importing_question_malformed')); + + return FALSE; + } + } + + /** + * Get Options from XML + * NOTICE: + * * Formats are set always as 1 (1 means HTML) + * * Due to lack of inverse_trig parameteter in MoodleXML files inverse_trig is always set as cos-1. + * * SOLVED if field doesn't exist, set to cos-1 + * @param array $data + */ + private function getOptionsFromXML($data) + { + $this->getPlugin()->includeClass('model/ilias_object/class.assStackQuestionOptions.php'); + $question_options = new assStackQuestionOptions(-1, $this->getQuestion()->getId()); + + //Question Variables + if (isset($data['questionvariables'][0]['text'])) { + $question_options->setQuestionVariables($data['questionvariables'][0]['text']); + } + + //Specific feedback + $mapping = $this->getMediaObjectsFromXML($data['specificfeedback'][0]['file']); + $specificfeedback = assStackQuestionUtils::_casTextConverter($this->replaceMediaObjectReferences($data['specificfeedback'][0]['text'], $mapping), $this->getQuestion()->getTitle(), TRUE); + $question_options->setSpecificFeedback(ilUtil::secureString($specificfeedback, true, $this->getRTETags())); + $question_options->setSpecificFeedbackFormat(1); + + //Question note: + $question_note = assStackQuestionUtils::_casTextConverter($data['questionnote'][0]['text'], $this->getQuestion()->getTitle(), TRUE); + $question_options->setQuestionNote($question_note); + + //Question simplify? Assume possitive? + $question_options->setQuestionSimplify((int)$data['questionsimplify']); + $question_options->setAssumePositive((int)$data['assumepositive']); + + //PRT Messages + $question_options->setPRTCorrectFormat(1); + $question_options->setPRTPartiallyCorrectFormat(1); + $question_options->setPRTIncorrectFormat(1); + + $mapping = $this->getMediaObjectsFromXML($data['prtcorrect'][0]['file']); + $prtcorrect = $this->replaceMediaObjectReferences($data['prtcorrect'][0]['text'], $mapping); + $question_options->setPRTCorrect(ilUtil::secureString($prtcorrect, true, $this->getRTETags())); + + $mapping = $this->getMediaObjectsFromXML($data['prtpartiallycorrect'][0]['file']); + $prtpartiallycorrect = $this->replaceMediaObjectReferences($data['prtpartiallycorrect'][0]['text'], $mapping); + $question_options->setPRTPartiallyCorrect(ilUtil::secureString($prtpartiallycorrect, true, $this->getRTETags())); + + $mapping = $this->getMediaObjectsFromXML($data['prtincorrect'][0]['file']); + $prtincorrect = $this->replaceMediaObjectReferences($data['prtincorrect'][0]['text'], $mapping); + $question_options->setPRTIncorrect(ilUtil::secureString($prtincorrect, true, $this->getRTETags())); + + //Multiplication, SQRT, Complex No, Variants seeds + $question_options->setMultiplicationSign(strip_tags($data['multiplicationsign'])); + $question_options->setSqrtSign(strip_tags($data['sqrtsign'])); + $question_options->setComplexNumbers(strip_tags($data['complexno'])); + $question_options->setInverseTrig(isset($data['inversetrig']) ? strip_tags($data['inversetrig']) : 'cos-1'); + $question_options->setMatrixParens(isset($data['matrixparens']) ? strip_tags($data['matrixparens']) : '['); + $question_options->setVariantsSelectionSeeds(strip_tags($data['variantsselectionseed'])); + + return $question_options; + } + + /** + * Get Inputs from XML and returns an array with them. + * NOTICE: + * * Options are setted as "" + * @param array $data + * @return \assStackQuestionInput + */ + private function getInputsFromXML($data) + { + $this->getPlugin()->includeClass('model/ilias_object/class.assStackQuestionInput.php'); + + $inputs = array(); + if (is_array($data)) { + foreach ($data as $input) { + + //Main attributes needed to create an InputOBJ + $input_name = strip_tags($input['name']); + $input_type = strip_tags($input['type']); + $input_teacher_answer = strip_tags($input['tans']); + $new_input = new assStackQuestionInput(-1, $this->getQuestion()->getId(), $input_name, $input_type, $input_teacher_answer); + + //Setting the rest of the attributes + $new_input->setBoxSize((int)$input['boxsize']); + $new_input->setStrictSyntax((int)$input['strictsyntax']); + $new_input->setInsertStars((int)$input['insertstars']); + $new_input->setSyntaxHint(strip_tags($input['syntaxhint'])); + $new_input->setForbidWords(strip_tags($input['forbidwords'])); + $new_input->setAllowWords(strip_tags($input['allowwords'])); + $new_input->setForbidFloat((int)$input['forbidfloat']); + $new_input->setRequireLowestTerms((int)$input['requirelowestterms']); + $new_input->setCheckAnswerType((int)$input['checkanswertype']); + $new_input->setMustVerify((int)$input['mustverify']); + $new_input->setShowValidation((int)$input['showvalidation']); + $new_input->setOptions(strip_tags($input['options'])); + + $inputs[$input_name] = $new_input; + } + } + //Allow creation of questions without inputs + /*else { + $this->error_log[] = $this->getPlugin()->txt('error_import_no_inputs') . ' ' . $this->getQuestion()->getTitle(); + + return FALSE; + } + + if (!is_array($inputs)) { + $this->error_log[] = $this->getPlugin()->txt('error_import_no_inputs') . ' ' . $this->getQuestion()->getTitle(); + + return FALSE; + }*/ + + //array of assStackQuestionInputs + return $inputs; + } + + /** + * Get PRTs from XML and returns an array with them + * NOTICE: + * * This method calls getPRTNodesFromXML + * * prt_nodes[first] should be unset after prt->first_node is set. + * @param array $data + * @return \assStackQuestionPRT + */ + private function getPRTsFromXML($data) + { + $this->getPlugin()->includeClass('model/ilias_object/class.assStackQuestionPRT.php'); + $prts = array(); + + if (is_array($data)) { + foreach ($data as $prt) { + //Creation of the PRT + $new_prt = new assStackQuestionPRT(-1, $this->getQuestion()->getId()); + $prt_name = strip_tags($prt['name']); + $new_prt->setPRTName($prt_name); + $new_prt->setPRTValue(strip_tags($prt['value'])); + $new_prt->setAutoSimplify(strip_tags($prt['autosimplify'])); + $new_prt->setPRTFeedbackVariables($prt['feedbackvariables']); + + //Creation of Nodes + $prt_nodes = $this->getPRTNodesFromXML($prt['node'], $new_prt->getPRTName()); + + //Set the first node and later unset from array + $new_prt->setFirstNodeName($prt_nodes['first']); + + unset($prt_nodes['first']); + $new_prt->setPRTNodes($prt_nodes); + + $prts[] = $new_prt; + } + + } + //Allow creation of questions without prt + /*else { + $this->error_log[] = $this->getPlugin()->txt('error_import_no_prt') . ' ' . $this->getQuestion()->getTitle(); + + return FALSE; + } + + if (!is_array($prts)) { + $this->error_log[] = $this->getPlugin()->txt('error_import_no_prt') . ' ' . $this->getQuestion()->getTitle(); + + return FALSE; + }*/ + + //array of assStackQuestionPRT + return $prts; + } + + /** + * Get PRTNodes from XML and returns an array with them and also with the first node of the PRT + * NOTICE: + * * Feedback format is set as 1 (Possible error in STACK because in description of DB + * * this field will be used for store the format of the feedback but is an int) + * @param array $data + * @param string $prt_name + * @return \assStackQuestionPRTNode + */ + private function getPRTNodesFromXML($data, $prt_name) + { + $this->getPlugin()->includeClass('model/ilias_object/class.assStackQuestionPRTNode.php'); + $prt_nodes = array(); + + //First node var + $is_first_node = true; + foreach ($data as $prt_node) { + //Main attributes for creating the PRTNode OBJ + $node_name = strip_tags($prt_node['name']); + + $true_next_node = strip_tags($prt_node['truenextnode']); + $false_next_node = strip_tags($prt_node['falsenextnode']); + $new_node = new assStackQuestionPRTNode(-1, $this->getQuestion()->getId(), $prt_name, $node_name, $true_next_node, $false_next_node); + + //Setting Answers + $new_node->setAnswerTest(strip_tags($prt_node['answertest'])); + $new_node->setStudentAnswer($prt_node['sans']); + $new_node->setTeacherAnswer($prt_node['tans']); + + //Other options + $new_node->setTestOptions($prt_node['testoptions']); + $new_node->setQuiet((int)$prt_node['quiet']); + + //True child + $new_node->setTrueScoreMode(strip_tags($prt_node['truescoremode'])); + $new_node->setTrueScore(strip_tags($prt_node['truescore'])); + $new_node->setTruePenalty(strip_tags($prt_node['truepenalty'])); + $new_node->setTrueAnswerNote($prt_node['trueanswernote']); + if (isset($prt_node['truefeedbackformat'])) { + $new_node->setTrueFeedbackFormat($prt_node['truefeedbackformat']); + } else { + $new_node->setTrueFeedbackFormat(1); + } + + $mapping = $this->getMediaObjectsFromXML($prt_node['truefeedback'][0]['file']); + $truefeedback = assStackQuestionUtils::_casTextConverter($this->replaceMediaObjectReferences($prt_node['truefeedback'][0]['text'], $mapping), $this->getQuestion()->getTitle(), TRUE); + $new_node->setTrueFeedback(ilUtil::secureString($truefeedback, true, $this->getRTETags())); + + //False child + $new_node->setFalseScoreMode(strip_tags($prt_node['falsescoremode'])); + $new_node->setFalseScore(strip_tags($prt_node['falsescore'])); + $new_node->setFalsePenalty(strip_tags($prt_node['falsepenalty'])); + $new_node->setFalseAnswerNote($prt_node['falseanswernote']); + if (isset($prt_node['falsefeedbackformat'])) { + $new_node->setFalseFeedbackFormat($prt_node['falsefeedbackformat']); + } else { + $new_node->setFalseFeedbackFormat(1); + } + + $mapping = $this->getMediaObjectsFromXML($prt_node['falsefeedback'][0]['file']); + $falsefeedback = assStackQuestionUtils::_casTextConverter($this->replaceMediaObjectReferences($prt_node['falsefeedback'][0]['text'], $mapping), $this->getQuestion()->getTitle(), TRUE); + $new_node->setFalseFeedback(ilUtil::secureString($falsefeedback, true, $this->getRTETags())); + + if ($is_first_node) { + $prt_nodes['first'] = $new_node->getNodeName(); + $is_first_node = false; + } + + $prt_nodes[] = $new_node; + } + + //array of assStackQuestionPRTNode + return $prt_nodes; + } + + private function getTestsFromXML($data) + { + $this->getPlugin()->includeClass('model/ilias_object/test/class.assStackQuestionTest.php'); + $tests = array(); + + foreach ($data as $test) { + //Main attributes needed to create an TestOBJ + $test_case = (int)$test['testcase']; + $new_test = new assStackQuestionTest(-1, $this->getQuestion()->getId(), $test_case); + + //Creation of inputs + $test_inputs = $this->getTestInputsFromXML($test['testinput'], $this->getQuestion()->getId(), $test_case); + $new_test->setTestInputs($test_inputs); + + //Creation of expected results + $test_expected = $this->getTestExpectedFromXML($test['expected'], $this->getQuestion()->getId(), $test_case); + $new_test->setTestExpected($test_expected); + + $tests[] = $new_test; + } + + //array of assStackQuestionTest + return $tests; + } + + private function getTestInputsFromXML($data, $question_id, $test_case) + { + $this->getPlugin()->includeClass('model/ilias_object/test/class.assStackQuestionTestInput.php'); + $test_inputs = array(); + + foreach ($data as $input) { + $new_test_input = new assStackQuestionTestInput(-1, $this->getQuestion()->getId(), $test_case); + + $new_test_input->setTestInputName($input['name']); + $new_test_input->setTestInputValue($input['value']); + + $test_inputs[] = $new_test_input; + } + + //array of assStackQuestionTestInput + return $test_inputs; + } + + private function getTestExpectedFromXML($data, $question_id, $test_case) + { + $this->getPlugin()->includeClass('model/ilias_object/test/class.assStackQuestionTestExpected.php'); + $test_expected = array(); + + foreach ($data as $expected) { + //Getting the PRT name + $prt_name = strip_tags($expected['name']); + $new_test_expected = new assStackQuestionTestExpected(-1, $this->getQuestion()->getId(), $test_case, $prt_name); + + $new_test_expected->setExpectedScore(strip_tags($expected['expectedscore'])); + $new_test_expected->setExpectedPenalty(strip_tags($expected['expectedpenalty'])); + $new_test_expected->setExpectedAnswerNote($expected['expectedanswernote']); + + $test_expected[] = $new_test_expected; + } + + //array of assStackQuestionTestExpected + return $test_expected; + } + + private function getDeployedSeedsFromXML($data) + { + $this->getPlugin()->includeClass('model/ilias_object/class.assStackQuestionDeployedSeed.php'); + $deployed_seeds = array(); + + foreach ($data as $deployed_seed_string) { + $deployed_seed = new assStackQuestionDeployedSeed(-1, $this->getQuestion()->getId(), (int)$deployed_seed_string); + $deployed_seeds[] = $deployed_seed; + } + + //array of assStackQuestionDeployedSeed + return $deployed_seeds; + } + + private function getExtraInfoFromXML($data) + { + $this->getPlugin()->includeClass('model/ilias_object/class.assStackQuestionExtraInfo.php'); + $extra_info = new assStackQuestionExtraInfo(-1, $this->getQuestion()->getId()); + + //General feedback property + $mapping = $this->getMediaObjectsFromXML($data['generalfeedback'][0]['file']); + $how_to_solve = assStackQuestionUtils::_casTextConverter($this->replaceMediaObjectReferences($data['generalfeedback'][0]['text'], $mapping), $this->getQuestion()->getTitle(), TRUE); + $extra_info->setHowToSolve(ilUtil::secureString($how_to_solve, true, $this->getRTETags())); + //Penalty property + $penalty = $data['penalty']; + $extra_info->setPenalty($penalty); + //Hidden property + $hidden = $data['hidden']; + $extra_info->setHidden($hidden); + + //assStackQuestionExtraInfo + return $extra_info; + } + + /** + * Create media objects from array converted file elements + * @param array $data [['_attributes' => ['name' => string, 'path' => string], '_content' => string], ...] + * @return array filename => object_id + */ + private function getMediaObjectsFromXML($data = array()) + { + $mapping = array(); + foreach ((array)$data as $file) { + $name = $file['_attributes']['name']; + $path = $file['_attributes']['path']; + $src = $file['_content']; + + $temp = ilUtil::ilTempnam(); + file_put_contents($temp, base64_decode($src)); + $media_object = ilObjMediaObject::_saveTempFileAsMediaObject($name, $temp, false); + @unlink($temp); + + $this->media_objects[$media_object->getId()] = $media_object; + $mapping[$name] = $media_object->getId(); + } + + return $mapping; + } + + /** + * Replace references to media objects in a text + * @param string text from moodleXML with local references + * @param array mapping of filenames to media object IDs + * @return string text with paths to media objects + */ + private function replaceMediaObjectReferences($text = "", $mapping = array()) + { + foreach ($mapping as $name => $id) { + $text = str_replace('src="@@PLUGINFILE@@/' . $name, 'src="' . ILIAS_HTTP_PATH . '/data/' . CLIENT_ID . '/mobs/mm_' . $id . "/" . $name . '"', $text); + } + + return $text; + } + + /** + * Clear the list of media objects + * This should be called for every new question import + */ + private function clearMediaObjects() + { + $this->media_objects = array(); + } + + /** + * Save the usages of media objects in a question + * @param integer $question_id + */ + private function saveMediaObjectUsages($question_id) + { + foreach ($this->media_objects as $id => $media_object) { + ilObjMediaObject::_saveUsage($media_object->getId(), "qpl:html", $question_id); + } + $this->media_objects = array(); + } + + /** + * Purge the media objects colleted for a not imported question + */ + private function purgeMediaObjects() + { + foreach ($this->media_objects as $id => $media_object) { + $media_object->delete(); + } + $this->media_objects = array(); + } + + + /** + * Check if the question has all data needed to work properly + * In this method is done the check for new syntax in CASText from STACK 4.0 + * @return boolean if question has been properly created + */ + public function checkQuestion(assStackQuestion $question) + { + //Step 1: Check if there is one option object and at least one input, one prt with at least one node; + if (!is_a($question->getOptions(), 'assStackQuestionOptions')) { + return false; + } + if (is_array($question->getInputs())) { + foreach ($question->getInputs() as $input) { + if (!is_a($input, 'assStackQuestionInput')) { + return false; + } + } + } else { + return false; + } + if (is_array($question->getPotentialResponsesTrees())) { + foreach ($question->getPotentialResponsesTrees() as $prt) { + if (!is_a($prt, 'assStackQuestionPRT')) { + return false; + } else { + foreach ($prt->getPRTNodes() as $node) { + if (!is_a($node, 'assStackQuestionPRTNode')) { + return false; + } + } + } + } + } else { + return false; + } + + //Step 2: Check options + $options_are_ok = $question->getOptions()->checkOptions(TRUE); + + //Step 3: Check inputs + foreach ($question->getInputs() as $input) { + $inputs_are_ok = $input->checkInput(TRUE); + if ($inputs_are_ok == FALSE) { + break; + } + } + + //Step 4A: Check PRT + if (is_array($question->getPotentialResponsesTrees())) { + foreach ($question->getPotentialResponsesTrees() as $PRT) { + $PRTs_are_ok = $PRT->checkPRT(TRUE); + if ($PRTs_are_ok == FALSE) { + break; + } else { + //Step 4B: Check Nodes + if (is_array($PRT->getPRTNodes())) { + foreach ($PRT->getPRTNodes() as $node) { + $Nodes_are_ok = $node->checkPRTNode(TRUE); + if ($Nodes_are_ok == FALSE) { + break; + } + } + } + //Step 4C: Check if nodes make a PRT + } + } + } + + //Step 5: Check tests + if (!empty($question->getTests())) { + foreach ($question->getTests() as $test) { + if (!is_a($test, 'assStackQuestionTest')) { + return false; + } else { + $tests_creation_is_ok = $test->checkTest(TRUE); + //Step 5B: Check inputs + foreach ($test->getTestInputs() as $input) { + $test_inputs_are_ok = $input->checkTestInput(TRUE); + if ($test_inputs_are_ok == FALSE) { + break; + } + } + //Step 5C: Check expected + foreach ($test->getTestExpected() as $expected) { + $test_expected_are_ok = $expected->checkTestExpected(TRUE); + if ($test_expected_are_ok == FALSE) { + break; + } + } + if ($tests_creation_is_ok AND $test_inputs_are_ok AND $test_expected_are_ok) { + $test_are_ok = TRUE; + } else { + $test_are_ok = FALSE; + } + } + } + } else { + $test_are_ok = TRUE; + } + + if ($options_are_ok AND $inputs_are_ok AND $PRTs_are_ok AND $Nodes_are_ok AND $test_are_ok) { + return true; + } else { + return false; + } + } + + /* + * GETTERS AND SETTERS + */ + + /** + * @param \ilassStackQuestionPlugin $plugin + */ + public function setPlugin($plugin) + { + $this->plugin = $plugin; + } + + /** + * @return \ilassStackQuestionPlugin + */ + public function getPlugin() + { + return $this->plugin; + } + + /** + * @param \assStackQuestion $question + */ + public function setQuestion($question) + { + $this->question = $question; + } + + /** + * @return \assStackQuestion + */ + public function getQuestion() + { + return $this->question; + } + + /** + * @param int $first_question + */ + public function setFirstQuestion($first_question) + { + $this->first_question = $first_question; + } + + /** + * @return int + */ + public function getFirstQuestion() + { + return $this->first_question; + } + + /** + * @return string allowed html tags, e.g. "..." + */ + public function setRTETags($tags) + { + $this->rte_tags = $tags; + } + + /** + * @return string allowed html tags, e.g. "..." + */ + public function getRTETags() + { + return $this->rte_tags; + } + + public function php72Format($raw_data) + { + $full_data = array(); + + foreach ($raw_data as $question_data) { + $data = array(); + //Check for not category + if (is_array($question_data['category'])) { + continue; + } + + //Question Name + if (isset($question_data['name'][0]['text'][0]["_content"])) { + $data['name'][0]['text'] = $question_data['name'][0]['text'][0]["_content"]; + } elseif (isset($question_data['name'][0]['text'])) { + $data['name'][0]['text'] = $question_data['name'][0]['text']; + } else { + echo "Unknown title format"; + exit; + } + + //Question text + $data['questiontext'][0]['text'] = $question_data['questiontext'][0]['text']; + + //General feedback + $data['generalfeedback'][0]['text'] = $question_data['generalfeedback'][0]['text']; + + //default grade + $data['defaultgrade'] = $question_data['defaultgrade'][0]["_content"]; + + //penalty + $data['penalty'] = $question_data['penalty'][0]["_content"]; + + //hidden + if (isset($question_data['hidden'][0]["_content"])) { + $data['hidden'] = $question_data['hidden'][0]["_content"]; + } else { + $data['hidden'] = ""; + } + + //stackversion + if (isset($question_data['stackversion'][0]["_content"])) { + $data['stackversion'][0]['text'] = $question_data['stackversion'][0]['text']; + } else { + $data['stackversion'][0]['text'] = ""; + } + + //questionvariables 2 versions to solve problems with question variables tarting with comments + if (isset($question_data['questionvariables'][0]['text'][0]['_content'])) { + $data['questionvariables'][0]['text'] = $question_data['questionvariables'][0]['text'][0]['_content']; + } elseif (isset($question_data['questionvariables'][0]['text']) AND is_string($question_data['questionvariables'][0]['text'])) { + $data['questionvariables'][0]['text'] = $question_data['questionvariables'][0]['text']; + } else { + $data['questionvariables'][0]['text'] = ""; + } + + //specificfeedback: + if (isset($question_data['specificfeedback'][0]['text'][0]['_content'])) { + $data['specificfeedback'][0]['text'] = $question_data['specificfeedback'][0]['text'][0]['_content']; + } elseif (isset($question_data['specificfeedback'][0]['text']) AND is_string($question_data['specificfeedback'][0]['text'])) { + $data['specificfeedback'][0]['text'] = $question_data['specificfeedback'][0]['text']; + } else { + $data['specificfeedback'][0]['text'] = ""; + } + + //questionnote + if (isset($question_data['questionnote'][0]['text'][0]['_content'])) { + $data['questionnote'][0]['text'] = $question_data['questionnote'][0]['text'][0]['_content']; + } elseif (isset($question_data['questionnote'][0]['text']) AND is_string($question_data['questionnote'][0]['text'])) { + $data['questionnote'][0]['text'] = $question_data['questionnote'][0]['text']; + } else { + $data['questionnote'][0]['text'] = ""; + } + + //questionsimplify + if (isset($question_data['questionsimplify'][0]["_content"])) { + $data['questionsimplify'] = $question_data['questionsimplify'][0]["_content"]; + } else { + $data['questionsimplify'] = ""; + } + + //assumepositive + if (isset($question_data['assumepositive'][0]["_content"])) { + $data['assumepositive'] = $question_data['assumepositive'][0]["_content"]; + } else { + $data['assumepositive'] = ""; + } + + //assumereal + if (isset($question_data['assumereal'][0]["_content"])) { + $data['assumereal'] = $question_data['assumereal'][0]["_content"]; + } else { + $data['assumereal'] = ""; + } + + //prtcorrect + if (isset($question_data['prtcorrect'][0]["_content"])) { + $data['prtcorrect'][0]['text'] = $question_data['prtcorrect'][0]['text']; + } else { + $data['prtcorrect'][0]['text'] = ""; + } + + //prtpartiallycorrect + if (isset($question_data['prtpartiallycorrect'][0]["_content"])) { + $data['prtpartiallycorrect'][0]['text'] = $question_data['prtpartiallycorrect'][0]['text']; + } else { + $data['prtpartiallycorrect'][0]['text'] = ""; + } + + //prtincorrect + if (isset($question_data['prtincorrect'][0]["_content"])) { + $data['prtincorrect'][0]['text'] = $question_data['prtincorrect'][0]['text']; + } else { + $data['prtincorrect'][0]['text'] = ""; + } + + //multiplicationsign + if (isset($question_data['multiplicationsign'][0]["_content"])) { + $data['multiplicationsign'] = $question_data['multiplicationsign'][0]["_content"]; + } else { + $data['multiplicationsign'] = ""; + } + + //sqrtsign + if (isset($question_data['sqrtsign'][0]["_content"])) { + $data['sqrtsign'] = $question_data['sqrtsign'][0]["_content"]; + } else { + $data['sqrtsign'] = ""; + } + + //complexno + if (isset($question_data['complexno'][0]["_content"])) { + $data['complexno'] = $question_data['complexno'][0]["_content"]; + } else { + $data['complexno'] = ""; + } + + //inversetrig + if (isset($question_data['inversetrig'][0]["_content"])) { + $data['inversetrig'] = $question_data['inversetrig'][0]["_content"]; + } else { + $data['inversetrig'] = ""; + } + + //matrixparens + if (isset($question_data['matrixparens'][0]["_content"])) { + $data['matrixparens'] = $question_data['matrixparens'][0]["_content"]; + } else { + $data['matrixparens'] = ""; + } + + //variantsselectionseed + if (isset($question_data['variantsselectionseed'])) { + $data['variantsselectionseed'] = $question_data['variantsselectionseed']; + } else { + $data['variantsselectionseed'] = ""; + } + + //Inputs + if (is_array($question_data['input'])) { + foreach ($question_data['input'] as $input_raw) { + $input_data = array(); + + //name + if (isset($input_raw['name'][0]["_content"])) { + $input_data['name'] = $input_raw['name'][0]["_content"]; + } else { + $input_data['name'] = ""; + } + + //type + if (isset($input_raw['type'][0]["_content"])) { + $input_data['type'] = $input_raw['type'][0]["_content"]; + } else { + $input_data['type'] = ""; + } + + //tans + if (isset($input_raw['tans'][0]["_content"])) { + $input_data['tans'] = $input_raw['tans'][0]["_content"]; + } else { + $input_data['tans'] = ""; + } + + //boxsize + if (isset($input_raw['boxsize'][0]["_content"])) { + $input_data['boxsize'] = $input_raw['boxsize'][0]["_content"]; + } else { + $input_data['boxsize'] = ""; + } + + //strictsyntax + if (isset($input_raw['strictsyntax'][0]["_content"])) { + $input_data['strictsyntax'] = $input_raw['strictsyntax'][0]["_content"]; + } else { + $input_data['strictsyntax'] = ""; + } + + //insertstars + if (isset($input_raw['insertstars'][0]["_content"])) { + $input_data['insertstars'] = $input_raw['insertstars'][0]["_content"]; + } else { + $input_data['insertstars'] = ""; + } + + //syntaxhint + if (isset($input_raw['syntaxhint'][0]["_content"])) { + $input_data['syntaxhint'] = $input_raw['syntaxhint'][0]["_content"]; + } else { + $input_data['syntaxhint'] = ""; + } + + //syntaxattribute + if (isset($input_raw['syntaxattribute'][0]["_content"])) { + $input_data['syntaxattribute'] = $input_raw['syntaxattribute'][0]["_content"]; + } else { + $input_data['syntaxattribute'] = ""; + } + + //forbidwords + if (isset($input_raw['forbidwords'][0]["_content"])) { + $input_data['forbidwords'] = $input_raw['forbidwords'][0]["_content"]; + } else { + $input_data['forbidwords'] = ""; + } + + //allowwords + if (isset($input_raw['allowwords'][0]["_content"])) { + $input_data['allowwords'] = $input_raw['allowwords'][0]["_content"]; + } else { + $input_data['allowwords'] = ""; + } + + //forbidfloat + if (isset($input_raw['forbidfloat'][0]["_content"])) { + $input_data['forbidfloat'] = $input_raw['forbidfloat'][0]["_content"]; + } else { + $input_data['forbidfloat'] = ""; + } + + //requirelowestterms + if (isset($input_raw['requirelowestterms'][0]["_content"])) { + $input_data['requirelowestterms'] = $input_raw['requirelowestterms'][0]["_content"]; + } else { + $input_data['requirelowestterms'] = ""; + } + + //checkanswertype + if (isset($input_raw['checkanswertype'][0]["_content"])) { + $input_data['checkanswertype'] = $input_raw['checkanswertype'][0]["_content"]; + } else { + $input_data['checkanswertype'] = ""; + } + + //mustverify + if (isset($input_raw['mustverify'][0]["_content"])) { + $input_data['mustverify'] = $input_raw['mustverify'][0]["_content"]; + } else { + $input_data['mustverify'] = ""; + } + + //showvalidation + if (isset($input_raw['showvalidation'][0]["_content"])) { + $input_data['showvalidation'] = $input_raw['showvalidation'][0]["_content"]; + } else { + $input_data['showvalidation'] = ""; + } + + //options + if (isset($input_raw['options'][0]["_content"])) { + $input_data['options'] = $input_raw['options'][0]["_content"]; + } else { + $input_data['options'] = ""; + } + + //Add to question + $data['input'][] = $input_data; + } + } + + //PRT + if (is_array($question_data['prt'])) { + foreach ($question_data['prt'] as $prt_raw) { + $prt_data = array(); + + //name + if (isset($prt_raw['name'][0]["_content"])) { + $prt_data['name'] = $prt_raw['name'][0]["_content"]; + } else { + $prt_data['name'] = ""; + } + + //value + if (isset($prt_raw['value'][0]["_content"])) { + $prt_data['value'] = $prt_raw['value'][0]["_content"]; + } else { + $prt_data['value'] = ""; + } + + //autosimplify + if (isset($prt_raw['autosimplify'][0]["_content"])) { + $prt_data['autosimplify'] = $prt_raw['autosimplify'][0]["_content"]; + } else { + $prt_data['autosimplify'] = ""; + } + + //feedbackvariables + if (isset($prt_raw['feedbackvariables'][0]["_content"])) { + $prt_data['feedbackvariables'] = $prt_raw['feedbackvariables'][0]["_content"]; + } elseif (isset($prt_raw['feedbackvariables'][0]["text"][0]["_content"])) { + $prt_data['feedbackvariables'] = $prt_raw['feedbackvariables'][0]["text"][0]["_content"]; + } elseif (isset($prt_raw['feedbackvariables'][0]["text"])) { + $prt_data['feedbackvariables'] = $prt_raw['feedbackvariables'][0]["text"]; + } + + //Nodes + if (is_array($prt_raw['node'])) { + foreach ($prt_raw['node'] as $node_raw) { + $node_data = array(); + + //name + if (isset($node_raw['name'][0]["_content"])) { + $node_data['name'] = $node_raw['name'][0]["_content"]; + } else { + $node_data['name'] = ""; + } + + //answertest + if (isset($node_raw['answertest'][0]["_content"])) { + $node_data['answertest'] = $node_raw['answertest'][0]["_content"]; + } else { + $node_data['answertest'] = ""; + } + + //sans + if (isset($node_raw['sans'][0]["_content"])) { + $node_data['sans'] = $node_raw['sans'][0]["_content"]; + } else { + $node_data['sans'] = ""; + } + + //tans + if (isset($node_raw['tans'][0]["_content"])) { + $node_data['tans'] = $node_raw['tans'][0]["_content"]; + } else { + $node_data['tans'] = ""; + } + + //testoptions + if (isset($node_raw['testoptions'][0]["_content"])) { + $node_data['testoptions'] = $node_raw['testoptions'][0]["_content"]; + } else { + $node_data['testoptions'] = ""; + } + + //quiet + if (isset($node_raw['quiet'][0]["_content"])) { + $node_data['quiet'] = $node_raw['quiet'][0]["_content"]; + } else { + $node_data['quiet'] = ""; + } + + //truescoremode + if (isset($node_raw['truescoremode'][0]["_content"])) { + $node_data['truescoremode'] = $node_raw['truescoremode'][0]["_content"]; + } else { + $node_data['truescoremode'] = ""; + } + + //truescore + if (isset($node_raw['truescore'][0]["_content"])) { + $node_data['truescore'] = $node_raw['truescore'][0]["_content"]; + } else { + $node_data['truescore'] = ""; + } + + //truepenalty + if (isset($node_raw['truepenalty'][0]["_content"])) { + $node_data['truepenalty'] = $node_raw['truepenalty'][0]["_content"]; + } else { + $node_data['truepenalty'] = ""; + } + + //truenextnode + if (isset($node_raw['truenextnode'][0]["_content"])) { + $node_data['truenextnode'] = $node_raw['truenextnode'][0]["_content"]; + } else { + $node_data['truenextnode'] = ""; + } + + //trueanswernote + if (isset($node_raw['trueanswernote'][0]["_content"])) { + $node_data['trueanswernote'] = $node_raw['trueanswernote'][0]["_content"]; + } else { + $node_data['trueanswernote'] = ""; + } + + //truefeedback + if (isset($node_raw['truefeedback'][0]["text"][0]["_content"])) { + $node_data['truefeedback'][0]["text"] = $node_raw['truefeedback'][0]["text"][0]["_content"]; + } elseif (isset($node_raw['truefeedback'][0]["text"])) { + $node_data['truefeedback'][0]["text"] = $node_raw['truefeedback'][0]["text"]; + } else { + $node_data['truefeedback'][0]["text"] = ""; + } + + //falsescoremode + if (isset($node_raw['falsescoremode'][0]["_content"])) { + $node_data['falsescoremode'] = $node_raw['falsescoremode'][0]["_content"]; + } else { + $node_data['falsescoremode'] = ""; + } + + //falsescore + if (isset($node_raw['falsescore'][0]["_content"])) { + $node_data['falsescore'] = $node_raw['falsescore'][0]["_content"]; + } else { + $node_data['falsescore'] = ""; + } + + //falsepenalty + if (isset($node_raw['falsepenalty'][0]["_content"])) { + $node_data['falsepenalty'] = $node_raw['falsepenalty'][0]["_content"]; + } else { + $node_data['falsepenalty'] = ""; + } + + //falsenextnode + if (isset($node_raw['falsenextnode'][0]["_content"])) { + $node_data['falsenextnode'] = $node_raw['falsenextnode'][0]["_content"]; + } else { + $node_data['falsenextnode'] = ""; + } + + //falseanswernote + if (isset($node_raw['falseanswernote'][0]["_content"])) { + $node_data['falseanswernote'] = $node_raw['falseanswernote'][0]["_content"]; + } else { + $node_data['falseanswernote'] = ""; + } + + //falsefeedback + if (isset($node_raw['falsefeedback'][0]["text"][0]["_content"])) { + $node_data['falsefeedback'][0]["text"] = $node_raw['falsefeedback'][0]["text"][0]["_content"]; + } elseif (isset($node_raw['falsefeedback'][0]["text"])) { + $node_data['falsefeedback'][0]["text"] = $node_raw['falsefeedback'][0]["text"]; + } else { + $node_data['falsefeedback'][0]["text"] = ""; + } + + //Add to prt + $prt_data['node'][] = $node_data; + } + } + + //Add to question + $data['prt'][] = $prt_data; + + //qtest + if (is_array($question_data['qtest'])) { + foreach ($question_data['qtest'] as $qtest_raw) { + $qtest_data = array(); + + //testcase + if (isset($qtest_raw['testcase'][0]["_content"])) { + $qtest_data['testcase'] = $qtest_raw['testcase'][0]["_content"]; + } else { + $qtest_data['testcase'] = ""; + } + + //testinput + if (isset($qtest_raw['testinput'][0]['name'][0]["_content"]) AND isset($qtest_raw['testinput'][0]['value'][0]["_content"])) { + $qtest_data['testinput'][0]['name'] = $qtest_raw['testinput'][0]['name'][0]["_content"]; + $qtest_data['testinput'][0]['value'] = $qtest_raw['testinput'][0]['value'][0]["_content"]; + } else { + $qtest_data['testinput'][0]['name'] = ""; + $qtest_data['testinput'][0]['value'] = ""; + } + + //expected + if (isset($qtest_raw['expected'][0]['name'][0]["_content"]) AND isset($qtest_raw['expected'][0]['expectedscore'][0]["_content"]) AND isset($qtest_raw['expected'][0]['expectedanswernote'][0]["_content"])) { + $qtest_data['expected'][0]['name'] = $qtest_raw['expected'][0]['name'][0]["_content"]; + $qtest_data['expected'][0]['expectedscore'] = $qtest_raw['expected'][0]['expectedscore'][0]["_content"]; + $qtest_data['expected'][0]['expectedpenalty'] = $qtest_raw['expected'][0]['expectedpenalty'][0]["_content"]; + $qtest_data['expected'][0]['expectedanswernote'] = $qtest_raw['expected'][0]['expectedanswernote'][0]["_content"]; + + } else { + $qtest_data['expected'][0]['name'] = ""; + $qtest_data['expected'][0]['expectedscore'] = ""; + $qtest_data['expected'][0]['expectedpenalty'] = ""; + $qtest_data['expected'][0]['expectedanswernote'] = ""; + } + + + //Add to question + $data['qtest'][] = $qtest_data; + } + } + + } + } + + //Add to full data + $full_data['question'][] = $data; + + } + + return $full_data; + } } From a687f3a98ef10420f25a2e3150bb3bf065bf0a25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Copado?= Date: Mon, 20 Jan 2020 14:46:36 +0100 Subject: [PATCH 18/23] 3.1.8 Include insert stars --- README.md | 5 +++++ .../class.assStackQuestionAuthoringGUI.php | 16 ++++++++++++---- classes/class.ilassStackQuestionConfigGUI.php | 12 ++++++++++-- lang/ilias_de.lang | 8 +++++++- lang/ilias_en.lang | 8 +++++++- plugin.php | 2 +- 6 files changed, 42 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 4970f30c..e9229c68 100644 --- a/README.md +++ b/README.md @@ -125,4 +125,9 @@ Version 3.1.7 (2019-11-27) for ILIAS 5.4 - https://mantis.ilias.de/view.php?id=26179 About crashing in test results - Solved #25225 about validation after checking - Solved #25318 about dropdown best solution problem + +Version 3.1.8 (2020-01-20) for ILIAS 5.4 +---------------------------------------- +Included new options for insert stars, now teachers have 6 different options, you can find more information here: +- https://github.com/maths/moodle-qtype_stack/blob/master/doc/en/Authoring/Inputs.md#insert-stars--insert_stars diff --git a/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php b/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php index 6bb81cb2..08204204 100644 --- a/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php +++ b/classes/GUI/question_authoring/class.assStackQuestionAuthoringGUI.php @@ -442,8 +442,16 @@ public function getInputPart(assStackQuestionInput $input) $input_strict_syntax = new ilCheckboxInputGUI($this->getPlugin()->txt('input_strict_syntax'), $input->getInputName() . '_input_strict_syntax'); $input_strict_syntax->setInfo($this->getPlugin()->txt("input_strict_syntax_info")); - $input_insert_stars = new ilCheckboxInputGUI($this->getPlugin()->txt('input_insert_stars'), $input->getInputName() . '_input_insert_stars'); - $input_insert_stars->setInfo($this->getPlugin()->txt("input_insert_stars_info")); + $input_insert_stars = new ilSelectInputGUI($this->getPlugin()->txt('input_insert_stars'), $input->getInputName() . '_input_insert_stars'); + $input_insert_stars->setOptions(array( + "0" => $this->getPlugin()->txt('input_stars_no_stars'), + "1" => $this->getPlugin()->txt('input_stars_implied'), + "2" => $this->getPlugin()->txt('input_stars_singlechar'), + "3" => $this->getPlugin()->txt('input_stars_spaces'), + "4" => $this->getPlugin()->txt('input_stars_implied_spaces'), + "5" => $this->getPlugin()->txt('input_type_implied_spaces_single'))); + + $input_insert_stars->setInfo($this->getPlugin()->txt("input_insert_stars_info")); $input_syntax_hint = new ilTextInputGUI($this->getPlugin()->txt('input_syntax_hint'), $input->getInputName() . '_input_syntax_hint'); $input_syntax_hint->setInfo($this->getPlugin()->txt('input_syntax_hint_info')); @@ -482,7 +490,7 @@ public function getInputPart(assStackQuestionInput $input) //$input_model_answer->setValue($this->default[""]); $input_box_size->setValue($this->default["input_box_size"]); $input_strict_syntax->setChecked((int)$this->default["input_strict_syntax"]); - $input_insert_stars->setChecked((int)$this->default["input_insert_stars"]); + $input_insert_stars->setValue((int)$this->default["input_insert_stars"]); $input_syntax_hint->setValue($this->default["input_syntax_hint"]); $input_forbidden_words->setValue($this->default["input_forbidden_words"]); $input_allow_words->setValue($this->default["input_allow_words"]); @@ -498,7 +506,7 @@ public function getInputPart(assStackQuestionInput $input) $input_model_answer->setValue($input->getTeacherAnswer()); $input_box_size->setValue($input->getBoxSize()); $input_strict_syntax->setChecked($input->getStrictSyntax()); - $input_insert_stars->setChecked($input->getInsertStars()); + $input_insert_stars->setValue($input->getInsertStars()); $input_syntax_hint->setValue($input->getSyntaxHint()); $input_forbidden_words->setValue($input->getForbidWords()); $input_allow_words->setValue($input->getAllowWords()); diff --git a/classes/class.ilassStackQuestionConfigGUI.php b/classes/class.ilassStackQuestionConfigGUI.php index 383bdb13..e5b4cb61 100644 --- a/classes/class.ilassStackQuestionConfigGUI.php +++ b/classes/class.ilassStackQuestionConfigGUI.php @@ -678,9 +678,17 @@ public function getDefaultInputsSettingsForm() $form->addItem($input_strict_syntax); //Input insert stars - $input_insert_stars = new ilCheckboxInputGUI($this->plugin_object->txt('input_insert_stars'), 'input_insert_stars'); + $input_insert_stars = new ilSelectInputGUI($this->plugin_object->txt('input_insert_stars'), 'input_insert_stars'); + $input_insert_stars->setOptions(array( + "0" => $this->plugin_object->txt('input_stars_no_stars'), + "1" => $this->plugin_object->txt('input_stars_implied'), + "2" => $this->plugin_object->txt('input_stars_singlechar'), + "3" => $this->plugin_object->txt('input_stars_spaces'), + "4" => $this->plugin_object->txt('input_stars_implied_spaces'), + "5" => $this->plugin_object->txt('input_type_implied_spaces_single'))); + $input_insert_stars->setInfo($this->plugin_object->txt("input_insert_stars_info")); - $input_insert_stars->setChecked($inputs_data['input_insert_stars']); + $input_insert_stars->setValue((int)$inputs_data['input_insert_stars']); $form->addItem($input_insert_stars); //Input forbid float diff --git a/lang/ilias_de.lang b/lang/ilias_de.lang index 429e726d..9eb7fc2e 100644 --- a/lang/ilias_de.lang +++ b/lang/ilias_de.lang @@ -458,4 +458,10 @@ feedback_stylesheet_id_info#:#Wählen Sie den Content-Style, der für das STACK- feedback_default#:#Allgemeiner Feedback-Style feedback_default_info#:#Wählen Sie den Feedback-Style für Feedback-Nachrichten in STACK-Fragen. Er wird für den Abschnitt einer Feedback-Nachricht von STACK verwendet. Innerhalb dieses Abschnitts sind die Feedbacks der Knoten eines Rückmeldebaums eingebettet, die zusätzlich mit eigenen Styles versehen werden können. nodes_feedback#:#Feedback von Knoten -config_prts_changed_message#:#Änderungen wurden übernommen \ No newline at end of file +config_prts_changed_message#:#Änderungen wurden übernommen +input_stars_no_stars#:#Keine Sternchen einfügen +input_stars_implied#:#Sternchen nur für implizierte Multiplikation einfügen +input_stars_singlechar#:#Sternchen einfügen, indem von Variablennamen mit nur einem Zeichen ausgegangen wird +input_stars_spaces#:#Sternchen nur für Leerzeichen einfügen +input_stars_implied_spaces#:#Sternchen für implizierte Multiplikation und für Leerzeichen einfügen +input_type_implied_spaces_single#:#Sternchen einfügen, indem von Variablennamen mit nur einem Zeichen ausgegangen wird, implizierte und für Leerzeichen \ No newline at end of file diff --git a/lang/ilias_en.lang b/lang/ilias_en.lang index 45eb8eef..2e346fcd 100644 --- a/lang/ilias_en.lang +++ b/lang/ilias_en.lang @@ -455,4 +455,10 @@ feedback_stylesheet_id_info#:#Select the content style used for STACK Feedback. feedback_default#:#General Feedback Style feedback_default_info#:#Select the feedback style for feedback messages in STACK questions. It is used for the section of a STACK feedback message. Within this section, the feedbacks of the nodes of a potential response tree are embedded, which can also be provided with their own styles. nodes_feedback#:#Feedback from Nodes -config_prts_changed_message#:#Changes have been applied \ No newline at end of file +config_prts_changed_message#:#Changes have been applied +input_stars_no_stars#:#Don't insert stars +input_stars_implied#:#Insert stars for implied multiplication only +input_stars_singlechar#:#Insert stars assuming single-character variable names +input_stars_spaces#:#Insert stars for spaces only +input_stars_implied_spaces#:#Insert stars for implied multiplication and for spaces +input_type_implied_spaces_single#:#Insert stars assuming single-character variables, implied and for spaces \ No newline at end of file diff --git a/plugin.php b/plugin.php index ce661a46..5134cfdd 100644 --- a/plugin.php +++ b/plugin.php @@ -9,7 +9,7 @@ // code version; must be changed for all code changes -$version = "3.1.7"; +$version = "3.1.8"; // ilias min and max version; must always reflect the versions that should // run with the plugin From 39c76c84a233cf2aa47b31e1b04d4a95fcee80a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Copado?= Date: Mon, 20 Jan 2020 15:41:56 +0100 Subject: [PATCH 19/23] 3.1.8 Fix import from MoodleXML --- .../MoodleXML/class.assStackQuestionMoodleImport.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/classes/model/import/MoodleXML/class.assStackQuestionMoodleImport.php b/classes/model/import/MoodleXML/class.assStackQuestionMoodleImport.php index fddb6f08..469c364a 100644 --- a/classes/model/import/MoodleXML/class.assStackQuestionMoodleImport.php +++ b/classes/model/import/MoodleXML/class.assStackQuestionMoodleImport.php @@ -473,7 +473,13 @@ private function getPRTsFromXML($data) $new_prt->setPRTName($prt_name); $new_prt->setPRTValue(strip_tags($prt['value'])); $new_prt->setAutoSimplify(strip_tags($prt['autosimplify'])); - $new_prt->setPRTFeedbackVariables($prt['feedbackvariables']); + if (is_string($prt['feedbackvariables'])) { + $new_prt->setPRTFeedbackVariables($prt['feedbackvariables']); + } elseif (is_string($prt['feedbackvariables'][0]["text"])) { + $new_prt->setPRTFeedbackVariables($prt['feedbackvariables'][0]["text"]); + } else { + $new_prt->setPRTFeedbackVariables(""); + } //Creation of Nodes $prt_nodes = $this->getPRTNodesFromXML($prt['node'], $new_prt->getPRTName()); From df58e3ed8da07c4db23219293515b48ecdbbd6f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Copado?= Date: Thu, 30 Jan 2020 15:43:49 +0100 Subject: [PATCH 20/23] 3.1.9 Preview mode points properly calculated --- README.md | 3 +++ classes/class.assStackQuestion.php | 21 ++++++++++++++++++- classes/class.assStackQuestionGUI.php | 9 +++++--- .../class.assStackQuestionDisplay.php | 1 + classes/stack/input/equiv/equiv.class.php | 2 +- plugin.php | 2 +- 6 files changed, 32 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index e9229c68..85c1d521 100644 --- a/README.md +++ b/README.md @@ -131,3 +131,6 @@ Version 3.1.8 (2020-01-20) for ILIAS 5.4 Included new options for insert stars, now teachers have 6 different options, you can find more information here: - https://github.com/maths/moodle-qtype_stack/blob/master/doc/en/Authoring/Inputs.md#insert-stars--insert_stars +Version 3.1.9 (2020-01-30) for ILIAS 5.4 +---------------------------------------- +Solved a bug that prevented points to be properly calculated in preview mode when more than one PRT is present in a question. diff --git a/classes/class.assStackQuestion.php b/classes/class.assStackQuestion.php index 3bfab54e..7ba79d45 100644 --- a/classes/class.assStackQuestion.php +++ b/classes/class.assStackQuestion.php @@ -1690,12 +1690,20 @@ public function getSolutionSubmit() public function calculateReachedPointsForSolution($found_values) { + //SHOW POINTS IN PREVIEW + if(empty($this->getStackQuestion()->getPRTResults())){ + if(isset($found_values["question_display"]["reached_points"])){ + if(is_float($found_values["question_display"]["reached_points"])){ + return $found_values["question_display"]["reached_points"]; + } + } + + } $points = 0.0; foreach ($this->getStackQuestion()->getPRTResults() as $prt_name => $results) { $points = $points + $results['points']; } - return $points; } @@ -1951,4 +1959,15 @@ public function fetchIndexedValuesFromValuePairs(array $valuePairs) { return $valuePairs; } + + /** + * Calculate the points a user has reached in a preview session + * @param ilAssQuestionPreviewSession $previewSession + * @return float + */ + public function calculateReachedPointsFromPreviewSession(ilAssQuestionPreviewSession $previewSession) + { + $solution = (array) $previewSession->getParticipantsSolution(); + return $this->calculateReachedPointsForSolution($solution); + } } \ No newline at end of file diff --git a/classes/class.assStackQuestionGUI.php b/classes/class.assStackQuestionGUI.php index 8dd98da0..ca8ea64b 100644 --- a/classes/class.assStackQuestionGUI.php +++ b/classes/class.assStackQuestionGUI.php @@ -450,7 +450,9 @@ public function getPreview($show_question_only = FALSE, $showInlineFeedback = fa $tabs = $DIC->tabs(); //Get solutions if given - $solutions = is_object($this->getPreviewSession()) ? (array)$this->getPreviewSession()->getParticipantsSolution() : array(); + if (is_object($this->getPreviewSession())) { + $solutions = (array)$this->getPreviewSession()->getParticipantsSolution(); + } //Include preview classes and set tab $this->plugin->includeClass("model/question_display/class.assStackQuestionPreview.php"); @@ -484,12 +486,14 @@ public function getPreview($show_question_only = FALSE, $showInlineFeedback = fa //Get question preview data $question_preview_object = new assStackQuestionPreview($this->plugin, $this->object, $seed, $solutions); $question_preview_data = $question_preview_object->getQuestionPreviewData(); +# + $this->getPreviewSession()->setParticipantsSolution($question_preview_data); + //$this->object->setPoints($question_preview_data["question_display"]["reached_points"]); //Get question preview GUI $question_preview_gui_object = new assStackQuestionPreviewGUI($this->plugin, $question_preview_data); $question_preview_gui = $question_preview_gui_object->getQuestionPreviewGUI(); - //Set preview mode $this->preview_mode = $question_preview_data; @@ -513,7 +517,6 @@ public function getPreview($show_question_only = FALSE, $showInlineFeedback = fa // get page object output $questionoutput = $this->getILIASPage($questionoutput); } - return $questionoutput; } diff --git a/classes/model/question_display/class.assStackQuestionDisplay.php b/classes/model/question_display/class.assStackQuestionDisplay.php index de93cb6a..59ca5837 100644 --- a/classes/model/question_display/class.assStackQuestionDisplay.php +++ b/classes/model/question_display/class.assStackQuestionDisplay.php @@ -142,6 +142,7 @@ public function getQuestionDisplayData($in_test = FALSE) $display_data['prts'][$prt_name]['display'] = $this->replacementForPRTPlaceholders($prt, $prt_name, $in_test); } + $display_data["reached_points"] = $this->getQuestion()->reached_points; return $display_data; } diff --git a/classes/stack/input/equiv/equiv.class.php b/classes/stack/input/equiv/equiv.class.php index da892dab..ad0fbe38 100644 --- a/classes/stack/input/equiv/equiv.class.php +++ b/classes/stack/input/equiv/equiv.class.php @@ -202,7 +202,7 @@ public function contents_to_maxima($contents) { * @param string $in * @return string */ - private function maxima_to_raw_input($in) { + public function maxima_to_raw_input($in) { $values = stack_utils::list_to_array($in, false); foreach ($values as $key => $val) { $values[$key] = $this->stackeq_to_equals($val); diff --git a/plugin.php b/plugin.php index 5134cfdd..2c2ca0b2 100644 --- a/plugin.php +++ b/plugin.php @@ -9,7 +9,7 @@ // code version; must be changed for all code changes -$version = "3.1.8"; +$version = "3.1.9"; // ilias min and max version; must always reflect the versions that should // run with the plugin From e9ab10385f620ebbc739d602334d9506a73aedc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Copado?= Date: Fri, 31 Jan 2020 13:11:04 +0100 Subject: [PATCH 21/23] 3.1.9 Preview in Test fixed --- classes/class.assStackQuestionGUI.php | 8 +++++--- classes/utils/class.assStackQuestionUtils.php | 16 +++++++++------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/classes/class.assStackQuestionGUI.php b/classes/class.assStackQuestionGUI.php index ca8ea64b..c781335a 100644 --- a/classes/class.assStackQuestionGUI.php +++ b/classes/class.assStackQuestionGUI.php @@ -486,9 +486,11 @@ public function getPreview($show_question_only = FALSE, $showInlineFeedback = fa //Get question preview data $question_preview_object = new assStackQuestionPreview($this->plugin, $this->object, $seed, $solutions); $question_preview_data = $question_preview_object->getQuestionPreviewData(); -# - $this->getPreviewSession()->setParticipantsSolution($question_preview_data); - //$this->object->setPoints($question_preview_data["question_display"]["reached_points"]); + + if(is_a($this->getPreviewSession(),"ilAssQuestionPreviewSession")){ + $this->getPreviewSession()->setParticipantsSolution($question_preview_data); + //$this->object->setPoints($question_preview_data["question_display"]["reached_points"]); + } //Get question preview GUI $question_preview_gui_object = new assStackQuestionPreviewGUI($this->plugin, $question_preview_data); diff --git a/classes/utils/class.assStackQuestionUtils.php b/classes/utils/class.assStackQuestionUtils.php index 1ddc1615..61fa1431 100644 --- a/classes/utils/class.assStackQuestionUtils.php +++ b/classes/utils/class.assStackQuestionUtils.php @@ -349,13 +349,15 @@ public static function _createOptions(assStackQuestionOptions $ilias_options) public static function _isArrayEmpty($array) { //If array is not empty returns it, otherwise return FALSE; - foreach ($array as $value) - { - if ($value != '' AND $value != '[]') - { - return FALSE; - } - } + if(is_array($array)){ + foreach ($array as $value) + { + if ($value != '' AND $value != '[]') + { + return FALSE; + } + } + } return TRUE; } From f93c828559294f8649835b9c5535904342d8b7d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Copado?= Date: Wed, 24 Jun 2020 14:05:46 +0200 Subject: [PATCH 22/23] Version 3.1.10 for ILIAS 5.4 --- README.md | 8 + classes/class.assStackQuestionGUI.php | 657 +++++++----------- .../class.assStackQuestionDisplay.php | 6 +- .../stack/answertest/at_general_cas.class.php | 8 +- classes/stack/cas/cassession.class.php | 1 + .../stack/input/checkbox/checkbox.class.php | 3 +- .../stack/input/dropdown/dropdown.class.php | 3 +- classes/stack/input/radio/radio.class.php | 3 +- lang/stack_de.php | 1 + plugin.php | 2 +- 10 files changed, 263 insertions(+), 429 deletions(-) diff --git a/README.md b/README.md index 85c1d521..9ad46ae8 100644 --- a/README.md +++ b/README.md @@ -134,3 +134,11 @@ Included new options for insert stars, now teachers have 6 different options, yo Version 3.1.9 (2020-01-30) for ILIAS 5.4 ---------------------------------------- Solved a bug that prevented points to be properly calculated in preview mode when more than one PRT is present in a question. + +Version 3.1.10 (2020-06-24) for ILIAS 5.4 +---------------------------------------- +The following bugs have been solved: +- 25256 and 27830 and 22273 about Matrix validation. +- 24199 about dropdown field dissapearing if answered but other prt related inputs are not answered. +- 27560 about inputs not properly deleted. +- 25256 about specific feedback not shown in test results. diff --git a/classes/class.assStackQuestionGUI.php b/classes/class.assStackQuestionGUI.php index c781335a..89c31868 100644 --- a/classes/class.assStackQuestionGUI.php +++ b/classes/class.assStackQuestionGUI.php @@ -35,8 +35,7 @@ public function __construct($id = -1) $this->plugin = ilPlugin::getPluginObject(IL_COMP_MODULE, "TestQuestionPool", "qst", "assStackQuestion"); $this->object = new assStackQuestion(); - if ($id >= 0) - { + if ($id >= 0) { $this->object->loadFromDb($id); } @@ -57,8 +56,7 @@ public function initRTESupport() $this->required_tags = array("a", "blockquote", "br", "cite", "code", "div", "em", "h1", "h2", "h3", "h4", "h5", "h6", "hr", "img", "li", "ol", "p", "pre", "span", "strike", "strong", "sub", "sup", "table", "caption", "thead", "th", "td", "tr", "u", "ul", "i", "b", "gap"); - if (serialize($this->rte_tags) != serialize(($this->required_tags))) - { + if (serialize($this->rte_tags) != serialize(($this->required_tags))) { $this->rte_tags = $this->required_tags; $obj_advance = new ilObjAdvancedEditing(); @@ -73,8 +71,7 @@ public function initRTESupport() */ public function setRTESupport(ilTextAreaInputGUI $field) { - if (empty($this->rte_tags)) - { + if (empty($this->rte_tags)) { $this->initRTESupport(); } $field->setUseRte(true); @@ -93,8 +90,7 @@ public function setRTESupport(ilTextAreaInputGUI $field) */ public function getRTETags() { - if (empty($this->rte_tags)) - { + if (empty($this->rte_tags)) { $this->initRTESupport(); } @@ -112,8 +108,7 @@ public function writePostData($always = FALSE) { $hasErrors = (!$always) ? $this->editQuestion(TRUE) : FALSE; - if (!$hasErrors) - { + if (!$hasErrors) { $this->deletionManagement(); $this->writeQuestionGenericPostData(); $this->writeQuestionSpecificPostData(); @@ -141,14 +136,32 @@ public function deletionManagement() global $DIC; $lng = $DIC->language(); - if (is_array($_POST['cmd']['save'])) - { - foreach ($this->object->getPotentialResponsesTrees() as $prt_name => $prt) - { - if (isset($_POST['cmd']['save']['delete_full_prt_' . $prt_name])) - { - if ($this->checkPRTForDeletion($prt)) - { + //Input delete: #27560 + $question_text = $_POST["question"]; + preg_match_all('|\[\[input:(\w*)\]\]|U', $question_text, $matches); + $inputs_to_save = $matches[1]; + + foreach ($this->object->getInputs() as $input_name => $input) { + $delete_input = TRUE; + foreach ($inputs_to_save as $key => $input_to_save) { + if ($input_name == $input_to_save) { + $delete_input = FALSE; + } + } + + if ($delete_input) { + $q_inputs = $this->object->getInputs(); + unset($q_inputs[$input_name]); + $this->object->setInputs($q_inputs); + $input->delete(); + + } + } + + if (is_array($_POST['cmd']['save'])) { + foreach ($this->object->getPotentialResponsesTrees() as $prt_name => $prt) { + if (isset($_POST['cmd']['save']['delete_full_prt_' . $prt_name])) { + if ($this->checkPRTForDeletion($prt)) { return FALSE; } $prt->delete(); @@ -157,20 +170,16 @@ public function deletionManagement() $this->object->setPotentialResponsesTrees($ptrs); //#18703 Should delete also nodes - foreach ($prt->getPRTNodes() as $node_name => $node) - { + foreach ($prt->getPRTNodes() as $node_name => $node) { $node->delete(); } return TRUE; } - foreach ($prt->getPRTNodes() as $node_name => $node) - { + foreach ($prt->getPRTNodes() as $node_name => $node) { - if (isset($_POST['cmd']['save']['delete_prt_' . $prt_name . '_node_' . $node->getNodeName()])) - { - if ($this->checkPRTNodeForDeletion($prt, $node)) - { + if (isset($_POST['cmd']['save']['delete_prt_' . $prt_name . '_node_' . $node->getNodeName()])) { + if ($this->checkPRTNodeForDeletion($prt, $node)) { return FALSE; } $node->delete(); @@ -183,8 +192,7 @@ public function deletionManagement() } //Copy Node - if (isset($_POST['cmd']['save']['copy_prt_' . $prt_name . '_node_' . $node->getNodeName()])) - { + if (isset($_POST['cmd']['save']['copy_prt_' . $prt_name . '_node_' . $node->getNodeName()])) { //Do node copy here $_SESSION['copy_node'] = $this->object->getId() . "_" . $prt_name . "_" . $node->getNodeName(); ilUtil::sendInfo($lng->txt("qpl_qst_xqcas_node_copied_to_clipboard"), TRUE); @@ -193,8 +201,7 @@ public function deletionManagement() } //Paste Node - if (isset($_POST['cmd']['save']['paste_node_in_' . $prt_name])) - { + if (isset($_POST['cmd']['save']['paste_node_in_' . $prt_name])) { //Do node paste here $raw_data = explode("_", $_SESSION['copy_node']); $paste_question_id = $raw_data[0]; @@ -205,8 +212,7 @@ public function deletionManagement() $paste_node = $paste_prt_node_list[$paste_node_name]; //Change values - if (is_a($paste_node, "assStackQuestionPRTNode")) - { + if (is_a($paste_node, "assStackQuestionPRTNode")) { $paste_node->setNodeId(""); $paste_node->setQuestionId($this->object->getId()); $paste_node->setPRTName($prt_name); @@ -225,8 +231,7 @@ public function deletionManagement() //PRT COpy - if (isset($_POST['cmd']['save']['copy_prt_' . $prt_name])) - { + if (isset($_POST['cmd']['save']['copy_prt_' . $prt_name])) { //Do node copy here $_SESSION['copy_prt'] = $this->object->getId() . "_" . $prt_name; ilUtil::sendInfo($lng->txt("qpl_qst_xqcas_prt_copied_to_clipboard"), TRUE); @@ -236,8 +241,7 @@ public function deletionManagement() } //Paste Node - if (isset($_POST['cmd']['save']['paste_prt'])) - { + if (isset($_POST['cmd']['save']['paste_prt'])) { $raw_data = explode("_", $_SESSION['copy_prt']); $paste_question_id = $raw_data[0]; $paste_prt_name = $raw_data[1]; @@ -246,17 +250,14 @@ public function deletionManagement() $paste_prt_list = assStackQuestionPRT::_read($paste_question_id); $paste_prt = $paste_prt_list[$paste_prt_name]; - if (is_a($paste_prt, 'assStackQuestionPRT')) - { + if (is_a($paste_prt, 'assStackQuestionPRT')) { $paste_prt->setPRTId(-1); $paste_prt->setQuestionId($this->object->getId()); $paste_prt->setPRTName($generated_prt_name); $paste_prt->save(); - foreach ($paste_prt->getPRTNodes() as $prt_node) - { - if (is_a($prt_node, 'assStackQuestionPRTNode')) - { + foreach ($paste_prt->getPRTNodes() as $prt_node) { + if (is_a($prt_node, 'assStackQuestionPRTNode')) { $prt_node->setNodeId(-1); $prt_node->setQuestionId($this->object->getId()); $prt_node->setPRTName($generated_prt_name); @@ -283,10 +284,8 @@ public function deletionManagement() public function checkPRTForDeletion(assStackQuestionPRT $prt) { - if (is_array($this->object->getPotentialResponsesTrees())) - { - if (sizeof($this->object->getPotentialResponsesTrees()) < 2) - { + if (is_array($this->object->getPotentialResponsesTrees())) { + if (sizeof($this->object->getPotentialResponsesTrees()) < 2) { $this->object->setErrors($this->object->getPlugin()->txt('deletion_error_not_enought_prts')); return TRUE; @@ -299,10 +298,8 @@ public function checkPRTForDeletion(assStackQuestionPRT $prt) public function checkPRTNodeForDeletion(assStackQuestionPRT $prt, assStackQuestionPRTNode $node) { - if (is_array($prt->getPRTNodes())) - { - if (sizeof($prt->getPRTNodes()) < 2) - { + if (is_array($prt->getPRTNodes())) { + if (sizeof($prt->getPRTNodes()) < 2) { $this->object->setErrors($this->object->getPlugin()->txt('deletion_error_not_enought_prt_nodes')); return TRUE; @@ -310,17 +307,14 @@ public function checkPRTNodeForDeletion(assStackQuestionPRT $prt, assStackQuesti } - if ((int)$prt->getFirstNodeName() == (int)$node->getNodeName()) - { + if ((int)$prt->getFirstNodeName() == (int)$node->getNodeName()) { $this->object->setErrors($this->object->getPlugin()->txt('deletion_error_first_node')); return TRUE; } - foreach ($prt->getPRTNodes() as $prt_node) - { - if ($prt_node->getTrueNextNode() == $node->getNodeName() OR $prt_node->getFalseNextNode() == $node->getNodeName()) - { + foreach ($prt->getPRTNodes() as $prt_node) { + if ($prt_node->getTrueNextNode() == $node->getNodeName() or $prt_node->getFalseNextNode() == $node->getNodeName()) { $this->object->setErrors($this->object->getPlugin()->txt('deletion_error_connected_node')); return TRUE; @@ -344,28 +338,21 @@ public function writeQuestionSpecificPostData() $text_inputs = stack_utils::extract_placeholders($this->object->getQuestion(), 'input'); //Edition and Deletion of inputs - foreach ($this->object->getInputs() as $input_name => $input) - { - if (in_array($input_name, $text_inputs)) - { + foreach ($this->object->getInputs() as $input_name => $input) { + if (in_array($input_name, $text_inputs)) { //Check if there exists placeholder in text - if (isset($_POST[$input_name . '_input_type'])) - { + if (isset($_POST[$input_name . '_input_type'])) { $input->writePostData($input_name); } - } else - { + } else { //If doesn' exist, check if must be deleted - if (is_array($this->object->getInputs())) - { - if (sizeof($this->object->getInputs()) < 2) - { + if (is_array($this->object->getInputs())) { + if (sizeof($this->object->getInputs()) < 2) { //If there are less than two inputs you cannot delete it //Add placeholder to question text $this->object->setQuestion($this->object->getQuestion() . " [[input:{$input_name}]] [[validation:{$input_name}]]"); } - } else - { + } else { //Delete input from object $db_inputs = $this->object->getInputs(); unset($db_inputs[$input_name]); @@ -376,10 +363,8 @@ public function writeQuestionSpecificPostData() } } //Addition of inputs - foreach ($text_inputs as $input_name) - { - if (is_null($this->object->getInputs($input_name))) - { + foreach ($text_inputs as $input_name) { + if (is_null($this->object->getInputs($input_name))) { //Create new Input $new_input = new assStackQuestionInput(-1, $this->object->getId(), $input_name, 'algebraic', ""); $new_input->getDefaultInput(); @@ -392,17 +377,13 @@ public function writeQuestionSpecificPostData() } //PRT - if (is_array($this->object->getPotentialResponsesTrees())) - { - foreach ($this->object->getPotentialResponsesTrees() as $prt_name => $prt) - { - if (isset($_POST['prt_' . $prt_name . '_value'])) - { + if (is_array($this->object->getPotentialResponsesTrees())) { + foreach ($this->object->getPotentialResponsesTrees() as $prt_name => $prt) { + if (isset($_POST['prt_' . $prt_name . '_value'])) { $prt->writePostData($prt_name, "", $this->getRTETags()); } //Add new node if info is filled in - if ($_POST['prt_' . $prt->getPRTName() . '_node_' . $prt->getPRTName() . '_new_node_student_answer'] != "" AND $_POST['prt_' . $prt->getPRTName() . '_node_' . $prt->getPRTName() . '_new_node_teacher_answer'] != "") - { + if ($_POST['prt_' . $prt->getPRTName() . '_node_' . $prt->getPRTName() . '_new_node_student_answer'] != "" and $_POST['prt_' . $prt->getPRTName() . '_node_' . $prt->getPRTName() . '_new_node_teacher_answer'] != "") { $new_node = new assStackQuestionPRTNode(-1, $this->object->getId(), $prt->getPRTName(), $prt->getLastNodeName() + 1, $_POST['prt_' . $prt->getPRTName() . '_node_' . $prt->getPRTName() . '_new_node_pos_next'], $_POST['prt_' . $prt->getPRTName() . '_node_' . $prt->getPRTName() . '_new_node_neg_next']); $new_node->writePostData($prt_name, $prt_name . '_new_node', "", $new_node->getNodeName(), $this->getRTETags()); } @@ -411,8 +392,7 @@ public function writeQuestionSpecificPostData() //Addition of PRT and Nodes //New PRT (and node) if the new prt is filled - if (isset($_POST['prt_new_prt_name']) AND $_POST['prt_new_prt_name'] != 'new_prt' AND !preg_match('/\s/', $_POST['prt_new_prt_name'])) - { + if (isset($_POST['prt_new_prt_name']) and $_POST['prt_new_prt_name'] != 'new_prt' and !preg_match('/\s/', $_POST['prt_new_prt_name'])) { //the prt name given is not used in this question $new_prt = new assStackQuestionPRT(-1, $this->object->getId()); $new_prt_node = new assStackQuestionPRTNode(-1, $this->object->getId(), ilUtil::stripSlashes($_POST['prt_new_prt_name']), '1', -1, -1); @@ -425,8 +405,7 @@ public function writeQuestionSpecificPostData() $this->object->getOptions()->setSpecificFeedback($specific_feedback); } - if (preg_match('/\s/', $_POST['prt_new_prt_name'])) - { + if (preg_match('/\s/', $_POST['prt_new_prt_name'])) { $this->question_gui->object->setErrors($this->object->getPlugin()->txt('error_not_valid_prt_name')); return FALSE; @@ -450,35 +429,29 @@ public function getPreview($show_question_only = FALSE, $showInlineFeedback = fa $tabs = $DIC->tabs(); //Get solutions if given - if (is_object($this->getPreviewSession())) { - $solutions = (array)$this->getPreviewSession()->getParticipantsSolution(); - } + if (is_object($this->getPreviewSession())) { + $solutions = (array)$this->getPreviewSession()->getParticipantsSolution(); + } //Include preview classes and set tab $this->plugin->includeClass("model/question_display/class.assStackQuestionPreview.php"); $this->plugin->includeClass("GUI/question_display/class.assStackQuestionPreviewGUI.php"); //Tab management - if ($_GET['cmd'] == 'edit') - { + if ($_GET['cmd'] == 'edit') { $tabs->setTabActive('edit_page'); - } elseif ($_GET['cmd'] == 'preview') - { + } elseif ($_GET['cmd'] == 'preview') { $tabs->setTabActive('preview'); } //Seed management - if (isset($_REQUEST['fixed_seed'])) - { + if (isset($_REQUEST['fixed_seed'])) { $seed = $_REQUEST['fixed_seed']; $_SESSION['q_seed_for_preview_' . $this->object->getId() . ''] = $seed; - } else - { - if (isset($_SESSION['q_seed_for_preview_' . $this->object->getId() . ''])) - { + } else { + if (isset($_SESSION['q_seed_for_preview_' . $this->object->getId() . ''])) { $seed = $_SESSION['q_seed_for_preview_' . $this->object->getId() . '']; - } else - { + } else { $seed = -1; } } @@ -487,10 +460,10 @@ public function getPreview($show_question_only = FALSE, $showInlineFeedback = fa $question_preview_object = new assStackQuestionPreview($this->plugin, $this->object, $seed, $solutions); $question_preview_data = $question_preview_object->getQuestionPreviewData(); - if(is_a($this->getPreviewSession(),"ilAssQuestionPreviewSession")){ - $this->getPreviewSession()->setParticipantsSolution($question_preview_data); - //$this->object->setPoints($question_preview_data["question_display"]["reached_points"]); - } + if (is_a($this->getPreviewSession(), "ilAssQuestionPreviewSession")) { + $this->getPreviewSession()->setParticipantsSolution($question_preview_data); + //$this->object->setPoints($question_preview_data["question_display"]["reached_points"]); + } //Get question preview GUI $question_preview_gui_object = new assStackQuestionPreviewGUI($this->plugin, $question_preview_data); @@ -506,16 +479,14 @@ public function getPreview($show_question_only = FALSE, $showInlineFeedback = fa //Include content Style $style_id = assStackQuestionUtils::_getActiveContentStyleId(); - if (strlen($style_id)) - { + if (strlen($style_id)) { require_once "./Services/Style/Content/classes/class.ilObjStyleSheet.php"; $tpl->addCss(ilObjStyleSheet::getContentStylePath((int)$style_id)); } $questionoutput = $question_preview_gui->get(); //Returns output (with page if needed) - if (!$show_question_only) - { + if (!$show_question_only) { // get page object output $questionoutput = $this->getILIASPage($questionoutput); } @@ -538,30 +509,24 @@ public function getTestOutput($active_id, $pass = NULL, $is_question_postponed = $solutions = NULL; // get the solution of the user for the active pass or from the last pass if allowed - if ($active_id) - { + if ($active_id) { require_once './Modules/Test/classes/class.ilObjTest.php'; - if (!ilObjTest::_getUsePreviousAnswers($active_id, true)) - { - if (is_null($pass)) - { + if (!ilObjTest::_getUsePreviousAnswers($active_id, true)) { + if (is_null($pass)) { $pass = ilObjTest::_getPass($active_id); } }# //If ILIAS 5.1 or 5.0 using intermediate - if (method_exists($this->object, "getUserSolutionPreferingIntermediate")) - { + if (method_exists($this->object, "getUserSolutionPreferingIntermediate")) { $solutions = $this->object->getUserSolutionPreferingIntermediate($active_id, $pass); - } else - { + } else { $solutions =& $this->object->getSolutionValues($active_id, $pass); } } //Create STACK Question object if doesn't exists - if (!is_a($this->object->getStackQuestion(), 'assStackQuestionStackQuestion')) - { + if (!is_a($this->object->getStackQuestion(), 'assStackQuestionStackQuestion')) { //Determine seed for current test run $seed = $this->object->getQuestionSeedForCurrentTestRun($active_id, $pass); @@ -599,8 +564,7 @@ public function getTestQuestionOutput($solutions, $show_specific_inline_feedback //Include content Style $style_id = assStackQuestionUtils::_getActiveContentStyleId(); - if (strlen($style_id)) - { + if (strlen($style_id)) { require_once "./Services/Style/Content/classes/class.ilObjStyleSheet.php"; $tpl->addCss(ilObjStyleSheet::getContentStylePath((int)$style_id)); } @@ -639,59 +603,49 @@ function getSolutionOutput($active_id, $pass = NULL, $graphicalOutput = FALSE, $ $this->active_id = $active_id; $this->pass = $pass; //Check for PASS - if ($active_id) - { + if ($active_id) { require_once './Modules/Test/classes/class.ilObjTest.php'; - if (!ilObjTest::_getUsePreviousAnswers($active_id, true)) - { - if (is_null($pass)) - { + if (!ilObjTest::_getUsePreviousAnswers($active_id, true)) { + if (is_null($pass)) { $pass = ilObjTest::_getPass($active_id); } } } //Is preview or Test - if (is_array($this->preview_mode)) - { + if (is_array($this->preview_mode)) { $solutions = $this->preview_mode["question_feedback"]; - } else - { + } else { //If ILIAS 5.1 or 5.0 using intermediate - if (method_exists($this->object, "getUserSolutionPreferingIntermediate")) - { + if (method_exists($this->object, "getUserSolutionPreferingIntermediate")) { $solutions = $this->object->getUserSolutionPreferingIntermediate($active_id, $pass); - } else - { + } else { $solutions =& $this->object->getSolutionValues($active_id, $pass); } } - if (($active_id > 0) && (!$show_correct_solution)) - { + if (($active_id > 0) && (!$show_correct_solution)) { //User Solution //Returns user solution HTML - //#25174 - if(isset($_GET["cmd"])){ - if($_GET["cmd"] == "outCorrectSolution"){ - $show_feedback = TRUE; - } - } + //#25174 + if (isset($_GET["cmd"])) { + if ($_GET["cmd"] == "outCorrectSolution") { + $show_feedback = TRUE; + } + } $solution_output = $this->getQuestionOutput($solutions, FALSE, $show_feedback, TRUE); //2.3.12 add feedback to solution $solution_output .= $this->getSpecificFeedbackOutput($solutions); - } else - { + } else { //Correct solution //Returns best solution HTML. $solution_output = $this->getQuestionOutput($solutions, TRUE, $show_feedback); } $question_text = $this->object->getQuestion(); - if ($show_question_text == true) - { + if ($show_question_text == true) { $solution_template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($question_text, TRUE)); } @@ -718,16 +672,14 @@ function getSolutionOutput($active_id, $pass = NULL, $graphicalOutput = FALSE, $ */ //2.4.0 Print view on test, just show the questions - if ($active_id == "" AND $pass == "" AND $_REQUEST["cmd"] == "print") - { + if ($active_id == "" and $pass == "" and $_REQUEST["cmd"] == "print") { return $this->getQuestionOutput($solutions, FALSE, $show_feedback); } $solution_template->setVariable("SOLUTION_OUTPUT", $solution_output); $solution_output = $solution_template->get(); - if (!$show_question_only) - { + if (!$show_question_only) { // get page object output $solution_output = $this->getILIASPage($solution_output); } @@ -744,44 +696,34 @@ function getSolutionOutput($active_id, $pass = NULL, $graphicalOutput = FALSE, $ */ public function getQuestionOutput($solutions, $best_solution, $show_feedback, $just_show = FALSE) { - if (isset($solutions["question_text"]) AND strlen($solutions["question_text"])) - { + if (isset($solutions["question_text"]) and strlen($solutions["question_text"])) { $question_text = $solutions["question_text"]; //Get Model answer from solutions and replace placeholders - if (isset($solutions["prt"])) - { - foreach ($solutions["prt"] as $prt_name => $prt) - { - if (isset($prt["response"])) - { - foreach ($prt["response"] as $input_name => $input_answer) - { + if (isset($solutions["prt"])) { + foreach ($solutions["prt"] as $prt_name => $prt) { + if (isset($prt["response"])) { + foreach ($prt["response"] as $input_name => $input_answer) { //Get input type for showing it properly $input = $this->object->getInputs($input_name); //Replace input depending on input type - switch ($input->getInputType()) - { + switch ($input->getInputType()) { case "dropdown": case "checkbox": case "radio": - if ($best_solution) - { + if ($best_solution) { $input_replacement = $input_answer["model_answer"]; $validation_replacement = $input_answer["model_answer_display"]; $question_text = str_replace("[[input:" . $input_name . "]]", $input_replacement, $question_text); $question_text = str_replace("[[validation:" . $input_name . "]]", $validation_replacement, $question_text); - } else - { - if ($just_show) - { + } else { + if ($just_show) { $input_replacement = "
" . $input_answer["display"]; $question_text = str_replace("[[validation:" . $input_name . "]]", "", $question_text); - } else - { + } else { $input_replacement = $input_answer["value"]; $question_text = str_replace("[[validation:" . $input_name . "]]", $this->object->getStackQuestion()->getInputs($input_name)->render_validation($this->object->getStackQuestion()->getInputState($input_name, $input_replacement), $input_name), $question_text); } @@ -791,28 +733,24 @@ public function getQuestionOutput($solutions, $best_solution, $show_feedback, $j break; case "matrix": //Select replace depending on mode if $best_solution is TRUE, best solution when FALSE user solution. - if ($best_solution) - { + if ($best_solution) { $input_replacement = $input_answer["model_answer"]; $validation_replacement = $input_answer["model_answer_display"]; $question_text = str_replace("[[input:" . $input_name . "]]", $input_replacement, $question_text); $question_text = str_replace("[[validation:" . $input_name . "]]", $validation_replacement, $question_text); - } else - { + } else { $input_replacement = $input_answer["display"]; } $question_text = str_replace("[[input:" . $input_name . "]]", $input_replacement, $question_text); break; case "textarea"; case "equiv"; - if ($best_solution) - { + if ($best_solution) { $input_replacement = $input_answer["model_answer"]; $validation_replacement = $input_answer["model_answer_display"]; $question_text = str_replace("[[input:" . $input_name . "]]", $input_replacement, $question_text); $question_text = str_replace("[[validation:" . $input_name . "]]", $validation_replacement, $question_text); - } else - { + } else { $input_replacement = ""; } $size = $input->getBoxSize(); @@ -821,22 +759,17 @@ public function getQuestionOutput($solutions, $best_solution, $show_feedback, $j $question_text = str_replace("[[input:" . $input_name . "]]", $input_text, $question_text); break; default: - if ($best_solution) - { + if ($best_solution) { $input_replacement = $input_answer["model_answer"]; $validation_replacement = $input_answer["model_answer_display"]; $question_text = str_replace("[[input:" . $input_name . "]]", $input_replacement, $question_text); $question_text = str_replace("[[validation:" . $input_name . "]]", $validation_replacement, $question_text); - } else - { + } else { $input_replacement = $input_answer["value"]; - if ($show_feedback) - { - if (strlen($input_answer["display"])) - { + if ($show_feedback) { + if (strlen($input_answer["display"])) { $validation_replacement = stack_string('studentValidation_yourLastAnswer', $input_answer["display"]); - } else - { + } else { $validation_replacement = $input_answer["display"]; } $question_text = str_replace("[[validation:" . $input_name . "]]", $validation_replacement, $question_text); @@ -850,8 +783,7 @@ public function getQuestionOutput($solutions, $best_solution, $show_feedback, $j //Replace feedback placeholder if required - if ($show_feedback) - { + if ($show_feedback) { $string = ""; //Generic feedback $string .= $prt["status"]["message"]; @@ -868,20 +800,17 @@ public function getQuestionOutput($solutions, $best_solution, $show_feedback, $j //Delete other place holders $question_text = preg_replace('/\[\[validation:(.*?)\]\]/', "", $question_text); - if (!$show_feedback) - { + if (!$show_feedback) { $question_text = preg_replace('/\[\[feedback:(.*?)\]\]/', "", $question_text); } - if ($best_solution) - { + if ($best_solution) { $question_text .= $solutions["general_feedback"]; } //Return the question text with LaTeX problems solved. return assStackQuestionUtils::_getLatex($question_text); - } else - { + } else { return ""; } } @@ -903,41 +832,31 @@ public function getSpecificFeedbackOutput($userSolution) $active_id = $this->active_id; $pass = $this->pass; - if ($active_id) - { + if ($active_id) { require_once './Modules/Test/classes/class.ilObjTest.php'; - if (!ilObjTest::_getUsePreviousAnswers($active_id, true)) - { - if (is_null($pass)) - { + if (!ilObjTest::_getUsePreviousAnswers($active_id, true)) { + if (is_null($pass)) { $pass = ilObjTest::_getPass($active_id); } } } //Is preview or Test - if (is_array($this->preview_mode)) - { + if (is_array($this->preview_mode)) { $solutions = $this->preview_mode["question_feedback"]; - } else - { + } else { //If ILIAS 5.1 or 5.0 using intermediate - if (method_exists($this->object, "getUserSolutionPreferingIntermediate")) - { + if (method_exists($this->object, "getUserSolutionPreferingIntermediate")) { $solutions = $this->object->getUserSolutionPreferingIntermediate($active_id, $pass); - } else - { + } else { $solutions =& $this->object->getSolutionValues($active_id, $pass); } } $specific_feedback = $this->object->getOptions()->getSpecificFeedback(); //Search for feedback placeholders in specific feedback text. - foreach ($this->object->getPotentialResponsesTrees() as $prt_name => $prt) - { - if (preg_match("[[feedback:" . $prt_name . "]]", $specific_feedback)) - { - if (isset($solutions["prt"][$prt_name])) - { + foreach ($this->object->getPotentialResponsesTrees() as $prt_name => $prt) { + if (preg_match("[[feedback:" . $prt_name . "]]", $specific_feedback)) { + if (isset($solutions["prt"][$prt_name])) { $string = ""; //feedback //Generic feedback @@ -947,8 +866,7 @@ public function getSpecificFeedbackOutput($userSolution) $string .= $solutions["prt"][$prt_name]["errors"]; $specific_feedback = str_replace("[[feedback:" . $prt_name . "]]", assStackQuestionUtils::_getFeedbackStyledText($string, "feedback_default"), $specific_feedback); - } else - { + } else { $specific_feedback = str_replace("[[feedback:" . $prt_name . "]]", $this->object->getPlugin()->txt("preview_no_answer"), $specific_feedback); } } @@ -993,17 +911,14 @@ public function setQuestionTabs() $q_type = $this->object->getQuestionType(); - if (strlen($q_type)) - { + if (strlen($q_type)) { $classname = $q_type . "GUI"; $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type); $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $_GET["q_id"]); } - if ($_GET["q_id"]) - { - if ($rbacsystem->checkAccess('write', $_GET["ref_id"])) - { + if ($_GET["q_id"]) { + if ($rbacsystem->checkAccess('write', $_GET["ref_id"])) { // edit page $tabs->addTarget("edit_page", $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "edit"), array("edit", "insert", "exec_pg"), "", "", ""); } @@ -1013,21 +928,16 @@ public function setQuestionTabs() } $force_active = false; - if ($rbacsystem->checkAccess('write', $_GET["ref_id"])) - { + if ($rbacsystem->checkAccess('write', $_GET["ref_id"])) { $url = ""; - if ($classname) - { + if ($classname) { $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion"); } $commands = $_POST["cmd"]; - if (is_array($commands)) - { - foreach ($commands as $key => $value) - { - if (preg_match("/^suggestrange_.*/", $key, $matches)) - { + if (is_array($commands)) { + foreach ($commands as $key => $value) { + if (preg_match("/^suggestrange_.*/", $key, $matches)) { $force_active = true; } } @@ -1037,8 +947,7 @@ public function setQuestionTabs() $this->addTab_QuestionFeedback($tabs); - if (in_array($_GET['cmd'], array('importQuestionFromMoodleForm', 'importQuestionFromMoodle', 'editQuestion', 'scoringManagement', 'scoringManagementPanel', 'deployedSeedsManagement', 'createNewDeployedSeed', 'deleteDeployedSeed', 'showUnitTests', 'runTestcases', 'createTestcases', 'post', 'exportQuestiontoMoodleForm', 'exportQuestionToMoodle',))) - { + if (in_array($_GET['cmd'], array('importQuestionFromMoodleForm', 'importQuestionFromMoodle', 'editQuestion', 'scoringManagement', 'scoringManagementPanel', 'deployedSeedsManagement', 'createNewDeployedSeed', 'deleteDeployedSeed', 'showUnitTests', 'runTestcases', 'createTestcases', 'post', 'exportQuestiontoMoodleForm', 'exportQuestionToMoodle',))) { $tabs->addSubTab('edit_question', $this->plugin->txt('edit_question'), $this->ctrl->getLinkTargetByClass($classname, "editQuestion")); $tabs->addSubTab('scoring_management', $this->plugin->txt('scoring_management'), $this->ctrl->getLinkTargetByClass($classname, "scoringManagementPanel")); $tabs->addSubTab('deployed_seeds_management', $this->plugin->txt('dsm_deployed_seeds'), $this->ctrl->getLinkTargetByClass($classname, "deployedSeedsManagement")); @@ -1050,21 +959,17 @@ public function setQuestionTabs() } // Assessment of questions sub menu entry - if ($_GET["q_id"]) - { + if ($_GET["q_id"]) { $tabs->addTarget("statistics", $this->ctrl->getLinkTargetByClass($classname, "assessment"), array("assessment"), $classname, ""); } - if (($_GET["calling_test"] > 0) || ($_GET["test_ref_id"] > 0)) - { + if (($_GET["calling_test"] > 0) || ($_GET["test_ref_id"] > 0)) { $ref_id = $_GET["calling_test"]; - if (strlen($ref_id) == 0) - { + if (strlen($ref_id) == 0) { $ref_id = $_GET["test_ref_id"]; } $tabs->setBackTarget($this->lng->txt("backtocallingtest"), "ilias.php?baseClass=ilObjTestGUI&cmd=questions&ref_id=$ref_id"); - } else - { + } else { $tabs->setBackTarget($this->lng->txt("qpl"), $this->ctrl->getLinkTargetByClass("ilobjquestionpoolgui", "questions")); } @@ -1085,8 +990,7 @@ public function editQuestionForm() { global $DIC; - if ($this->object->getSelfAssessmentEditingMode()) - { + if ($this->object->getSelfAssessmentEditingMode()) { $this->getLearningModuleTabs(); } @@ -1113,11 +1017,9 @@ public function editQuestionForm() $this->info_config->ajax_url = $ctrl->getLinkTargetByClass("assstackquestiongui", "saveInfoState", "", TRUE); //Set to user's session value - if (isset($_SESSION['stack_authoring_show'])) - { + if (isset($_SESSION['stack_authoring_show'])) { $this->info_config->show = (int)$_SESSION['stack_authoring_show']; - } else - { + } else { //first time must be shown $this->info_config->show = 1; } @@ -1152,17 +1054,13 @@ public function editQuestion($checkonly = FALSE) public function enableDisableInfo() { - if (isset($_SESSION['show_input_info_fields_in_form'])) - { - if ($_SESSION['show_input_info_fields_in_form'] == TRUE) - { + if (isset($_SESSION['show_input_info_fields_in_form'])) { + if ($_SESSION['show_input_info_fields_in_form'] == TRUE) { $_SESSION['show_input_info_fields_in_form'] = FALSE; - } else - { + } else { $_SESSION['show_input_info_fields_in_form'] = TRUE; } - } else - { + } else { $_SESSION['show_input_info_fields_in_form'] = TRUE; } @@ -1178,8 +1076,7 @@ public function deployedSeedsManagement() global $DIC; $tabs = $DIC->tabs(); - if ($this->object->getSelfAssessmentEditingMode()) - { + if ($this->object->getSelfAssessmentEditingMode()) { $this->getLearningModuleTabs(); } //Set all parameters required @@ -1218,8 +1115,7 @@ public function createNewDeployedSeed() $this->plugin->includeClass('model/ilias_object/class.assStackQuestionDeployedSeed.php'); $deployed_seed = new assStackQuestionDeployedSeed('', $question_id, $seed); - if (!$deployed_seed->save()) - { + if (!$deployed_seed->save()) { $this->question_gui->object->setErrors($this->plugin->txt('dsm_not_allowed_seed')); } @@ -1241,10 +1137,8 @@ public function deleteDeployedSeed() $this->plugin->includeClass('model/ilias_object/class.assStackQuestionDeployedSeed.php'); $deployed_seeds = assStackQuestionDeployedSeed::_read($question_id); - foreach ($deployed_seeds as $deployed_seed) - { - if ($deployed_seed->getSeed() == $seed) - { + foreach ($deployed_seeds as $deployed_seed) { + if ($deployed_seed->getSeed() == $seed) { $deployed_seed->delete(); ilUtil::sendSuccess($this->plugin->txt('dsm_deployed_seed_deleted')); break; @@ -1268,8 +1162,7 @@ public function scoringManagementPanel($new_question_points = '') { global $DIC; $tabs = $DIC->tabs(); - if ($this->object->getSelfAssessmentEditingMode()) - { + if ($this->object->getSelfAssessmentEditingMode()) { $this->getLearningModuleTabs(); } //Set all parameters required @@ -1295,11 +1188,9 @@ public function scoringManagementPanel($new_question_points = '') public function showScoringComparison() { //Get new points value - if (isset($_POST['new_scoring']) AND (float)$_POST['new_scoring'] > 0.0) - { + if (isset($_POST['new_scoring']) and (float)$_POST['new_scoring'] > 0.0) { $new_question_points = (float)ilUtil::stripSlashes($_POST['new_scoring']); - } else - { + } else { $this->question_gui->object->setErrors($this->plugin->txt('sco_invalid_value')); } //Show scoring panel with comparison @@ -1313,12 +1204,10 @@ public function showScoringComparison() public function saveNewScoring() { //Get new points value and save it to the DB - if (isset($_POST['new_scoring']) AND (float)$_POST['new_scoring'] > 0.0) - { + if (isset($_POST['new_scoring']) and (float)$_POST['new_scoring'] > 0.0) { $this->object->setPoints(ilUtil::stripSlashes($_POST['new_scoring'])); $this->object->saveQuestionDataToDb($this->object->getId()); - } else - { + } else { $this->question_gui->object->setErrors($this->plugin->txt('sco_invalid_value')); } //Show scoring panel @@ -1336,8 +1225,7 @@ public function showUnitTests() { global $DIC; $tabs = $DIC->tabs(); - if ($this->object->getSelfAssessmentEditingMode()) - { + if ($this->object->getSelfAssessmentEditingMode()) { $this->getLearningModuleTabs(); } @@ -1376,25 +1264,20 @@ public function runTestcases() $this->getQuestionTemplate(); //get Post vars - if (isset($_POST['test_id'])) - { + if (isset($_POST['test_id'])) { $test_id = $_POST['test_id']; } - if (isset($_POST['question_id'])) - { + if (isset($_POST['question_id'])) { $question_id = $_POST['question_id']; } - if (isset($_POST['testcase_name'])) - { + if (isset($_POST['testcase_name'])) { $testcase_name = $_POST['testcase_name']; - } else - { + } else { $testcase_name = FALSE; } //Create STACK Question object if doesn't exists - if (!is_a($this->object->getStackQuestion(), 'assStackQuestionStackQuestion')) - { + if (!is_a($this->object->getStackQuestion(), 'assStackQuestionStackQuestion')) { $this->plugin->includeClass("model/class.assStackQuestionStackQuestion.php"); $this->object->setStackQuestion(new assStackQuestionStackQuestion()); $this->object->getStackQuestion()->init($this->object); @@ -1431,19 +1314,15 @@ public function editTestcases() $this->getQuestionTemplate(); //get Post vars - if (isset($_POST['test_id'])) - { + if (isset($_POST['test_id'])) { $test_id = $_POST['test_id']; } - if (isset($_POST['question_id'])) - { + if (isset($_POST['question_id'])) { $question_id = $_POST['question_id']; } - if (isset($_POST['testcase_name'])) - { + if (isset($_POST['testcase_name'])) { $testcase_name = $_POST['testcase_name']; - } else - { + } else { $testcase_name = FALSE; } @@ -1467,27 +1346,20 @@ public function editTestcases() */ public function doEditTestcase() { - if (isset($_POST['testcase_name'])) - { + if (isset($_POST['testcase_name'])) { $testcase_name = $_POST['testcase_name']; $test = $this->object->getTests($testcase_name); - } else - { + } else { $testcase_name = FALSE; } - if (is_a($test, 'assStackQuestionTest')) - { + if (is_a($test, 'assStackQuestionTest')) { //Creation of inputs - foreach ($this->object->getInputs() as $input_name => $q_input) - { + foreach ($this->object->getInputs() as $input_name => $q_input) { $exists = FALSE; - foreach ($test->getTestInputs() as $input) - { - if ($input->getTestInputName() == $input_name) - { - if (isset($_REQUEST[$input->getTestInputName()])) - { + foreach ($test->getTestInputs() as $input) { + if ($input->getTestInputName() == $input_name) { + if (isset($_REQUEST[$input->getTestInputName()])) { $input->setTestInputValue($_REQUEST[$input->getTestInputName()]); $input->checkTestInput(); $input->save(); @@ -1497,8 +1369,7 @@ public function doEditTestcase() } //Correct current mistakes - if (!$exists) - { + if (!$exists) { $new_test_input = new assStackQuestionTestInput(-1, $this->object->getId(), $testcase_name); $new_test_input->setTestInputName($input_name); $new_test_input->setTestInputValue(""); @@ -1508,18 +1379,14 @@ public function doEditTestcase() //Creation of expected results - foreach ($test->getTestExpected() as $index => $prt) - { - if (isset($_REQUEST['score_' . $prt->getTestPRTName()])) - { + foreach ($test->getTestExpected() as $index => $prt) { + if (isset($_REQUEST['score_' . $prt->getTestPRTName()])) { $prt->setExpectedScore(ilUtil::stripSlashes($_REQUEST['score_' . $prt->getTestPRTName()])); } - if (isset($_REQUEST['penalty_' . $prt->getTestPRTName()])) - { + if (isset($_REQUEST['penalty_' . $prt->getTestPRTName()])) { $prt->setExpectedPenalty(ilUtil::stripSlashes($_REQUEST['penalty_' . $prt->getTestPRTName()])); } - if (isset($_REQUEST['answernote_' . $prt->getTestPRTName()])) - { + if (isset($_REQUEST['answernote_' . $prt->getTestPRTName()])) { $prt->setExpectedAnswerNote(ilUtil::stripSlashes($_REQUEST['answernote_' . $prt->getTestPRTName()])); } $prt->checkTestExpected(); @@ -1565,16 +1432,13 @@ public function doCreateTestcase() $new_test = new assStackQuestionTest(-1, $this->object->getId(), $testcase); //Creation of inputs - foreach ($this->object->getInputs() as $input_name => $input) - { + foreach ($this->object->getInputs() as $input_name => $input) { $new_test_input = new assStackQuestionTestInput(-1, $this->object->getId(), $testcase); $new_test_input->setTestInputName($input_name); - if (isset($_REQUEST[$input_name])) - { + if (isset($_REQUEST[$input_name])) { $new_test_input->setTestInputValue(ilUtil::stripSlashes($_REQUEST[$input_name])); - } else - { + } else { $new_test_input->setTestInputValue(""); } @@ -1583,32 +1447,25 @@ public function doCreateTestcase() } //Creation of expected results - foreach ($this->object->getPotentialResponsesTrees() as $prt_name => $prt) - { + foreach ($this->object->getPotentialResponsesTrees() as $prt_name => $prt) { //Getting the PRT name $new_test_expected = new assStackQuestionTestExpected(-1, $this->object->getId(), $testcase, $prt_name); - if (isset($_REQUEST['score_' . $prt_name])) - { + if (isset($_REQUEST['score_' . $prt_name])) { $new_test_expected->setExpectedScore(ilUtil::stripSlashes($_REQUEST['score_' . $prt_name])); - } else - { + } else { $new_test_expected->setExpectedScore(""); } - if (isset($_REQUEST['penalty_' . $prt_name])) - { + if (isset($_REQUEST['penalty_' . $prt_name])) { $new_test_expected->setExpectedPenalty(ilUtil::stripSlashes($_REQUEST['penalty_' . $prt_name])); - } else - { + } else { $new_test_expected->setExpectedPenalty(""); } - if (isset($_REQUEST['answernote_' . $prt_name])) - { + if (isset($_REQUEST['answernote_' . $prt_name])) { $new_test_expected->setExpectedAnswerNote(ilUtil::stripSlashes($_REQUEST['answernote_' . $prt_name])); - } else - { + } else { $new_test_expected->setExpectedAnswerNote(""); } $new_test_expected->save(); @@ -1628,19 +1485,15 @@ public function doCreateTestcase() public function doDeleteTestcase() { //get Post vars - if (isset($_POST['test_id'])) - { + if (isset($_POST['test_id'])) { $test_id = $_POST['test_id']; } - if (isset($_POST['question_id'])) - { + if (isset($_POST['question_id'])) { $question_id = $_POST['question_id']; } - if (isset($_POST['testcase_name'])) - { + if (isset($_POST['testcase_name'])) { $testcase_name = $_POST['testcase_name']; - } else - { + } else { $testcase_name = FALSE; } @@ -1663,14 +1516,12 @@ public function importQuestionFromMoodleForm() $tabs = $DIC->tabs(); //#25145 - if (isset($_REQUEST["test_ref_id"])) - { + if (isset($_REQUEST["test_ref_id"])) { ilUtil::sendFailure($lng->txt("qpl_qst_xqcas_import_in_test_error"), TRUE); $DIC->ctrl()->redirect($this, 'editQuestion'); } - if ($this->object->getSelfAssessmentEditingMode()) - { + if ($this->object->getSelfAssessmentEditingMode()) { $this->getLearningModuleTabs(); } //Set all parameters required @@ -1708,24 +1559,20 @@ public function importQuestionFromMoodle() $tabs->activateSubTab('import_from_moodle'); //Getting the xml file from $_FILES - if (file_exists($_FILES["questions_xml"]["tmp_name"])) - { + if (file_exists($_FILES["questions_xml"]["tmp_name"])) { $xml_file = $_FILES["questions_xml"]["tmp_name"]; - } else - { + } else { $this->object->setErrors($this->plugin->txt('error_import_question_in_test'), true); return; } //CHECK FOR NOT ALLOW IMPROT QUESTIONS DIRECTLY IN TESTS - if (isset($_GET['calling_test'])) - { + if (isset($_GET['calling_test'])) { $this->object->setErrors($this->plugin->txt('error_import_question_in_test'), true); return; - } else - { + } else { //Include import class and prepare object $this->plugin->includeClass('model/import/MoodleXML/class.assStackQuestionMoodleImport.php'); $import = new assStackQuestionMoodleImport($this->plugin, (int)$_POST['first_question_id'], $this->object); @@ -1752,22 +1599,18 @@ public function exportQuestiontoMoodleForm() $options = new ilRadioGroupInputGUI($lng->txt("qpl_qst_xqcas_all_from_pool"), "xqcas_all_from_pool"); $only_question = new ilRadioOption($lng->txt("qpl_qst_xqcas_export_only_this"), "xqcas_export_only_this", $lng->txt("qpl_qst_xqcas_export_only_this_info")); - if (isset($_GET['calling_test'])) - { + if (isset($_GET['calling_test'])) { $all_from_pool = new ilRadioOption($lng->txt("qpl_qst_xqcas_export_all_from_test"), "xqcas_export_all_from_test", $lng->txt("qpl_qst_xqcas_export_all_from_test_info")); - } else - { + } else { $all_from_pool = new ilRadioOption($lng->txt("qpl_qst_xqcas_export_all_from_pool"), "xqcas_export_all_from_pool", $lng->txt("qpl_qst_xqcas_export_all_from_pool_info")); } $options->addOption($only_question); $options->addOption($all_from_pool); - if (isset($_GET['calling_test'])) - { + if (isset($_GET['calling_test'])) { $options->setValue("xqcas_export_all_from_test"); - } else - { + } else { $options->setValue("xqcas_export_all_from_pool"); } @@ -1796,31 +1639,25 @@ public function exportQuestionToMoodle() $tabs->activateSubTab('export_to_moodle'); //Getting data from POST - if (isset($_POST['first_question_id']) AND isset($_POST['xqcas_all_from_pool'])) - { + if (isset($_POST['first_question_id']) and isset($_POST['xqcas_all_from_pool'])) { $id = $_POST['first_question_id']; $mode = ""; - if ($_POST['xqcas_all_from_pool'] == 'xqcas_export_all_from_pool') - { + if ($_POST['xqcas_all_from_pool'] == 'xqcas_export_all_from_pool') { //Get all questions from a pool $export_to_moodle = new assStackQuestionMoodleXMLExport($this->object->getAllQuestionsFromPool()); $xml = $export_to_moodle->toMoodleXML(); - } elseif ($_POST['xqcas_all_from_pool'] == 'xqcas_export_only_this') - { + } elseif ($_POST['xqcas_all_from_pool'] == 'xqcas_export_only_this') { //get current stack question info. $export_to_moodle = new assStackQuestionMoodleXMLExport(array($id => $this->object)); $xml = $export_to_moodle->toMoodleXML(); - } elseif ($_POST['xqcas_all_from_pool'] == 'xqcas_export_all_from_test') - { + } elseif ($_POST['xqcas_all_from_pool'] == 'xqcas_export_all_from_test') { //get current stack question info. $export_to_moodle = new assStackQuestionMoodleXMLExport($this->object->getAllQuestionsFromTest()); $xml = $export_to_moodle->toMoodleXML(); - } else - { + } else { throw new Exception($lng->txt('qpl_qst_xqcas_error_exporting_to_moodle_mode')); } - } else - { + } else { throw new Exception($lng->txt('qpl_qst_xqcas_error_exporting_to_moodle_question_id')); } } @@ -1856,10 +1693,8 @@ public function getErrors() //Check all inputs have a model answer $incomplete_model_answers = ""; - foreach ($this->object->getInputs() as $input_name => $input) - { - if ($input->getTeacherAnswer() == "" OR $input->getTeacherAnswer() == " ") - { + foreach ($this->object->getInputs() as $input_name => $input) { + if ($input->getTeacherAnswer() == "" or $input->getTeacherAnswer() == " ") { $isComplete = FALSE; $incomplete_model_answers .= $input_name . ", "; } @@ -1868,12 +1703,9 @@ public function getErrors() //Check student answer is always filled in $incomplete_student_answers = ""; - foreach ($this->object->getPotentialResponsesTrees() as $prt_name => $prt) - { - foreach ($prt->getPRTNodes() as $node_name => $node) - { - if ($node->getStudentAnswer() == "" OR $node->getStudentAnswer() == " ") - { + foreach ($this->object->getPotentialResponsesTrees() as $prt_name => $prt) { + foreach ($prt->getPRTNodes() as $node_name => $node) { + if ($node->getStudentAnswer() == "" or $node->getStudentAnswer() == " ") { $isComplete = FALSE; $incomplete_student_answers .= $prt_name . " / " . $node_name . ", "; } @@ -1883,12 +1715,9 @@ public function getErrors() //Check teacher answer is always filled in $incomplete_teacher_answers = ""; - foreach ($this->object->getPotentialResponsesTrees() as $prt_name => $prt) - { - foreach ($prt->getPRTNodes() as $node_name => $node) - { - if ($node->getTeacherAnswer() == "" OR $node->getTeacherAnswer() == " ") - { + foreach ($this->object->getPotentialResponsesTrees() as $prt_name => $prt) { + foreach ($prt->getPRTNodes() as $node_name => $node) { + if ($node->getTeacherAnswer() == "" or $node->getTeacherAnswer() == " ") { $isComplete = FALSE; $incomplete_teacher_answers .= $prt_name . " / " . $node_name . ", "; } @@ -1896,18 +1725,14 @@ public function getErrors() } $incomplete_teacher_answers = substr($incomplete_teacher_answers, 0, -2); - if (!$isComplete AND $this->object->getTitle() != NULL) - { - if ($incomplete_model_answers != "") - { + if (!$isComplete and $this->object->getTitle() != NULL) { + if ($incomplete_model_answers != "") { $this->object->setErrors($this->getPlugin()->txt("error_model_answer_missing") . " " . $incomplete_model_answers); } - if ($incomplete_student_answers != "") - { + if ($incomplete_student_answers != "") { $this->object->setErrors($this->getPlugin()->txt("error_student_answer_missing") . " " . $incomplete_student_answers); } - if ($incomplete_teacher_answers != "") - { + if ($incomplete_teacher_answers != "") { $this->object->setErrors($this->getPlugin()->txt("error_teacher_answer_missing") . " " . $incomplete_teacher_answers); } } @@ -1940,8 +1765,7 @@ public function getLearningModuleTabs() $q_type = $this->object->getQuestionType(); - if (strlen($q_type)) - { + if (strlen($q_type)) { $classname = $q_type . "GUI"; $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type); $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $this->object->getId()); @@ -1950,17 +1774,13 @@ public function getLearningModuleTabs() $force_active = false; $url = ""; - if ($classname) - { + if ($classname) { $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion"); } $commands = $_POST["cmd"]; - if (is_array($commands)) - { - foreach ($commands as $key => $value) - { - if (preg_match("/^suggestrange_.*/", $key, $matches)) - { + if (is_array($commands)) { + foreach ($commands as $key => $value) { + if (preg_match("/^suggestrange_.*/", $key, $matches)) { $force_active = true; } } @@ -1968,8 +1788,7 @@ public function getLearningModuleTabs() // edit question properties $tabs->addTarget("edit_properties", $url, array("editQuestion", "save", "cancel", "addSuggestedSolution", "cancelExplorer", "linkChilds", "removeSuggestedSolution", "parseQuestion", "saveEdit", "suggestRange"), $classname, "", $force_active); - if (in_array($_GET['cmd'], array('importQuestionFromMoodleForm', 'importQuestionFromMoodle', 'editQuestion', 'scoringManagement', 'scoringManagementPanel', 'deployedSeedsManagement', 'createNewDeployedSeed', 'deleteDeployedSeed', 'showUnitTests', 'runTestcases', 'createTestcases', 'post', 'exportQuestiontoMoodleForm', 'exportQuestionToMoodle',))) - { + if (in_array($_GET['cmd'], array('importQuestionFromMoodleForm', 'importQuestionFromMoodle', 'editQuestion', 'scoringManagement', 'scoringManagementPanel', 'deployedSeedsManagement', 'createNewDeployedSeed', 'deleteDeployedSeed', 'showUnitTests', 'runTestcases', 'createTestcases', 'post', 'exportQuestiontoMoodleForm', 'exportQuestionToMoodle',))) { $tabs->addSubTab('edit_question', $this->plugin->txt('edit_question'), $this->ctrl->getLinkTargetByClass($classname, "editQuestion")); $tabs->addSubTab('scoring_management', $this->plugin->txt('scoring_management'), $this->ctrl->getLinkTargetByClass($classname, "scoringManagementPanel")); $tabs->addSubTab('deployed_seeds_management', $this->plugin->txt('dsm_deployed_seeds'), $this->ctrl->getLinkTargetByClass($classname, "deployedSeedsManagement")); diff --git a/classes/model/question_display/class.assStackQuestionDisplay.php b/classes/model/question_display/class.assStackQuestionDisplay.php index 59ca5837..e804eb2f 100644 --- a/classes/model/question_display/class.assStackQuestionDisplay.php +++ b/classes/model/question_display/class.assStackQuestionDisplay.php @@ -210,8 +210,6 @@ private function replacementForInputPlaceholders($input, $input_name, $in_test, /** * Replace validation placeholders by validation button. - * This is different thatn STACK because at the moment instant validtaion is not - * supported by STACK Questionestion plugin. * @param stack_input $input * @param string $input_name */ @@ -476,8 +474,10 @@ public function replacementForValidationInput($input, $input_name, $in_test, $re $validation_message = stack_string('studentValidation_yourLastAnswer', $input_state->contentsdisplayed); -#25225 add validation div wrapping + #25225 add validation div wrapping $validation_div = '
'; + #27830 + $validation_div .= $user_matrix. $validation_message; return $validation_div; } if (is_a($input, "stack_checkbox_input")) { diff --git a/classes/stack/answertest/at_general_cas.class.php b/classes/stack/answertest/at_general_cas.class.php index e576f667..ae3d5111 100644 --- a/classes/stack/answertest/at_general_cas.class.php +++ b/classes/stack/answertest/at_general_cas.class.php @@ -154,7 +154,8 @@ public function do_test() { $session = new stack_cas_session($cts, $this->options, 0); $session->instantiate(); $this->debuginfo = $session->get_debuginfo(); - if ('' != $session->get_errors_key('STACKSA')) { + + if ('' != $session->get_errors_key('STACKSA')) { $this->aterror = 'TEST_FAILED'; $this->atfeedback = stack_string('TEST_FAILED', array('errors' => $session->get_errors_key('STACKSA'))); $this->atansnote = $this->casfunction.'_STACKERROR_SAns.'; @@ -184,13 +185,14 @@ public function do_test() { } $sessionvars = $session->get_session(); - if (!$this->processcasoptions || trim($op) === '' ) { + + if (!$this->processcasoptions || trim($op) === '' ) { $result = $sessionvars[3]; } else { $result = $sessionvars[4]; } - if ('' != $result->get_errors()) { + if ('' != $result->get_errors()) { $this->aterror = 'TEST_FAILED'; if ('' != trim($result->get_feedback())) { $this->atfeedback = $result->get_feedback(); diff --git a/classes/stack/cas/cassession.class.php b/classes/stack/cas/cassession.class.php index 12c52948..6905d56d 100644 --- a/classes/stack/cas/cassession.class.php +++ b/classes/stack/cas/cassession.class.php @@ -200,6 +200,7 @@ public function instantiate() { } if (array_key_exists('value', $result)) { + $val = str_replace('QMCHAR', '?', $result['value']); $cs->set_value($val); $gotvalue = true; diff --git a/classes/stack/input/checkbox/checkbox.class.php b/classes/stack/input/checkbox/checkbox.class.php index 78cebe4d..25fc6492 100644 --- a/classes/stack/input/checkbox/checkbox.class.php +++ b/classes/stack/input/checkbox/checkbox.class.php @@ -55,7 +55,8 @@ public function contents_to_maxima($contents) { public function render(stack_input_state $state, $fieldname, $readonly, $tavalue) { if ($this->errors) { - return $this->render_error($this->errors); + //fau: hide this to solve bug 24199 + //return $this->render_error($this->errors); } // Create html. diff --git a/classes/stack/input/dropdown/dropdown.class.php b/classes/stack/input/dropdown/dropdown.class.php index f35a8471..33499714 100644 --- a/classes/stack/input/dropdown/dropdown.class.php +++ b/classes/stack/input/dropdown/dropdown.class.php @@ -347,7 +347,8 @@ public function get_choices() { public function render(stack_input_state $state, $fieldname, $readonly, $tavalue) { if ($this->errors) { - return $this->render_error($this->errors); + //fau: hide this to solve bug 24199 + //return $this->render_error($this->errors); } // Create html. diff --git a/classes/stack/input/radio/radio.class.php b/classes/stack/input/radio/radio.class.php index b5f7ed67..ee9cf4a9 100644 --- a/classes/stack/input/radio/radio.class.php +++ b/classes/stack/input/radio/radio.class.php @@ -35,7 +35,8 @@ class stack_radio_input extends stack_dropdown_input { public function render(stack_input_state $state, $fieldname, $readonly, $tavalue) { if ($this->errors) { - return $this->render_error($this->errors); + //fau: hide this to solve bug 24199 + //return $this->render_error($this->errors); } // Create html. diff --git a/lang/stack_de.php b/lang/stack_de.php index 7af554a0..f4ee68cb 100644 --- a/lang/stack_de.php +++ b/lang/stack_de.php @@ -1137,3 +1137,4 @@ //Solve thttps://mantis.ilias.de/view.php?id=24003 $string['stackCas_unencpsulated_comma'] = 'In dem eingegebenen Ausdruck erscheint ein Komma an ungewöhnlicher Stelle. Kommas werden zur Trennung von Elementen in Listen, Mengen usw. verwendet. Bitte verwenden Sie in Dezimalzahlen anstelle eines Kommas einen Dezimalpunkt.'; +$string['Variable_function'] = 'Folgendes erscheint in Ihrem Ausdruck sowohl als Variable als auch als Funktion: {$ a-> m0}. Bitte klären Sie Ihre Eingabe. Fügen Sie entweder * -Symbole ein, um Funktionen zu entfernen, oder machen Sie alle Vorkommensfunktionen.'; diff --git a/plugin.php b/plugin.php index 2c2ca0b2..34f7f813 100644 --- a/plugin.php +++ b/plugin.php @@ -9,7 +9,7 @@ // code version; must be changed for all code changes -$version = "3.1.9"; +$version = "3.1.10"; // ilias min and max version; must always reflect the versions that should // run with the plugin From 7b5df418b07e11794bda94c543a843ce9ecf89e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Copado?= Date: Fri, 13 Nov 2020 17:19:16 +0100 Subject: [PATCH 23/23] 3.1.11 --- README.md | 6 ++++++ classes/class.assStackQuestionGUI.php | 14 +++++++++++++- .../class.assStackQuestionDisplay.php | 7 ++++++- plugin.php | 2 +- 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9ad46ae8..a20cd5dd 100644 --- a/README.md +++ b/README.md @@ -142,3 +142,9 @@ The following bugs have been solved: - 24199 about dropdown field dissapearing if answered but other prt related inputs are not answered. - 27560 about inputs not properly deleted. - 25256 about specific feedback not shown in test results. + +Version 3.1.11 (2020-11-13) for ILIAS 6 +---------------------------------------- +The following bugs have been solved: +- 25938 firstline option not appearing the first line of the teacher answer as hint in equivalence reasoning inputs. +- 24273 In test results, user solutions for Matrix inputs now appears like the rest of the inputs and not as LaTeX entry. \ No newline at end of file diff --git a/classes/class.assStackQuestionGUI.php b/classes/class.assStackQuestionGUI.php index 89c31868..736e1100 100644 --- a/classes/class.assStackQuestionGUI.php +++ b/classes/class.assStackQuestionGUI.php @@ -739,7 +739,19 @@ public function getQuestionOutput($solutions, $best_solution, $show_feedback, $j $question_text = str_replace("[[input:" . $input_name . "]]", $input_replacement, $question_text); $question_text = str_replace("[[validation:" . $input_name . "]]", $validation_replacement, $question_text); } else { - $input_replacement = $input_answer["display"]; + //#24273 + //Create STACK Question object if doesn't exists + if (!is_a($this->object->getStackQuestion(), 'assStackQuestionStackQuestion')) { + $this->plugin->includeClass("model/class.assStackQuestionStackQuestion.php"); + $this->object->setStackQuestion(new assStackQuestionStackQuestion()); + $this->object->getStackQuestion()->init($this->object); + } + $stack_matrix = $this->object->getStackQuestion()->getInputs($input_name); + $stack_matrix_response = $stack_matrix->maxima_to_response_array($input_answer["value"]); + $matrix_state = $this->object->getStackQuestion()->getInputState($input_name,$stack_matrix_response); + $input_replacement = $stack_matrix->render($matrix_state,$input_name."_user_solution",TRUE,$stack_matrix_response); + $question_text = str_replace("[[input:" . $input_name . "]]", $input_replacement, $question_text); + //#24273 } $question_text = str_replace("[[input:" . $input_name . "]]", $input_replacement, $question_text); break; diff --git a/classes/model/question_display/class.assStackQuestionDisplay.php b/classes/model/question_display/class.assStackQuestionDisplay.php index e804eb2f..7c82de3f 100644 --- a/classes/model/question_display/class.assStackQuestionDisplay.php +++ b/classes/model/question_display/class.assStackQuestionDisplay.php @@ -188,7 +188,12 @@ private function replacementForInputPlaceholders($input, $input_name, $in_test, return $state->contentsdisplayed; } //Get teacher answer value for equivalence reasoning input firstline problem #22847 - $ta_value = $this->getQuestion()->getSession()->get_value_key($input->get_teacher_answer()); + //Modified to solve 25938 if else + if(is_a($input,"stack_equiv_input")){ + $ta_value = $this->getQuestion()->getSession()->get_value_key("ta"); + }else{ + $ta_value = $this->getQuestion()->getSession()->get_value_key($input->get_teacher_answer()); + } //Return renderised input if (get_class($input) == 'stack_algebraic_input') { diff --git a/plugin.php b/plugin.php index 34f7f813..8232c533 100644 --- a/plugin.php +++ b/plugin.php @@ -9,7 +9,7 @@ // code version; must be changed for all code changes -$version = "3.1.10"; +$version = "3.1.11"; // ilias min and max version; must always reflect the versions that should // run with the plugin