From 61500b65b6ed55d1766a677398c4732de909cc50 Mon Sep 17 00:00:00 2001 From: Gordon Bateson Date: Wed, 3 Dec 2014 22:02:45 +0900 Subject: [PATCH] MDL-79863 qtype_ordering: qtype/ordering fix upgrade script to check for existence of reader_question_instances before attempting to acces sit --- question/type/ordering/db/upgrade.php | 10 +- question/type/ordering/legacy/20.php | 196 ++++++++---------------- question/type/ordering/lib.php | 2 +- question/type/ordering/question.php | 4 +- question/type/ordering/questiontype.php | 29 +++- question/type/ordering/readme.txt | 12 +- question/type/ordering/renderer.php | 63 ++------ question/type/ordering/styles.css | 40 ++++- question/type/ordering/version.php | 4 +- 9 files changed, 155 insertions(+), 205 deletions(-) diff --git a/question/type/ordering/db/upgrade.php b/question/type/ordering/db/upgrade.php index 0e0292472e3..7f09a82ce28 100644 --- a/question/type/ordering/db/upgrade.php +++ b/question/type/ordering/db/upgrade.php @@ -30,7 +30,7 @@ function xmldb_qtype_ordering_upgrade($oldversion) { $newversion = 2013062800; if ($oldversion < $newversion) { $select = 'qn.*, qo.id AS questionorderingid'; - $from = '{question} qn LEFT JOIN {question_ordering} qo ON qn.id=qo.question'; + $from = '{question} qn LEFT JOIN {question_ordering} qo ON qn.id = qo.question'; $where = 'qn.qtype = ? AND qo.id IS NULL'; $params = array('ordering'); if ($questions = $DB->get_records_sql("SELECT $select FROM $from WHERE $where", $params)) { @@ -49,8 +49,12 @@ function xmldb_qtype_ordering_upgrade($oldversion) { } else { // this is a faulty ordering question - remove it $DB->delete_records('question', array('id' => $question->id)); - $DB->delete_records('quiz_question_instances', array('question' => $question->id)); - $DB->delete_records('reader_question_instances', array('question' => $question->id)); + if ($dbman->table_exists('quiz_question_instances')) { + $DB->delete_records('quiz_question_instances', array('question' => $question->id)); + } + if ($dbman->table_exists('reader_question_instances')) { + $DB->delete_records('reader_question_instances', array('question' => $question->id)); + } } } } diff --git a/question/type/ordering/legacy/20.php b/question/type/ordering/legacy/20.php index d18e27002e5..fba9d4a0497 100644 --- a/question/type/ordering/legacy/20.php +++ b/question/type/ordering/legacy/20.php @@ -704,7 +704,6 @@ class question_type extends default_questiontype { * be retrieved. Question type specific information is * available. */ - // ULPGC ecastro function get_all_responses(&$question, &$state) { if (isset($question->options->answers) && is_array($question->options->answers)) { $answers = array(); @@ -759,7 +758,6 @@ class question_type extends default_questiontype { * for which a correct answer is needed. Question * type specific information is included. */ - // ULPGC ecastro function get_actual_response($question, $state) { if (!empty($state->responses)) { $responses[] = $state->responses['']; @@ -796,7 +794,6 @@ class question_type extends default_questiontype { return array($responsedetail); } - // ULPGC ecastro function get_fractional_grade(&$question, &$state) { $grade = $state->grade; if ($question->maxgrade > 0) { @@ -819,7 +816,6 @@ class question_type extends default_questiontype { * for which a correct answer is needed. Question * type specific information is included. */ - // ULPGC ecastro function check_response(&$question, &$state){ return false; } @@ -1249,19 +1245,19 @@ class question_type extends default_questiontype { function print_question_formulation_and_controls(&$question, &$state, $cmoptions, $options) { global $CFG, $DB; - static $addStyle = true; - static $addScript = true; - - if (empty($question->options)) { - return; // shouldn't happen !! + if (empty($options->correctness)) { + $options->correctness = 0; } - if (empty($question->options->answers)) { + // shortcut to answers + $answers = $question->options->answers; + + if (empty($question->options) || empty($answers)) { return; // shouldn't happen !! } if ($question->options->studentsee==0) { // all items - $question->options->studentsee = count($question->options->answers); + $question->options->studentsee = count($answers); } else { // a nasty hack so that "studentsee" is the same // as what is displayed by edit_ordering_form.php @@ -1271,139 +1267,81 @@ class question_type extends default_questiontype { switch ($question->options->logical) { case 0: // all - $answerids = array_keys($question->options->answers); + $answerids = array_keys($answers); break; case 1: // random subset - $answerids = array_rand($question->options->answers, $question->options->studentsee); + $answerids = array_rand($answers, $question->options->studentsee); break; case 2: // contiguous subset - if (count($question->options->answers) > $question->options->studentsee) { - $offset = mt_rand(0, count($question->options->answers) - $question->options->studentsee); - $question->options->answers = array_slice($question->options->answers, $offset, $question->options->studentsee, true); + if (count($answers) > $question->options->studentsee) { + $offset = mt_rand(0, count($answers) - $question->options->studentsee); + $answers = array_slice($answers, $offset, $question->options->studentsee, true); } - $answerids = array_keys($question->options->answers); + $answerids = array_keys($answers); break; } shuffle($answerids); - $formatoptions = (object)array('noclean' => true, 'para' => true); - $questiontext = format_text($question->questiontext, $question->questiontextformat, $formatoptions, $cmoptions->course); + $response_name = 'q'.$question->id; + $response_id = 'id_q'.$question->id; + $sortable_id = 'id_sortable'.$question->id; $output = ''; - $output .= html_writer::tag('script', '', array('type'=>'text/javascript', 'src'=>$CFG->wwwroot.'/question/type/ordering/js/jquery.js')); - $output .= html_writer::tag('script', '', array('type'=>'text/javascript', 'src'=>$CFG->wwwroot.'/question/type/ordering/js/jquery-ui.js')); - $style = "\n"; - $style .= "ul.sortable".$question->id." li {\n"; - $style .= " position: relative;\n"; - $style .= "}\n"; - if ($addStyle) { - $addStyle = false; // only add style once - $style .= "ul.boxy {\n"; - $style .= " border: 1px solid #ccc;\n"; - $style .= " float: left;\n"; - $style .= " font-family: Arial, sans-serif;\n"; - $style .= " font-size: 13px;\n"; - $style .= " list-style-type: none;\n"; - $style .= " margin: 0px;\n"; - $style .= " margin-left: 5px;\n"; - $style .= " padding: 4px 4px 0 4px;\n"; - $style .= " width: 360px;\n"; - $style .= "}\n"; - $style .= "ul.boxy li {\n"; - $style .= " background-color: #eeeeee;\n"; - $style .= " border: 1px solid #cccccc;\n"; - $style .= " border-image: initial;\n"; - $style .= " cursor: move;\n"; - $style .= " list-style-type: none;\n"; - $style .= " margin-bottom: 1px;\n"; - $style .= " min-height: 20px;\n"; - $style .= " padding: 8px 2px;\n"; - $style .= "}\n"; + if (count($answerids)) { + + if ($options->readonly || $options->correctness) { + // don't allow items to be dragged and dropped + } else { + $script = "\n"; + $script .= "//\n"; + $output .= html_writer::tag('script', $script, array('type' => 'text/javascript')); + } + + $questiontext = $this->format_text($question->questiontext, $question->questiontextformat, $cmoptions); + $output .= html_writer::tag('div', $questiontext, array('class' => 'qtext')); + + $output .= html_writer::start_tag('div', array('class' => 'ablock')); + $output .= html_writer::start_tag('div', array('class' => 'answer')); + $output .= html_writer::start_tag('ul', array('class' => 'sortablelist', 'id' => $sortable_id)); + + // generate ordering items + foreach ($answerids as $i => $answerid) { + // the original "id" revealed the correct order of the answers + // because $answer->fraction holds the correct order number + // $id = 'ordering_item_'.$answerid.'_'.intval($answers[$answerid]->fraction); + $id = 'ordering_item_'.md5($CFG->passwordsaltmain.$answers[$answerid]->answer); + $class = 'sortableitem'; + $params = array('class' => $class, 'id' => $id); + $output .= html_writer::tag('li', $answers[$answerid]->answer, $params); + } + + $output .= html_writer::end_tag('ul'); + $output .= html_writer::end_tag('div'); // answer + $output .= html_writer::end_tag('div'); // ablock + + $output .= html_writer::empty_tag('input', array('type' => 'hidden', + 'name' => $response_name, + 'id' => $response_id, + 'value' => '')); + $output .= html_writer::tag('div', '', array('style' => 'clear:both;')); } - $output .= html_writer::tag('style', $style, array('type' => 'text/css')); - - $script = "\n"; - $script .= "//id."').sortable({\n"; - $script .= " update: function(event, ui) {\n"; - $script .= " var ItemsOrder = $(this).sortable('toArray').toString();\n"; - $script .= " $('#q".$question->id."').attr('value', ItemsOrder);\n"; - $script .= " }\n"; - $script .= " });\n"; - $script .= " $('#sortable".$question->id."').disableSelection();\n"; - $script .= "});\n"; - $script .= "$(document).ready(function() {\n"; - $script .= " var ItemsOrder = $('#sortable".$question->id."').sortable('toArray').toString();\n"; - $script .= " $('#q".$question->id."').attr('value', ItemsOrder);\n"; - $script .= "});\n"; - $script .= "//]]>\n"; - $output .= html_writer::tag('script', $script, array('type' => 'text/javascript')); - - $output .= html_writer::tag('div', stripslashes($questiontext), array('class' => 'qtext')); - $output .= html_writer::start_tag('div', array('class' => 'ablock')); - $output .= html_writer::start_tag('div', array('class' => 'answer')); - $output .= html_writer::start_tag('ul', array('class' => 'boxy', 'id' => 'sortable'.$question->id)); - - // generate ordering items - foreach ($answerids as $i => $answerid) { - // the original "id" revealed the correct order of the answers - // because $answer->fraction holds the correct order number - // $id = 'ordering_item_'.$answerid.'_'.intval($question->options->answers[$answerid]->fraction); - $id = 'ordering_item_'.md5($CFG->passwordsaltmain.$question->options->answers[$answerid]->answer); - $params = array('class' => 'ui-state-default', 'id' => $id); - $output .= html_writer::tag('li', $question->options->answers[$answerid]->answer, $params); - } - - $output .= html_writer::end_tag('ul'); - $output .= html_writer::end_tag('div'); // answer - $output .= html_writer::end_tag('div'); // ablock - - $output .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'q'.$question->id, 'id' => 'q'.$question->id, 'value' => '9')); - $output .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'answer', 'value' => '')); - - $output .= html_writer::tag('div', '', array('style' => 'clear:both;')); - - $script = "\n"; - $script .= "//id."');\n"; - $script .= "//]]>\n"; - $output .= html_writer::tag('script', $script, array('type' => 'text/javascript')); echo $output; } diff --git a/question/type/ordering/lib.php b/question/type/ordering/lib.php index 38c54d3a893..5efbb7d3250 100644 --- a/question/type/ordering/lib.php +++ b/question/type/ordering/lib.php @@ -31,6 +31,6 @@ defined('MOODLE_INTERNAL') || die(); */ function qtype_ordering_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) { global $CFG; - require_once($CFG->libdir . '/questionlib.php'); + 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 909fbe3d3a1..66425a9e246 100644 --- a/question/type/ordering/question.php +++ b/question/type/ordering/question.php @@ -15,7 +15,7 @@ // along with Moodle. If not, see . /** - * Ordering question definition classes. + * ORDERING question definition classes. * * @package qtype * @subpackage ordering @@ -26,7 +26,7 @@ defined('MOODLE_INTERNAL') || die(); /** - * Represents an ordering question. + * Represents an ORDERING question. * * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later diff --git a/question/type/ordering/questiontype.php b/question/type/ordering/questiontype.php index 5bc3b2729f7..0ba55dccb12 100644 --- a/question/type/ordering/questiontype.php +++ b/question/type/ordering/questiontype.php @@ -34,13 +34,40 @@ if (class_exists('question_type')) { } /** - * The ordering question type. + * The ORDERING question type. * * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qtype_ordering extends question_type { + /** + * Utility method used by {@link qtype_renderer::head_code()} + * It looks for any of the files script.js or script.php that + * exist in the plugin folder and ensures they get included. + * It also includes the jquery files required for this plugin + */ + public function find_standard_scripts() { + global $PAGE; + + // include "script.js" and/or "script.php" in the normal way + parent::find_standard_scripts(); + + // include jquery files + if (method_exists($PAGE->requires, 'jquery')) { + // Moodle >= 2.5 + $PAGE->requires->jquery(); + $PAGE->requires->jquery_plugin('ui'); + $PAGE->requires->jquery_plugin('ui.touch-punch', 'qtype_ordering'); + } else { + // Moodle <= 2.4 + $jquery = '/question/type/' . $this->name().'/jquery'; + $PAGE->requires->js($jquery.'/jquery.js', true); + $PAGE->requires->js($jquery.'/jquery-ui.js', true); + $PAGE->requires->js($jquery.'/jquery-ui.touch-punch.js', true); + } + } + protected function initialise_question_instance(question_definition $question, $questiondata) { parent::initialise_question_instance($question, $questiondata); $answers = array_keys($questiondata->options->answers); diff --git a/question/type/ordering/readme.txt b/question/type/ordering/readme.txt index 598277b2176..bd83e0ccefb 100644 --- a/question/type/ordering/readme.txt +++ b/question/type/ordering/readme.txt @@ -1,12 +1,12 @@ -====================================== +========================================== The Ordering question type for Moodle 2.x -====================================== +========================================== The ordering question type displays several short sentences in a random order which are to be dragged into the correct sequential order. It was developed for the ordering questions used in the Reader activity module for Moodle 2.x -====================================== +========================================== To INSTALL or UPDATE this plugin -====================================== +========================================== 1. get the files for this plugin from any one of the following locations: @@ -23,9 +23,9 @@ To INSTALL or UPDATE this plugin if install/upgrade does not begin automatically, you can initiate it manually by navigating to the following link: Settings -> Site administration -> Notifications -====================================== +========================================== Further information -====================================== +========================================== For more information, tutorials and online discussion forums, please visit: http://moodlereader.org/ diff --git a/question/type/ordering/renderer.php b/question/type/ordering/renderer.php index 125fc197b63..57a0c24b1f5 100644 --- a/question/type/ordering/renderer.php +++ b/question/type/ordering/renderer.php @@ -26,7 +26,7 @@ defined('MOODLE_INTERNAL') || die(); /** - * Generates the output for true-false questions. + * Generates the output for ORDERING questions * * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later @@ -36,9 +36,6 @@ class qtype_ordering_renderer extends qtype_renderer { public function formulation_and_controls(question_attempt $qa, question_display_options $options) { global $CFG, $DB; - static $addStyle = true; - static $addScript = true; - $question = $qa->get_question(); $ordering = $question->get_ordering_options(); $answers = $question->get_ordering_answers(); @@ -55,13 +52,6 @@ class qtype_ordering_renderer extends qtype_renderer { $ordering->studentsee += 2; } - if ($options->readonly || $options->correctness) { - // don't allow items to be dragged and dropped - $readonly = true; - } else { - $readonly = false; - } - if ($options->correctness) { list($answerids, $correctorder) = $this->get_response($qa, $question, $answers); } else { @@ -91,45 +81,10 @@ class qtype_ordering_renderer extends qtype_renderer { $sortable_id = 'id_sortable_'.$question->id; $result = ''; - if ($readonly==false) { - $result .= html_writer::tag('script', '', array('type'=>'text/javascript', 'src'=>$CFG->wwwroot.'/question/type/ordering/js/jquery.js')); - $result .= html_writer::tag('script', '', array('type'=>'text/javascript', 'src'=>$CFG->wwwroot.'/question/type/ordering/js/jquery-ui.js')); - $result .= html_writer::tag('script', '', array('type'=>'text/javascript', 'src'=>$CFG->wwwroot.'/question/type/ordering/js/jquery.ui.touch-punch.js')); - } - $style = "\n"; - $style .= "ul#$sortable_id li {\n"; - $style .= " position: relative;\n"; - $style .= "}\n"; - if ($addStyle) { - $addStyle = false; // only add style once - $style .= "ul.boxy {\n"; - $style .= " border: 1px solid #ccc;\n"; - $style .= " float: left;\n"; - $style .= " font-family: Arial, sans-serif;\n"; - $style .= " font-size: 13px;\n"; - $style .= " list-style-type: none;\n"; - $style .= " margin: 0px;\n"; - $style .= " margin-left: 5px;\n"; - $style .= " padding: 4px 4px 0 4px;\n"; - $style .= " width: 360px;\n"; - $style .= "}\n"; - $style .= "ul.boxy li {\n"; - $style .= " background-color: #eeeeee;\n"; - $style .= " border: 1px solid #cccccc;\n"; - $style .= " border-image: initial;\n"; - if ($readonly==false) { - $style .= " cursor: move;\n"; - } - $style .= " list-style-type: none;\n"; - $style .= " margin-bottom: 1px;\n"; - $style .= " min-height: 20px;\n"; - $style .= " padding: 8px 2px;\n"; - $style .= "}\n"; - } - $result .= html_writer::tag('style', $style, array('type' => 'text/css')); - - if ($readonly==false) { + if ($options->readonly || $options->correctness) { + // don't allow items to be dragged and dropped + } else { $script = "\n"; $script .= "// 'ablock')); $result .= html_writer::start_tag('div', array('class' => 'answer')); - $result .= html_writer::start_tag('ul', array('class' => 'boxy', 'id' => $sortable_id)); + $result .= html_writer::start_tag('ul', array('class' => 'sortablelist', 'id' => $sortable_id)); // generate ordering items foreach ($answerids as $position => $answerid) { @@ -169,7 +124,7 @@ class qtype_ordering_renderer extends qtype_renderer { } $img = "$img "; } else { - $class = 'ui-state-default'; + $class = 'sortableitem'; $img = ''; } // the original "id" revealed the correct order of the answers @@ -185,8 +140,10 @@ class qtype_ordering_renderer extends qtype_renderer { $result .= html_writer::end_tag('div'); // answer $result .= html_writer::end_tag('div'); // ablock - $params = array('type' => 'hidden', 'name' => $response_name, 'id' => $response_id, 'value' => ''); - $result .= html_writer::empty_tag('input', $params); + $result .= html_writer::empty_tag('input', array('type' => 'hidden', + 'name' => $response_name, + 'id' => $response_id, + 'value' => '')); $result .= html_writer::tag('div', '', array('style' => 'clear:both;')); } diff --git a/question/type/ordering/styles.css b/question/type/ordering/styles.css index e8c86cbfa08..46fc21e5acb 100644 --- a/question/type/ordering/styles.css +++ b/question/type/ordering/styles.css @@ -1,11 +1,35 @@ -ul.boxy li.correctposition { - border: 4px solid #99ff66; /* gentle green */ +ul.sortablelist { + border : 1px solid #ccc; + float : left; + font-family : Arial, sans-serif; + font-size : 13px; + list-style-type : none; + margin : 0px; + margin-left : 5px; + padding : 4px 4px 0 4px; + width : 360px; } -ul.boxy li.wrongposition { - border: 4px solid #ff7373; /* gentle red */ +ul.sortablelist li { + background-color : #eeeeee; + border : 1px solid #cccccc; + border-image : initial; + list-style-type : none; + margin-bottom : 1px; + min-height : 20px; + padding : 8px 2px; } -ul.boxy li.correctposition, -ul.boxy li.wrongposition { - margin-bottom: 4px; - margin-top: 4px; +ul.sortablelist li.sortableitem { + position : relative; + cursor : move; +} +ul.sortablelist li.correctposition { + border : 4px solid #99ff66; /* gentle green */ +} +ul.sortablelist li.wrongposition { + border : 4px solid #ff7373; /* gentle red */ +} +ul.sortablelist li.correctposition, +ul.sortablelist li.wrongposition { + margin-bottom : 4px; + margin-top : 4px; } diff --git a/question/type/ordering/version.php b/question/type/ordering/version.php index cc295409704..69ecbee81b0 100644 --- a/question/type/ordering/version.php +++ b/question/type/ordering/version.php @@ -30,6 +30,6 @@ defined('MOODLE_INTERNAL') || die(); $plugin->cron = 0; $plugin->component = 'qtype_ordering'; $plugin->maturity = MATURITY_STABLE; // ALPHA=50, BETA=100, RC=150, STABLE=200 -$plugin->release = '2014-11-30 (03)'; -$plugin->version = 2014113003; +$plugin->release = '2014-12-04 (04)'; +$plugin->version = 2014120404; $plugin->requires = 2010112400; // Moodle 2.0