From 7f5464d5bf2fd9532d1e24969df320462592c418 Mon Sep 17 00:00:00 2001 From: Vadim Dvorovenko Date: Wed, 11 May 2016 20:36:16 +0700 Subject: [PATCH] MDL-79863 qtype_ordering: phpdoc fix --- question/type/ordering/backup/moodle1/lib.php | 10 +- .../restore_qtype_ordering_plugin.class.php | 7 +- question/type/ordering/db/upgrade.php | 25 +- question/type/ordering/edit_ordering_form.php | 71 ++++-- question/type/ordering/lib.php | 12 +- question/type/ordering/question.php | 233 +++++++++++++++++- question/type/ordering/questiontype.php | 130 +++++++--- question/type/ordering/renderer.php | 51 +++- 8 files changed, 458 insertions(+), 81 deletions(-) diff --git a/question/type/ordering/backup/moodle1/lib.php b/question/type/ordering/backup/moodle1/lib.php index 5ba15c66a60..591b4bf0c1c 100644 --- a/question/type/ordering/backup/moodle1/lib.php +++ b/question/type/ordering/backup/moodle1/lib.php @@ -33,7 +33,10 @@ defined('MOODLE_INTERNAL') || die(); class moodle1_qtype_ordering_handler extends moodle1_qtype_handler { /** - * @return array + * Returns the list of paths within one that this qtype needs to have included + * in the grouped question structure + * + * @return array of strings */ public function get_question_subpaths() { return array( @@ -43,7 +46,10 @@ class moodle1_qtype_ordering_handler extends moodle1_qtype_handler { } /** - * Appends the ordering specific information to the question + * Gives the qtype handler a chance to write converted data into questions.xml + * + * @param array $data grouped question data + * @param array $raw grouped raw QUESTION data */ public function process_question(array $data, array $raw) { diff --git a/question/type/ordering/backup/moodle2/restore_qtype_ordering_plugin.class.php b/question/type/ordering/backup/moodle2/restore_qtype_ordering_plugin.class.php index 945266f3771..ae0fc224913 100644 --- a/question/type/ordering/backup/moodle2/restore_qtype_ordering_plugin.class.php +++ b/question/type/ordering/backup/moodle2/restore_qtype_ordering_plugin.class.php @@ -52,6 +52,8 @@ class restore_qtype_ordering_plugin extends restore_qtype_plugin { /** * Process the qtype/ordering element + * + * @param array $data */ public function process_ordering($data) { global $DB; @@ -76,9 +78,10 @@ class restore_qtype_ordering_plugin extends restore_qtype_plugin { /** * Given one question_states record, return the answer - * recoded pointing to all the restored stuff for ordering questions + * recoded pointing to all the restored stuff for ordering questions. + * If not empty, answer is one question_answers->id. * - * if not empty, answer is one question_answers->id + * @param object $state */ public function recode_legacy_state_answer($state) { $answer = $state->answer; diff --git a/question/type/ordering/db/upgrade.php b/question/type/ordering/db/upgrade.php index 5551ac609b1..2793f0b6fbd 100644 --- a/question/type/ordering/db/upgrade.php +++ b/question/type/ordering/db/upgrade.php @@ -22,28 +22,13 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -// This file keeps track of upgrades to -// the calculated qtype plugin. -// -// Sometimes, changes between versions involve -// alterations to database structures and other -// major things that may break installations. -// -// The upgrade function in this file will attempt -// to perform all the necessary actions to upgrade -// your older installation to the current version. -// -// If there's something it cannot do itself, it -// will tell you what you need to do. -// -// The commands in here will all be database-neutral, -// using the methods of database_manager class. -// -// Please do not forget to use upgrade_set_timeout() -// before any action that may take longer time to finish. - defined('MOODLE_INTERNAL') || die(); +/** + * Upgrade code for the ordering question type. + * + * @param int $oldversion the version we are upgrading from. + */ function xmldb_qtype_ordering_upgrade($oldversion) { global $CFG, $DB; diff --git a/question/type/ordering/edit_ordering_form.php b/question/type/ordering/edit_ordering_form.php index 91f0780a860..c0af4bb76c1 100644 --- a/question/type/ordering/edit_ordering_form.php +++ b/question/type/ordering/edit_ordering_form.php @@ -36,14 +36,26 @@ require_once($CFG->dirroot.'/question/type/ordering/question.php'); */ class qtype_ordering_edit_form extends question_edit_form { + /** Rows count in answer field */ const NUM_ANS_ROWS = 2; + + /** Cols count in answer field */ const NUM_ANS_COLS = 60; + + /** Number of answers in question by default */ const NUM_ANS_DEFAULT = 6; + + /** Minimal number of answers to show */ const NUM_ANS_MIN = 3; + + /** Number of answers to add on demand */ const NUM_ANS_ADD = 3; /** - * unique name for this question type + * Unique name for this question type + * + * @return the question type name, should be the same as the name() method + * in the question type class. */ public function qtype() { return 'ordering'; @@ -127,6 +139,12 @@ class qtype_ordering_edit_form extends question_edit_form { $this->add_interactive_settings(false, false); } + /** + * Returns answer repeats count + * + * @param object $question + * @return int + */ protected function get_answer_repeats($question) { if (isset($question->id)) { $repeats = count($question->options->answers); @@ -140,7 +158,9 @@ class qtype_ordering_edit_form extends question_edit_form { } /** - * get_editor_attributes + * Returns editor attributes + * + * @return array */ protected function get_editor_attributes() { return array( @@ -150,7 +170,9 @@ class qtype_ordering_edit_form extends question_edit_form { } /** - * get_editor_options + * Returns editor options + * + * @return array */ protected function get_editor_options() { return array( @@ -161,7 +183,11 @@ class qtype_ordering_edit_form extends question_edit_form { } /** - * reset_editor_format + * Resets editor format to specified + * + * @param object $editor + * @param int $format + * @return int */ protected function reset_editor_format($editor, $format=FORMAT_MOODLE) { $value = $editor->getValue(); @@ -171,7 +197,11 @@ class qtype_ordering_edit_form extends question_edit_form { } /** - * adjust_html_editors + * Adjust HTML editor and removal buttons. + * + * @param object $mform + * @param string $name + * @param int $repeats */ protected function adjust_html_editors($mform, $name, $repeats) { @@ -235,7 +265,10 @@ class qtype_ordering_edit_form extends question_edit_form { } /** - * data_preprocessing + * Perform an preprocessing needed on the data passed to {@link set_data()} + * before it is used to initialise the form. + * @param object $question the data being passed to the form. + * @return object $question the modified data. */ public function data_preprocessing($question) { @@ -300,6 +333,14 @@ class qtype_ordering_edit_form extends question_edit_form { return $question; } + /** + * Form validation + * + * @param array $data array of ("fieldname"=>value) of submitted data + * @param array $files array of uploaded files "element_name"=>tmp_file_path + * @return array of "element_name"=>"error_description" if there are errors, + * or an empty array if everything is OK (true allowed for backwards compatibility too). + */ public function validation($data, $files) { $errors = array(); $plugin = 'qtype_ordering'; @@ -334,29 +375,29 @@ class qtype_ordering_edit_form extends question_edit_form { } /** - * get_default_value + * Returns default value for item * - * @param $name - * @param $default (optional, default = null) - * @return default value for field with this $name + * @param string $name Item name + * @param string|mixed|null $default Default value (optional, default = null) + * @return string|mixed|null Default value for field with this $name */ protected function get_default_value($name, $default=null) { return get_user_preferences("qtype_ordering_$name", $default); } /** - * get_default_value + * Saves default value for item * - * @param $name - * @param $default (optional, default = null) - * @return default value for field with this $name + * @param string $name Item name + * @param string|mixed|null $value + * @return bool Always true or exception */ protected function set_default_value($name, $value) { return set_user_preferences(array("qtype_ordering_$name" => $value)); } /** - * this javascript could be useful for inserting buttons + * This javascript could be useful for inserting buttons * into the form once it has loaded in the browser * however this means that the buttons are not recognized * by the Moodle Form API diff --git a/question/type/ordering/lib.php b/question/type/ordering/lib.php index 4d43ac9d1e7..d58ac38ee5c 100644 --- a/question/type/ordering/lib.php +++ b/question/type/ordering/lib.php @@ -25,9 +25,17 @@ defined('MOODLE_INTERNAL') || die(); /** - * Checks file access for multiple choice questions. + * Checks file access for ordering questions. + * + * @param stdClass $course course object + * @param stdClass $cm course module object + * @param stdClass $context context object + * @param string $filearea file area + * @param array $args extra arguments + * @param bool $forcedownload whether or not force download + * @param array $options additional options affecting the file serving */ -function qtype_ordering_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) { +function qtype_ordering_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) { global $CFG; require_once($CFG->dirroot.'/lib/questionlib.php'); question_pluginfile($course, $context, 'qtype_ordering', $filearea, $args, $forcedownload); diff --git a/question/type/ordering/question.php b/question/type/ordering/question.php index 65a2639d9d0..1843beea3a4 100644 --- a/question/type/ordering/question.php +++ b/question/type/ordering/question.php @@ -33,40 +33,78 @@ defined('MOODLE_INTERNAL') || die(); */ class qtype_ordering_question extends question_graded_automatically { + /** Select all answers */ const SELECT_ALL = 0; + /** Select random set of answers */ const SELECT_RANDOM = 1; + /** Select contignous subset of answers */ const SELECT_CONTIGUOUS = 2; + + /** Show answers in vertical list */ const LAYOUT_VERTICAL = 0; + /** Show answers in one horizontal line */ const LAYOUT_HORIZONTAL = 1; + + + /** @var int Zero grade on any error */ const GRADING_ALL_OR_NOTHING = -1; + /** @var int Counts items, placed into right absolute place */ const GRADING_ABSOLUTE_POSITION = 0; + /** @var int Every sequential pair in right order is graded (last pair is excluded) */ const GRADING_RELATIVE_NEXT_EXCLUDE_LAST = 1; + /** @var int Every sequential pair in right order is graded (last pair is included) */ const GRADING_RELATIVE_NEXT_INCLUDE_LAST = 2; + /** @var int Single answers that are placed before and after each answer is graded if in right order*/ const GRADING_RELATIVE_ONE_PREVIOUS_AND_NEXT = 3; + /** @var int All answers that are placed before and after each answer is graded if in right order*/ const GRADING_RELATIVE_ALL_PREVIOUS_AND_NEXT = 4; + /** @var int Only longest ordered subset is graded */ const GRADING_LONGEST_ORDERED_SUBSET = 5; + /** @var int Only longest ordered and contignous subset is graded */ const GRADING_LONGEST_CONTIGUOUS_SUBSET = 6; - /** fields from "qtype_ordering_options" */ + // Fields from "qtype_ordering_options" table. + /** @var string */ public $correctfeedback; + /** @var int */ public $correctfeedbackformat; + /** @var string */ public $incorrectfeedback; + /** @var int */ public $incorrectfeedbackformat; + /** @var string */ public $partiallycorrectfeedback; + /** @var int */ public $partiallycorrectfeedbackformat; - /** records from "question_answers" table */ + /** @var array Records from "question_answers" table */ public $answers; - /** records from "qtype_ordering_options" table */ + /** @var array Records from "qtype_ordering_options" table */ public $options; - /** array of answerids in correct order */ + /** @var array of answerids in correct order */ public $correctresponse; - /** array current order of answerids */ + /** @var array contatining current order of answerids */ public $currentresponse; + /** + * Start a new attempt at this question, storing any information that will + * be needed later in the step. + * + * This is where the question can do any initialisation required on a + * per-attempt basis. For example, this is where the multiple choice + * question type randomly shuffles the choices (if that option is set). + * + * Any information about how the question has been set up for this attempt + * should be stored in the $step, by calling $step->set_qt_var(...). + * + * @param question_attempt_step $step The first step of the {@link question_attempt} + * being started. Can be used to store state. + * @param int $variant which variant of this question to start. Will be between + * 1 and {@link get_num_variants()} inclusive. + */ public function start_attempt(question_attempt_step $step, $variant) { $answers = $this->get_ordering_answers(); $options = $this->get_ordering_options(); @@ -118,6 +156,19 @@ class qtype_ordering_question extends question_graded_automatically { $step->set_qt_var('_currentresponse', implode(',', $this->currentresponse)); } + /** + * When an in-progress {@link question_attempt} is re-loaded from the + * database, this method is called so that the question can re-initialise + * its internal state as needed by this attempt. + * + * For example, the multiple choice question type needs to set the order + * of the choices to the order that was set up when start_attempt was called + * originally. All the information required to do this should be in the + * $step object, which is the first step of the question_attempt being loaded. + * + * @param question_attempt_step $step The first step of the {@link question_attempt} + * being loaded. + */ public function apply_attempt_state(question_attempt_step $step) { $answers = $this->get_ordering_answers(); $options = $this->get_ordering_options(); @@ -125,11 +176,30 @@ class qtype_ordering_question extends question_graded_automatically { $this->correctresponse = array_filter(explode(',', $step->get_qt_var('_correctresponse'))); } + /** + * What data may be included in the form submission when a student submits + * this question in its current state? + * + * This information is used in calls to optional_param. The parameter name + * has {@link question_attempt::get_field_prefix()} automatically prepended. + * + * @return array|string variable name => PARAM_... constant, or, as a special case + * that should only be used in unavoidable, the constant question_attempt::USE_RAW_DATA + * meaning take all the raw submitted data belonging to this question. + */ public function get_expected_data() { $name = $this->get_response_fieldname(); return array($name => PARAM_TEXT); } + /** + * What data would need to be submitted to get this question correct. + * If there is more than one correct answer, this method should just + * return one possibility. If it is not possible to compute a correct + * response, this method should return null. + * + * @return array|null parameter name => value. + */ public function get_correct_response() { $correctresponse = $this->correctresponse; foreach ($correctresponse as $position => $answerid) { @@ -140,31 +210,89 @@ class qtype_ordering_question extends question_graded_automatically { return array($name => implode(',', $correctresponse)); } + /** + * Produce a plain text summary of a response. + * + * @param array $response a response, as might be passed to {@link grade_response()}. + * @return string a plain text summary of that response, that could be used in reports. + */ public function summarise_response(array $response) { return ''; } + /** + * Categorise the student's response according to the categories defined by + * get_possible_responses. + * + * @param array $response a response, as might be passed to {@link grade_response()}. + * @return array subpartid => {@link question_classified_response} objects. + * returns an empty array if no analysis is possible. + */ public function classify_response(array $response) { return array(); } + /** + * Used by many of the behaviours, to work out whether the student's + * response to the question is complete. That is, whether the question attempt + * should move to the COMPLETE or INCOMPLETE state. + * + * @param array $response responses, as returned by + * {@link question_attempt_step::get_qt_data()}. + * @return bool whether this response is a complete answer to this question. + */ public function is_complete_response(array $response) { return true; } + /** + * Use by many of the behaviours to determine whether the student + * has provided enough of an answer for the question to be graded automatically, + * or whether it must be considered aborted. + * + * @param array $response responses, as returned by + * {@link question_attempt_step::get_qt_data()}. + * @return bool whether this response can be graded. + */ public function is_gradable_response(array $response) { return true; } + /** + * In situations where is_gradable_response() returns false, this method + * should generate a description of what the problem is. + * @param array $response + * @return string the message + */ public function get_validation_error(array $response) { return ''; } + /** + * Use by many of the behaviours to determine whether the student's + * response has changed. This is normally used to determine that a new set + * of responses can safely be discarded. + * + * @param array $old the responses previously recorded for this question, + * as returned by {@link question_attempt_step::get_qt_data()} + * @param array $new the new responses, in the same format. + * @return bool whether the two sets of responses are the same - that is + * whether the new set of responses can safely be discarded. + */ public function is_same_response(array $old, array $new) { $name = $this->get_response_fieldname(); return (isset($old[$name]) && isset($new[$name]) && $old[$name] == $new[$name]); } + /** + * Grade a response to the question, returning a fraction between + * get_min_fraction() and get_max_fraction(), and the corresponding {@link question_state} + * right, partial or wrong. + * + * @param array $response responses, as returned by + * {@link question_attempt_step::get_qt_data()}. + * @return array (float, integer) the fraction, and the state. + */ public function grade_response(array $response) { $this->update_current_response($response); @@ -243,6 +371,17 @@ class qtype_ordering_question extends question_graded_automatically { return array($fraction, question_state::graded_state_for_fraction($fraction)); } + /** + * Checks whether the users is allow to be served a particular file. + * + * @param question_attempt $qa the question attempt being displayed. + * @param question_display_options $options the options that control display of the question. + * @param string $component the name of the component we are serving files for. + * @param string $filearea the name of the file area. + * @param array $args the remaining bits of the file path. + * @param bool $forcedownload whether the user must be forced to download the file. + * @return bool true if the user can access this file. + */ public function check_file_access($qa, $options, $component, $filearea, $args, $forcedownload) { if ($component == 'question') { if ($filearea == 'answer') { @@ -259,14 +398,27 @@ class qtype_ordering_question extends question_graded_automatically { return parent::check_file_access($qa, $options, $component, $filearea, $args, $forcedownload); } - /** + /* + * ------------------ * Custom methods + * ------------------ */ + /** + * Returns response mform field name + * + * @return string + */ public function get_response_fieldname() { return 'response_'.$this->id; } + /** + * Convert response data from mform into array + * + * @param array $response Form data + * @return array + */ public function update_current_response($response) { $name = $this->get_response_fieldname(); if (isset($response[$name])) { @@ -283,6 +435,11 @@ class qtype_ordering_question extends question_graded_automatically { } } + /** + * Loads from DB and returns options for question instance + * + * @return object + */ public function get_ordering_options() { global $DB; if ($this->options === null) { @@ -307,6 +464,11 @@ class qtype_ordering_question extends question_graded_automatically { return $this->options; } + /** + * Loads from DB and returns array of answers objects + * + * @return array of objects + */ public function get_ordering_answers() { global $CFG, $DB; if ($this->answers === null) { @@ -327,6 +489,11 @@ class qtype_ordering_question extends question_graded_automatically { return $this->answers; } + /** + * Returns layoutclass + * + * @return string + */ public function get_ordering_layoutclass() { $options = $this->get_ordering_options(); switch ($options->layouttype) { @@ -339,6 +506,13 @@ class qtype_ordering_question extends question_graded_automatically { } } + /** + * Returns array of next answers + * + * @param array $answerids array of answers id + * @param bool $lastitem Include last item? + * @return array of id of next answer + */ public function get_next_answerids($answerids, $lastitem = false) { $nextanswerids = array(); $imax = count($answerids); @@ -357,6 +531,13 @@ class qtype_ordering_question extends question_graded_automatically { return $nextanswerids; } + /** + * Returns prev and next answers array + * + * @param array $answerids array of answers id + * @param bool $all include all answers + * @return array of array('prev' => previd, 'next' => nextid) + */ public function get_previous_and_next_answerids($answerids, $all = false) { $prevnextanswerids = array(); $next = $answerids; @@ -378,6 +559,12 @@ class qtype_ordering_question extends question_graded_automatically { return $prevnextanswerids; } + /** + * Search for best ordered subset + * + * @param bool $contiguous + * @return array + */ public function get_ordered_subset($contiguous) { $positions = $this->get_ordered_positions($this->correctresponse, @@ -405,6 +592,13 @@ class qtype_ordering_question extends question_graded_automatically { return $bestsubset; } + /** + * Get array of right answer positions for current response + * + * @param array $correctresponse + * @param array $currentresponse + * @return array + */ public function get_ordered_positions($correctresponse, $currentresponse) { $positions = array(); foreach ($currentresponse as $answerid) { @@ -414,7 +608,7 @@ class qtype_ordering_question extends question_graded_automatically { } /** - * get all ordered subsets in the positions array + * Get all ordered subsets in the positions array * * @param array $positions * @param boolean $contiguous TRUE if searching only for contiguous subsets; otherwise FALSE @@ -484,6 +678,13 @@ class qtype_ordering_question extends question_graded_automatically { return $subsets; } + /** + * Helper function for get_select_types, get_layout_types, get_grading_types + * + * @param array $types + * @param int $type + * @return array|string array if $type is not specified and single string if $type is specified + */ static public function get_types($types, $type) { if ($type === null) { return $types; // Return all $types. @@ -494,6 +695,12 @@ class qtype_ordering_question extends question_graded_automatically { return $type; // Shouldn't happen !! } + /** + * Returns availibe values and descriptions for field "selecttype" + * + * @param int $type + * @return array|string array if $type is not specified and single string if $type is specified + */ static public function get_select_types($type=null) { $plugin = 'qtype_ordering'; $types = array( @@ -504,6 +711,12 @@ class qtype_ordering_question extends question_graded_automatically { return self::get_types($types, $type); } + /** + * Returns availibe values and descriptions for field "layouttype" + * + * @param int $type + * @return array|string array if $type is not specified and single string if $type is specified + */ static public function get_layout_types($type=null) { $plugin = 'qtype_ordering'; $types = array( @@ -513,6 +726,12 @@ class qtype_ordering_question extends question_graded_automatically { return self::get_types($types, $type); } + /** + * Returns availibe values and descriptions for field "gradingtype" + * + * @param int $type + * @return array|string array if $type is not specified and single string if $type is specified + */ static public function get_grading_types($type=null) { $plugin = 'qtype_ordering'; $types = array( diff --git a/question/type/ordering/questiontype.php b/question/type/ordering/questiontype.php index fbbcfbb9bd9..8ba6ca67476 100644 --- a/question/type/ordering/questiontype.php +++ b/question/type/ordering/questiontype.php @@ -32,7 +32,7 @@ defined('MOODLE_INTERNAL') || die(); */ class qtype_ordering extends question_type { - /** combined feedback fields */ + /** @var array Combined feedback fields */ public $feedbackfields = array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback'); /** @@ -97,11 +97,24 @@ class qtype_ordering extends question_type { } } + /** + * Initialise the common question_definition fields. + * @param question_definition $question the question_definition we are creating. + * @param object $questiondata the question data loaded from the database. + */ protected function initialise_question_instance(question_definition $question, $questiondata) { parent::initialise_question_instance($question, $questiondata); $this->initialise_combined_feedback($question, $questiondata); } + /** + * Saves question-type specific options + * + * This is called by {@link save_question()} to save the question-type specific data + * @return object $result->error or $result->notice + * @param object $question This holds the information from the editing form, + * it is not a standard question object. + */ public function save_question_options($question) { global $DB; @@ -234,6 +247,33 @@ class qtype_ordering extends question_type { return true; } + /** + * This method should return all the possible types of response that are + * recognised for this question. + * + * The question is modelled as comprising one or more subparts. For each + * subpart, there are one or more classes that that students response + * might fall into, each of those classes earning a certain score. + * + * For example, in a shortanswer question, there is only one subpart, the + * text entry field. The response the student gave will be classified according + * to which of the possible $question->options->answers it matches. + * + * For the matching question type, there will be one subpart for each + * question stem, and for each stem, each of the possible choices is a class + * of student's response. + * + * A response is an object with two fields, ->responseclass is a string + * presentation of that response, and ->fraction, the credit for a response + * in that class. + * + * Array keys have no specific meaning, but must be unique, and must be + * the same if this function is called repeatedly. + * + * @param object $questiondata the question definition data. + * @return array keys are subquestionid, values are arrays of possible + * responses to that subquestion. + */ public function get_possible_responses($questiondata) { $responses = array(); $question = $this->make_question($questiondata); @@ -247,6 +287,12 @@ class qtype_ordering extends question_type { return; } + /** + * Callback function for filtering answers with array_filter + * + * @param mixed $value + * @return bool If true, this item should be saved. + */ public function is_not_blank($value) { if (is_array($value)) { $value = $value['text']; @@ -255,6 +301,18 @@ class qtype_ordering extends question_type { return ($value || $value === '0'); } + /** + * Loads the question type specific options for the question. + * + * This function loads any question type specific options for the + * question from the database into the question object. This information + * is placed in the $question->options field. A question type is + * free, however, to decide on a internal structure of the options field. + * @return bool Indicates success or failure. + * @param object $question The question object for the question. This object + * should be updated to include the question type + * specific information (it is passed by reference). + */ public function get_question_options($question) { global $DB, $OUTPUT; @@ -275,6 +333,12 @@ class qtype_ordering extends question_type { return true; } + /** + * Deletes the question-type specific data when a question is deleted. + * + * @param int $questionid The id of question being deleted. + * @param int $contextid the context this quesiotn belongs to. + */ public function delete_question($questionid, $contextid) { global $DB; $DB->delete_records('qtype_ordering_options', array('questionid' => $questionid)); @@ -282,13 +346,13 @@ class qtype_ordering extends question_type { } /** - * import_from_gift + * Import question from GIFT format * - * @param array $data - * @param stdClass $question + * @param array $lines + * @param object $question * @param qformat_gift $format - * @param string $extra (optional, default=null) - * @todo Finish documenting this function + * @param string $extra (optional, default=null) + * @return object Question instance */ public function import_from_gift($lines, $question, $format, $extra=null) { global $CFG; @@ -379,10 +443,9 @@ class qtype_ordering extends question_type { } /** - * check_ordering_combined_feedback + * Check that the required feedback fields exist * - * @param stdClass $question (passed by reference) - * @todo Finish documenting this function + * @param object $question */ protected function check_ordering_combined_feedback(&$question) { foreach ($this->feedbackfields as $field) { @@ -393,10 +456,11 @@ class qtype_ordering extends question_type { } /** - * extract_layout_select_count_grading + * Given question object, returns array with array layouttype, selecttype, selectcount, gradingtype, where + * layouttype, selecttype, gradingtype are string representation. * - * @param stdClass $question - * @todo Finish documenting this function + * @param object $question + * @return array(layouttype, selecttype, selectcount, gradingtype) */ public function extract_layout_select_count_grading($question) { @@ -461,12 +525,12 @@ class qtype_ordering extends question_type { } /** - * export_to_gift + * Exports question to GIFT format * - * @param stdClass $question + * @param object $question * @param qformat_gift $format - * @param string $extra (optional, default=null) - * @todo Finish documenting this function + * @param string $extra (optional, default=null) + * @return string GIFT representation of question */ public function export_to_gift($question, $format, $extra=null) { global $CFG; @@ -485,12 +549,12 @@ class qtype_ordering extends question_type { } /** - * export_to_xml + * Exports question to XML format * - * @param stdClass $question + * @param object $question * @param qformat_xml $format - * @param string $extra (optional, default=null) - * @todo Finish documenting this function + * @param string $extra (optional, default=null) + * @return string XML representation of question */ public function export_to_xml($question, qformat_xml $format, $extra=null) { global $CFG; @@ -521,16 +585,17 @@ class qtype_ordering extends question_type { return $output; } - /* + /** * Imports question from the Moodle XML format * * Imports question using information from extra_question_fields function * If some of you fields contains id's you'll need to reimplement this * - * @param array $data + * @param array $data * @param qtype_ordering $question (or null) - * @param qformat_xml $format - * @param string $extra (optional, default=null) + * @param qformat_xml $format + * @param string $extra (optional, default=null) + * @return object New question object */ public function import_from_xml($data, $question, qformat_xml $format, $extra=null) { global $CFG; @@ -587,12 +652,13 @@ class qtype_ordering extends question_type { return $newquestion; } - /* - * fix_questionname + /** + * Fix empty or long question name * * @param string $name * @param string $defaultname (optional, default='') * @param integer $maxnamelength (optional, default=42) + * @return string Fixed name */ public function fix_questionname($name, $defaultname='', $maxnamelength = 42) { if (trim($name) == '') { @@ -612,14 +678,14 @@ class qtype_ordering extends question_type { return $name; } - /* - * set_layout_select_count_grading + /** + * Set layouttype, selecttype, selectcount, gradingtype based on their textual representation * * @param object $question (passed by reference) - * @param integer $layout the layout type - * @param integer $select the select type - * @param integer $count the number of items to display - * @param integer $grading the grading type + * @param string $layout the layout type + * @param string $select the select type + * @param string $count the number of items to display + * @param string $grading the grading type */ public function set_layout_select_count_grading(&$question, $layout, $select, $count, $grading) { diff --git a/question/type/ordering/renderer.php b/question/type/ordering/renderer.php index 21e91fb75db..2a002eebd43 100644 --- a/question/type/ordering/renderer.php +++ b/question/type/ordering/renderer.php @@ -22,7 +22,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -/** Prevent direct access to this script */ +// Prevent direct access to this script. defined('MOODLE_INTERNAL') || die(); /** @@ -33,12 +33,28 @@ defined('MOODLE_INTERNAL') || die(); */ class qtype_ordering_renderer extends qtype_with_combined_feedback_renderer { + /** @var array of answerids in correct order */ protected $correctinfo = null; + + /** @var array of answerids in order of current answer*/ protected $currentinfo = null; + + /** @var array of scored for every item */ protected $itemscores = array(); + /** @var bool True if answer is 100% correct */ protected $allcorrect = null; + /** + * Generate the display of the formulation part of the question. This is the + * area that contains the quetsion text, and the controls for students to + * input their answers. Some question types also embed bits of feedback, for + * example ticks and crosses, in this area. + * + * @param question_attempt $qa the question attempt to display. + * @param question_display_options $options controls what should and should not be displayed. + * @return string HTML fragment. + */ public function formulation_and_controls(question_attempt $qa, question_display_options $options) { global $CFG, $DB; @@ -157,6 +173,13 @@ class qtype_ordering_renderer extends qtype_with_combined_feedback_renderer { return $result; } + /** + * Generate the specific feedback. This is feedback that varies according to + * the response the student gave. + * + * @param question_attempt $qa the question attempt to display. + * @return string HTML fragment. + */ public function specific_feedback(question_attempt $qa) { if ($feedback = $this->combined_feedback($qa)) { @@ -236,6 +259,14 @@ class qtype_ordering_renderer extends qtype_with_combined_feedback_renderer { return $feedback.$gradingtype.$gradedetails.$scoredetails; } + /** + * Gereate an automatic description of the correct response to this question. + * Not all question types can do this. If it is not possible, this method + * should just return an empty string. + * + * @param question_attempt $qa the question attempt to display. + * @return string HTML fragment. + */ public function correct_response(question_attempt $qa) { global $DB; @@ -277,6 +308,11 @@ class qtype_ordering_renderer extends qtype_with_combined_feedback_renderer { // Custom methods. + /** + * Fills $this->correctinfo and $this->currentinfo depending on question options. + * + * @param object $question + */ protected function get_response_info($question) { $gradingtype = $question->options->gradingtype; @@ -320,6 +356,14 @@ class qtype_ordering_renderer extends qtype_with_combined_feedback_renderer { } } + /** + * Returns score for one item depending on correctness and question settings. + * + * @param object $question + * @param int $position + * @param int $answerid + * @return array (score, maxscore, fraction, percent, class, img) + */ protected function get_ordering_item_score($question, $position, $answerid) { if (! isset($this->itemscores[$position])) { @@ -433,6 +477,11 @@ class qtype_ordering_renderer extends qtype_with_combined_feedback_renderer { return $this->itemscores[$position]; } + /** + * Return true if answer is 100% correct. + * + * @return bool + */ protected function is_all_correct() { if ($this->allcorrect === null) { // Use "==" to determine if the two "info" arrays are identical.