From bce6b3c70a44b6f6118c7987d077e39e0e8522a2 Mon Sep 17 00:00:00 2001 From: Tony Levi Date: Thu, 16 Jun 2011 12:47:17 +0930 Subject: [PATCH 01/21] MDL-24577: Fix mark all posts in this discussion read doesn't work completely correct --- mod/forum/lib.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mod/forum/lib.php b/mod/forum/lib.php index cc5ef170ef702..1cc0b02edb3d8 100644 --- a/mod/forum/lib.php +++ b/mod/forum/lib.php @@ -6226,8 +6226,9 @@ function forum_tp_mark_posts_read($user, $postids) { if ($new) { list($usql, $new_params) = $DB->get_in_or_equal($new); - $params = array($user->id, $now, $now, $user->id, $cutoffdate); + $params = array($user->id, $now, $now, $user->id); $params = array_merge($params, $new_params); + $params[] = $cutoffdate; $sql = "INSERT INTO {forum_read} (userid, postid, discussionid, forumid, firstread, lastread) From cb1564b1ce5eeb793b8be81020f3190489ec306f Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 9 Nov 2011 11:45:02 +0000 Subject: [PATCH 02/21] MDL-29743 quiz: Finish attempt link didn't save responses in some brosers. Thanks to Brandon Browning for identifying the problem. It is quite subtle why this typo would have this effect. You need to look at the implementation of the preventDefault method in lib/yui/3.4.1/build/event-base/event-base.js. --- mod/quiz/module.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/quiz/module.js b/mod/quiz/module.js index ec37234f43fef..d9d217f685cc4 100644 --- a/mod/quiz/module.js +++ b/mod/quiz/module.js @@ -170,7 +170,7 @@ M.mod_quiz.nav.init = function(Y) { if (Y.one('a.endtestlink')) { Y.on('click', function(e) { - e.preventDefault(e); + e.preventDefault(); Y.one('#followingpage').set('value', -1); Y.one('#responseform').submit(); }, 'a.endtestlink'); From 6336bd914a7adb446dc48b88a0f58bbcec795a17 Mon Sep 17 00:00:00 2001 From: Henning Bostelmann Date: Tue, 13 Sep 2011 01:11:19 +0100 Subject: [PATCH 03/21] MDL-29350 Prevent duplication of groupings when copying activities This patch also includes a database upgrade to correct data produced as a result of this bug. --- backup/moodle2/restore_stepslib.php | 9 ++++++++- lib/db/upgrade.php | 15 +++++++++++++++ version.php | 2 +- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/backup/moodle2/restore_stepslib.php b/backup/moodle2/restore_stepslib.php index 3044c7ff80862..c9705a98b3333 100644 --- a/backup/moodle2/restore_stepslib.php +++ b/backup/moodle2/restore_stepslib.php @@ -802,7 +802,14 @@ public function process_grouping_group($data) { $data->groupingid = $this->get_new_parentid('grouping'); // Use new parentid $data->groupid = $this->get_mappingid('group', $data->groupid); // Get from mappings - $DB->insert_record('groupings_groups', $data); // No need to set this mapping (no child info nor files) + + $params = array(); + $params['groupingid'] = $data->groupingid; + $params['groupid'] = $data->groupid; + + if (!$DB->record_exists('groupings_groups', $params)) { + $DB->insert_record('groupings_groups', $data); // No need to set this mapping (no child info nor files) + } } protected function after_execute() { diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index 83adec7443908..097cfb10066f6 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -6916,6 +6916,21 @@ function xmldb_main_upgrade($oldversion) { upgrade_main_savepoint(true, 2011110200.02); } + if ($oldversion < 2011111500.01) { + // Remove duplicate entries from groupings_groups table + $sql = 'SELECT MIN(id) AS firstid, groupingid, groupid FROM {groupings_groups} '. + 'GROUP BY groupingid, groupid HAVING COUNT(id)>1'; + $badrecs = $DB->get_records_sql($sql); + foreach ($badrecs as $badrec) { + $where = 'groupingid = ? and groupid = ? and id > ?'; + $params = array($badrec->groupingid, $badrec->groupid, $badrec->firstid); + $DB->delete_records_select('groupings_groups', $where, $params); + } + + // Main savepoint reached + upgrade_main_savepoint(true, 2011111500.01); + } + return true; } diff --git a/version.php b/version.php index eb0a3297af2e3..19816d1a81fc9 100644 --- a/version.php +++ b/version.php @@ -30,7 +30,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2011111500.00; // YYYYMMDD = weekly release date of this DEV branch +$version = 2011111500.01; // YYYYMMDD = weekly release date of this DEV branch // RR = release increments - 00 in DEV branches // .XX = incremental changes From 5cc021a00b43722379a10fb6905314defeff016e Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Tue, 8 Nov 2011 15:12:58 +0000 Subject: [PATCH 04/21] MDL-30069 Question type icons missing in lots of places. --- lib/questionlib.php | 12 ++--------- mod/quiz/editlib.php | 8 +++---- question/editlib.php | 2 +- question/renderer.php | 49 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 15 deletions(-) create mode 100644 question/renderer.php diff --git a/lib/questionlib.php b/lib/questionlib.php index 1bfe045e44f06..081a0e67cd06f 100644 --- a/lib/questionlib.php +++ b/lib/questionlib.php @@ -825,16 +825,8 @@ function get_question_options(&$questions, $loadtags = false) { * @return string the HTML for the img tag. */ function print_question_icon($question) { - global $OUTPUT; - - $qtype = question_bank::get_qtype($question->qtype, false); - $namestr = $qtype->menu_name(); - - // TODO convert to return a moodle_icon object, or whatever the class is. - $html = '' .
-            $namestr . ''; - - return $html; + global $PAGE; + return $PAGE->get_renderer('question', 'bank')->qtype_icon($question->qtype); } /** diff --git a/mod/quiz/editlib.php b/mod/quiz/editlib.php index 6b5ddf9f74a9c..0097787deb50c 100644 --- a/mod/quiz/editlib.php +++ b/mod/quiz/editlib.php @@ -781,7 +781,7 @@ function quiz_print_singlequestion($question, $returnurl, $quiz) { echo quiz_question_edit_button($quiz->cmid, $question, $returnurl, quiz_question_tostring($question) . ' '); echo ''; - print_question_icon($question); + echo print_question_icon($question); echo ' ' . question_bank::get_qtype_name($question->qtype) . ''; echo '' . quiz_question_preview_button($quiz, $question, true) . ''; @@ -807,7 +807,7 @@ function quiz_print_randomquestion(&$question, &$pageurl, &$quiz, $quiz_qbanktoo } echo '
'; - print_question_icon($question); + echo print_question_icon($question); print_random_option_icon($question); echo ' ' . get_string('randomfromcategory', 'quiz') . '
'; @@ -886,7 +886,7 @@ function quiz_print_randomquestion(&$question, &$pageurl, &$quiz, $quiz_qbanktoo function quiz_print_singlequestion_reordertool($question, $returnurl, $quiz) { echo '
'; echo ''; echo '' . @@ -920,7 +920,7 @@ function quiz_print_randomquestion_reordertool(&$question, &$pageurl, &$quiz) { echo '
'; echo '
'; echo $reordercheckboxlabel; - print_question_icon($question); + echo print_question_icon($question); print_random_option_icon($question); if ($questioncount == 0) { diff --git a/question/editlib.php b/question/editlib.php index 8bc1c2c80c1e0..4079d48488b50 100644 --- a/question/editlib.php +++ b/question/editlib.php @@ -1793,7 +1793,7 @@ function print_qtype_to_add_option($qtype) { echo ''; $fakequestion = new stdClass(); $fakequestion->qtype = $qtype->name(); - print_question_icon($fakequestion); + echo print_question_icon($fakequestion); echo $qtype->menu_name() . '' . $summary; echo "\n"; echo "
\n"; diff --git a/question/renderer.php b/question/renderer.php new file mode 100644 index 0000000000000..f8f667b598196 --- /dev/null +++ b/question/renderer.php @@ -0,0 +1,49 @@ +. + +/** + * Renderers for outputting parts of the question bank. + * + * @package moodlecore + * @subpackage questionbank + * @copyright 2011 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +defined('MOODLE_INTERNAL') || die(); + + +/** + * This renderer outputs parts of the question bank. + * + * @copyright 2011 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class core_question_bank_renderer extends plugin_renderer_base { + + /** + * Output the icon for a question type + * @param string $qtype the question type. + * @return string HTML fragment. + */ + public function qtype_icon($qtype) { + $qtype = question_bank::get_qtype($qtype, false); + $namestr = $qtype->local_name(); + + return $this->pix_icon('icon', $namestr, $qtype->plugin_name(), array('title' => $namestr)); + } +} From 94c0ec215925dd52a5c8ea8ba59e62ef7c236c5d Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Tue, 8 Nov 2011 16:53:15 +0000 Subject: [PATCH 05/21] MDL-30185 question engine reporting: add redundant where to query for perf. Without this, MySQL fails to cope. --- mod/quiz/report/attemptsreport.php | 10 ++++- question/engine/datalib.php | 63 +++++++++++++++++------------- 2 files changed, 45 insertions(+), 28 deletions(-) diff --git a/mod/quiz/report/attemptsreport.php b/mod/quiz/report/attemptsreport.php index 89bfefc1fc5ee..f26b2ec707127 100644 --- a/mod/quiz/report/attemptsreport.php +++ b/mod/quiz/report/attemptsreport.php @@ -621,13 +621,21 @@ protected function add_latest_state_join($slot) { return; } + // This condition roughly filters the list of attempts to be considered. + // It is only used in a subselect to help crappy databases (see MDL-30122) + // therefore, it is better to use a very simple join, which may include + // too many records, than to do a super-accurate join. + $qubaids = new qubaid_join("{quiz_attempts} {$alias}quiza", "{$alias}quiza.uniqueid", + "{$alias}quiza.quiz = :{$alias}quizid", array("{$alias}quizid" => $this->sql->params['quizid'])); + $dm = new question_engine_data_mapper(); - $inlineview = $dm->question_attempt_latest_state_view($alias); + list($inlineview, $viewparams) = $dm->question_attempt_latest_state_view($alias, $qubaids); $this->sql->fields .= ",\n$fields"; $this->sql->from .= "\nLEFT JOIN $inlineview ON " . "$alias.questionusageid = quiza.uniqueid AND $alias.slot = :{$alias}slot"; $this->sql->params[$alias . 'slot'] = $slot; + $this->sql->params = array_merge($this->sql->params, $viewparams); } /** diff --git a/question/engine/datalib.php b/question/engine/datalib.php index cdcaf8f07da0f..2f41b12d7ff72 100644 --- a/question/engine/datalib.php +++ b/question/engine/datalib.php @@ -865,33 +865,42 @@ public function sum_usage_marks_subquery($qubaid) { END) = 0"; } - public function question_attempt_latest_state_view($alias) { - return "( - SELECT - {$alias}qa.id AS questionattemptid, - {$alias}qa.questionusageid, - {$alias}qa.slot, - {$alias}qa.behaviour, - {$alias}qa.questionid, - {$alias}qa.variant, - {$alias}qa.maxmark, - {$alias}qa.minfraction, - {$alias}qa.flagged, - {$alias}qa.questionsummary, - {$alias}qa.rightanswer, - {$alias}qa.responsesummary, - {$alias}qa.timemodified, - {$alias}qas.id AS attemptstepid, - {$alias}qas.sequencenumber, - {$alias}qas.state, - {$alias}qas.fraction, - {$alias}qas.timecreated, - {$alias}qas.userid - - FROM {question_attempts} {$alias}qa - JOIN {question_attempt_steps} {$alias}qas ON - {$alias}qas.id = {$this->latest_step_for_qa_subquery($alias . 'qa.id')} - ) $alias"; + /** + * Get a subquery that returns the latest step of every qa in some qubas. + * Currently, this is only used by the quiz reports. See + * {@link quiz_attempt_report_table::add_latest_state_join()}. + * @param string $alias alias to use for this inline-view. + * @param qubaid_condition $qubaids restriction on which question_usages we + * are interested in. This is important for performance. + * @return array with two elements, the SQL fragment and any params requried. + */ + public function question_attempt_latest_state_view($alias, qubaid_condition $qubaids) { + return array("( + SELECT {$alias}qa.id AS questionattemptid, + {$alias}qa.questionusageid, + {$alias}qa.slot, + {$alias}qa.behaviour, + {$alias}qa.questionid, + {$alias}qa.variant, + {$alias}qa.maxmark, + {$alias}qa.minfraction, + {$alias}qa.flagged, + {$alias}qa.questionsummary, + {$alias}qa.rightanswer, + {$alias}qa.responsesummary, + {$alias}qa.timemodified, + {$alias}qas.id AS attemptstepid, + {$alias}qas.sequencenumber, + {$alias}qas.state, + {$alias}qas.fraction, + {$alias}qas.timecreated, + {$alias}qas.userid + + FROM {$qubaids->from_question_attempts($alias . 'qa')} + JOIN {question_attempt_steps} {$alias}qas ON + {$alias}qas.id = {$this->latest_step_for_qa_subquery($alias . 'qa.id')} + WHERE {$qubaids->where()} + ) $alias", $qubaids->from_where_params()); } protected function latest_step_for_qa_subquery($questionattemptid = 'qa.id') { From 6c314a368113c07a8d7da0aeac04771520413132 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Mon, 7 Nov 2011 12:36:19 +0000 Subject: [PATCH 06/21] MDL-30167 qtype_numerical: notice when required unit is not in the answer. --- question/type/numerical/questiontype.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/question/type/numerical/questiontype.php b/question/type/numerical/questiontype.php index 5090b00206aef..07433189c029f 100644 --- a/question/type/numerical/questiontype.php +++ b/question/type/numerical/questiontype.php @@ -641,16 +641,17 @@ public function apply_units($response, $separateunit = null) { $numberstring = $matches[0]; if ($this->unitsbefore) { - $unit = substr($response, 0, -strlen($numberstring)); + // substr returns false when it means '', so cast back to string. + $unit = (string) substr($response, 0, -strlen($numberstring)); } else { - $unit = substr($response, strlen($numberstring)); + $unit = (string) substr($response, strlen($numberstring)); } if (!is_null($separateunit)) { $unit = $separateunit; } - if ($unit && $this->is_known_unit($unit)) { + if ($this->is_known_unit($unit)) { $multiplier = 1 / $this->units[$unit]; } else { $multiplier = null; From f7094147b14befe00600eae4eb10c4bd8535e1a0 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Tue, 8 Nov 2011 15:57:18 +0000 Subject: [PATCH 07/21] MDL-30186 qtype editing forms should use advcheckbox. --- question/type/edit_question_form.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/question/type/edit_question_form.php b/question/type/edit_question_form.php index 34f52a80df97a..e7505f35edcaa 100644 --- a/question/type/edit_question_form.php +++ b/question/type/edit_question_form.php @@ -344,7 +344,7 @@ protected function add_combined_feedback_fields($withshownumpartscorrect = false $mform->setType($feedbackname, PARAM_RAW); if ($withshownumpartscorrect && $feedbackname == 'partiallycorrectfeedback') { - $mform->addElement('checkbox', 'shownumcorrect', + $mform->addElement('advcheckbox', 'shownumcorrect', get_string('options', 'question'), get_string('shownumpartscorrect', 'question')); } @@ -361,11 +361,11 @@ protected function get_hint_fields($withclearwrong = false, $withshownumpartscor $repeatedoptions['hint']['type'] = PARAM_RAW; if ($withclearwrong) { - $repeated[] = $mform->createElement('checkbox', 'hintclearwrong', + $repeated[] = $mform->createElement('advcheckbox', 'hintclearwrong', get_string('options', 'question'), get_string('clearwrongparts', 'question')); } if ($withshownumpartscorrect) { - $repeated[] = $mform->createElement('checkbox', 'hintshownumcorrect', '', + $repeated[] = $mform->createElement('advcheckbox', 'hintshownumcorrect', '', get_string('shownumpartscorrect', 'question')); } From 0f7477c07f7b69189e7477c00e44a6cab1cd91a6 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 9 Nov 2011 12:51:01 +0000 Subject: [PATCH 08/21] MDL-30199 qtype numerical etc. Don't require tolerance for answer *. --- question/type/numerical/edit_numerical_form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/question/type/numerical/edit_numerical_form.php b/question/type/numerical/edit_numerical_form.php index 512f694958115..2775ef0b8d50d 100644 --- a/question/type/numerical/edit_numerical_form.php +++ b/question/type/numerical/edit_numerical_form.php @@ -264,7 +264,7 @@ protected function validate_answers($data, $errors) { if ($data['fraction'][$key] == 1) { $maxgrade = true; } - if (!is_numeric($data['tolerance'][$key])) { + if ($answer !== '*' && !is_numeric($data['tolerance'][$key])) { $errors['tolerance['.$key.']'] = get_string('mustbenumeric', 'qtype_calculated'); } From 7238cd2ef0f51fe39478fe5dd7493cc675a50711 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Thu, 10 Nov 2011 12:51:24 +0000 Subject: [PATCH 09/21] MDL-30209 quiz refers to wrong rendere method in two places. Thanks to Dan Marsden for working out the fix. --- mod/quiz/startattempt.php | 2 +- mod/quiz/summary.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mod/quiz/startattempt.php b/mod/quiz/startattempt.php index c660df32e93dd..c3e31d855cd39 100644 --- a/mod/quiz/startattempt.php +++ b/mod/quiz/startattempt.php @@ -101,7 +101,7 @@ $output = $PAGE->get_renderer('mod_quiz'); if (!$quizobj->is_preview_user() && $messages) { print_error('attempterror', 'quiz', $quizobj->view_url(), - $output->print_messages($messages)); + $output->access_messages($messages)); } if ($accessmanager->is_preflight_check_required($currentattemptid)) { diff --git a/mod/quiz/summary.php b/mod/quiz/summary.php index 065bb8cccb3a9..869b4b1d75ea1 100644 --- a/mod/quiz/summary.php +++ b/mod/quiz/summary.php @@ -61,7 +61,7 @@ $output = $PAGE->get_renderer('mod_quiz'); if (!$attemptobj->is_preview_user() && $messages) { print_error('attempterror', 'quiz', $attemptobj->view_url(), - $output->print_messages($messages)); + $output->access_messages($messages)); } if ($accessmanager->is_preflight_check_required($attemptobj->get_attemptid())) { redirect($attemptobj->start_attempt_url(null, $page)); From 08502b574dae47e00b02ab6ef538303d626fd2b9 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 9 Nov 2011 13:56:03 +0000 Subject: [PATCH 10/21] MDL-30182 quiz grade.php should support userid param. --- mod/quiz/attemptlib.php | 9 +++++- mod/quiz/grade.php | 70 ++++++++++++++++++++++++++++++++--------- 2 files changed, 63 insertions(+), 16 deletions(-) diff --git a/mod/quiz/attemptlib.php b/mod/quiz/attemptlib.php index 22dba91fac0a3..385832d3d3d79 100644 --- a/mod/quiz/attemptlib.php +++ b/mod/quiz/attemptlib.php @@ -418,10 +418,17 @@ class quiz_attempt { * @param object $quiz the quiz object for this attempt and user. * @param object $cm the course_module object for this quiz. * @param object $course the row from the course table for the course we belong to. + * @param bool $loadquestions (optional) if true, the default, load all the details + * of the state of each question. Else just set up the basic details of the attempt. */ - public function __construct($attempt, $quiz, $cm, $course) { + public function __construct($attempt, $quiz, $cm, $course, $loadquestions = true) { $this->attempt = $attempt; $this->quizobj = new quiz($quiz, $cm, $course); + + if (!$loadquestions) { + return; + } + $this->quba = question_engine::load_questions_usage_by_activity($this->attempt->uniqueid); $this->determine_layout(); $this->number_questions(); diff --git a/mod/quiz/grade.php b/mod/quiz/grade.php index dd2b22cbebc7c..9334731706fa3 100644 --- a/mod/quiz/grade.php +++ b/mod/quiz/grade.php @@ -30,23 +30,63 @@ $id = required_param('id', PARAM_INT); +$userid = optional_param('userid', 0, PARAM_INT); -if (!$cm = get_coursemodule_from_id('quiz', $id)) { - print_error('invalidcoursemodule'); -} -if (!$quiz = $DB->get_record('quiz', array('id' => $cm->instance))) { - print_error('invalidquizid'); -} -if (!$course = $DB->get_record('course', array('id' => $quiz->course))) { - print_error('coursemisconf'); +$cm = get_coursemodule_from_id('quiz', $id, 0, false, MUST_EXIST); +$course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST); +$quiz = $DB->get_record('quiz', array('id' => $cm->instance), '*', MUST_EXIST); +require_login($course, false, $cm); + +$reportlist = quiz_report_list(context_module::instance($cm->id)); +if (empty($reportlist) || $userid == $USER->id) { + // If the user cannot see reports, or can see reports but is looking + // at their own grades, redirect them to the view.php page. + // (The looking at their own grades case is unlikely, since users who + // appear in the gradebook are unlikely to be able to see quiz reports, + // but it is possible.) + redirect(new moodle_url('/mod/quiz/view.php', array('id' => $cm->id))); } -require_login($course, false, $cm); +// Now we know the user is interested in reports. If they are interested in a +// specific other user, try to send them to the most appropriate attempt review page. +if ($userid) { -$reportlist = quiz_report_list(get_context_instance(CONTEXT_MODULE, $cm->id)); -if (!empty($reportlist)) { - redirect(new moodle_url('/mod/quiz/report.php', array( - 'id' => $cm->id, 'mode' => reset($reportlist)))); -} else { - redirect(new moodle_url('/mod/quiz/view.php', array('id' => $cm->id))); + // Work out which attempt is most significant from a grading point of view. + $attempts = quiz_get_user_attempts($quiz->id, $userid, 'finished'); + $attempt = null; + switch ($quiz->grademethod) { + case QUIZ_ATTEMPTFIRST: + $attempt = reset($attempts); + break; + + case QUIZ_ATTEMPTLAST: + case QUIZ_GRADEAVERAGE: + $attempt = end($attempts); + break; + + case QUIZ_GRADEHIGHEST: + $maxmark = 0; + foreach ($attempts as $at) { + // >=, since we want to most recent relevant attempt. + if ((float) $at->sumgrades >= $maxmark) { + $maxmark = $at->sumgrades; + $attempt = $at; + } + } + break; + } + + // If the user can review the relevant attempt, redirect to it. + if ($attempt) { + $attemptobj = new quiz_attempt($attempt, $quiz, $cm, $course, false); + if ($attemptobj->is_review_allowed()) { + redirect($attemptobj->review_url()); + } + } + + // Otherwise, fall thorugh to the generic case. } + +// Send the user to the first report they can see. +redirect(new moodle_url('/mod/quiz/report.php', array( + 'id' => $cm->id, 'mode' => reset($reportlist)))); From 0c9cb1bc1997730bfcc48bd689c15fc9e0bbb7d6 Mon Sep 17 00:00:00 2001 From: sam marshall Date: Tue, 15 Nov 2011 10:27:10 +0000 Subject: [PATCH 11/21] MDL-30266 completionlib fix unit test breakage (regression) --- lib/simpletest/testcompletionlib.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/simpletest/testcompletionlib.php b/lib/simpletest/testcompletionlib.php index f4288fd9eb044..c78063be01098 100644 --- a/lib/simpletest/testcompletionlib.php +++ b/lib/simpletest/testcompletionlib.php @@ -527,7 +527,7 @@ function test_get_progress_all() { $c->__construct((object)array('id'=>42)); // 1) Basic usage - $c->expectAt(0,'get_tracked_users',array(false, array(), 0, '', '', '')); + $c->expectAt(0,'get_tracked_users',array(false, array(), 0, '', '', '', null)); $c->setReturnValueAt(0,'get_tracked_users',array( (object)array('id'=>100,'firstname'=>'Woot','lastname'=>'Plugh'), (object)array('id'=>201,'firstname'=>'Vroom','lastname'=>'Xyzzy'), @@ -556,7 +556,7 @@ function test_get_progress_all() { ),$c->get_progress_all(false)); // 2) With more than 1,000 results - $c->expectAt(1,'get_tracked_users',array(true, 3, 0, '', '', '')); + $c->expectAt(1,'get_tracked_users',array(true, 3, 0, '', '', '', null)); $tracked=array(); $ids=array(); From 4a645a682120adbec21a597abecf786cf25cbb83 Mon Sep 17 00:00:00 2001 From: Andrew Robert Nicols Date: Tue, 15 Nov 2011 15:16:47 +0000 Subject: [PATCH 12/21] MDL-30274 Correct typo of loginpage variable --- theme/mymobile/renderers.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/theme/mymobile/renderers.php b/theme/mymobile/renderers.php index f7c253c527509..3007930d3c982 100644 --- a/theme/mymobile/renderers.php +++ b/theme/mymobile/renderers.php @@ -380,7 +380,7 @@ public function login_info_footer() { return ''; } - $loginapge = ((string)$this->page->url === get_login_url()); + $loginpage = ((string)$this->page->url === get_login_url()); $course = $this->page->course; if (session_is_loggedinas()) { @@ -407,7 +407,7 @@ public function login_info_footer() { } if (isguestuser()) { $loggedinas = $realuserinfo.get_string('loggedinasguest'); - if (!$loginapge) { + if (!$loginpage) { $loggedinas .= " (".get_string('login').')'; } } else if (is_role_switched($course->id)) { // Has switched roles @@ -421,7 +421,7 @@ public function login_info_footer() { } } else { $loggedinas = get_string('loggedinnot', 'moodle'); - if (!$loginapge) { + if (!$loginpage) { $loggedinas .= " (".get_string('login').')'; } } From 24ad1d1feb8ecf173bf036671644b10691080bae Mon Sep 17 00:00:00 2001 From: sam marshall Date: Tue, 15 Nov 2011 15:24:08 +0000 Subject: [PATCH 13/21] MDL-30275 Assignment activity description not displayed on course page --- mod/assignment/lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/assignment/lib.php b/mod/assignment/lib.php index 5d4d5fb3dedaf..0be90a6d383e4 100644 --- a/mod/assignment/lib.php +++ b/mod/assignment/lib.php @@ -3540,7 +3540,7 @@ function assignment_get_coursemodule_info($coursemodule) { } if ($coursemodule->showdescription) { // Convert intro to html. Do not filter cached version, filters run at display time. - $info->content = format_module_intro('assignment', $assignment, $coursemodule->id, false); + $result->content = format_module_intro('assignment', $assignment, $coursemodule->id, false); } return $result; } else { From 63a1625d788745aa7bce67bcb944f968ce0b7082 Mon Sep 17 00:00:00 2001 From: Ankit Kumar Agarwal Date: Wed, 16 Nov 2011 09:47:00 +0530 Subject: [PATCH 14/21] MDL-30279 SCORM Fixing sql errors during cron --- mod/scorm/lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/scorm/lib.php b/mod/scorm/lib.php index b4c84a94fa4b3..50906fbd4d9cc 100644 --- a/mod/scorm/lib.php +++ b/mod/scorm/lib.php @@ -510,7 +510,7 @@ function scorm_cron () { $cfg_scorm = get_config('scorm'); if (!empty($cfg_scorm->allowaicchacp)) { $expiretime = time() - ($cfg_scorm->aicchacpkeepsessiondata*24*60*60); - $DB->delete_records_select('scorm_aicc_session', 'WHERE timemodified < ?', array($expiretime)); + $DB->delete_records_select('scorm_aicc_session', 'timemodified < ?', array($expiretime)); } } From e079e82c087becf06d902089d14f3f76686bde19 Mon Sep 17 00:00:00 2001 From: Ankit Kumar Agarwal Date: Thu, 10 Nov 2011 13:46:43 +0530 Subject: [PATCH 15/21] MDL-29893 Fixing issues with password generation function --- lib/moodlelib.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/moodlelib.php b/lib/moodlelib.php index fee53244e8ffd..b5ea4586750de 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -8725,12 +8725,17 @@ function generate_password($maxlen=10) { $filler1 = $fillers[rand(0, strlen($fillers) - 1)]; $password = $word1 . $filler1 . $word2; } else { - $maxlen = !empty($CFG->minpasswordlength) ? $CFG->minpasswordlength : 0; + $minlen = !empty($CFG->minpasswordlength) ? $CFG->minpasswordlength : 0; $digits = $CFG->minpassworddigits; $lower = $CFG->minpasswordlower; $upper = $CFG->minpasswordupper; $nonalphanum = $CFG->minpasswordnonalphanum; - $additional = $maxlen - ($lower + $upper + $digits + $nonalphanum); + $total = $lower + $upper + $digits + $nonalphanum; + // minlength should be the greater one of the two ( $minlen and $total ) + $minlen = $minlen < $total ? $total : $minlen; + // maxlen can never be smaller than minlen + $maxlen = $minlen > $maxlen ? $minlen : $maxlen; + $additional = $maxlen - $total; // Make sure we have enough characters to fulfill // complexity requirements From 15d660a8fd44249c9237630edfd6ccf399f5a7f1 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 16 Nov 2011 10:52:19 +0000 Subject: [PATCH 16/21] MDL-30300 question behaviours: improve q compatibility API. --- question/behaviour/behaviourbase.php | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/question/behaviour/behaviourbase.php b/question/behaviour/behaviourbase.php index 95c0e2a4dfeb3..a5f5575dc46cd 100644 --- a/question/behaviour/behaviourbase.php +++ b/question/behaviour/behaviourbase.php @@ -70,13 +70,22 @@ abstract class question_behaviour { public function __construct(question_attempt $qa, $preferredbehaviour) { $this->qa = $qa; $this->question = $qa->get_question(); - $requiredclass = $this->required_question_definition_type(); - if (!$this->question instanceof $requiredclass) { + if (!$this->is_compatible_question($this->question)) { throw new coding_exception('This behaviour (' . $this->get_name() . ') cannot work with this question (' . get_class($this->question) . ')'); } } + /** + * Some behaviours can only work with certing types of question. This method + * allows the behaviour to verify that a question is compatible. + * @param question_definition $question the question. + */ + public function is_compatible_question(question_definition $question) { + $requiredclass = $this->required_question_definition_type(); + return $this->question instanceof $requiredclass; + } + /** * Most behaviours can only work with {@link question_definition}s * of a particular subtype, or that implement a particular interface. @@ -84,7 +93,9 @@ public function __construct(question_attempt $qa, $preferredbehaviour) { * question passed to the constructor is then checked against this type. * @return string class/interface name. */ - public abstract function required_question_definition_type(); + protected function required_question_definition_type() { + return 'question_definition'; + } /** * @return string the name of this behaviour. For example the name of From 3d17cd3f1ca118ac681074252485aee7ad70b1d8 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 16 Nov 2011 11:07:35 +0000 Subject: [PATCH 17/21] MDL-30300 qbehaviours: convert to the new is_compatible_question API. --- question/behaviour/adaptive/behaviour.php | 4 ++-- question/behaviour/behaviourbase.php | 7 +++++++ question/behaviour/deferredfeedback/behaviour.php | 4 ++-- question/behaviour/immediatefeedback/behaviour.php | 4 ++-- question/behaviour/informationitem/behaviour.php | 4 ++-- question/behaviour/interactive/behaviour.php | 4 ++-- question/behaviour/interactivecountback/behaviour.php | 4 ++-- question/behaviour/missing/behaviour.php | 5 +++-- question/behaviour/upgrade.txt | 7 ++++++- 9 files changed, 28 insertions(+), 15 deletions(-) diff --git a/question/behaviour/adaptive/behaviour.php b/question/behaviour/adaptive/behaviour.php index c663b52226886..9144296f543af 100644 --- a/question/behaviour/adaptive/behaviour.php +++ b/question/behaviour/adaptive/behaviour.php @@ -38,8 +38,8 @@ class qbehaviour_adaptive extends question_behaviour_with_save { const IS_ARCHETYPAL = true; - public function required_question_definition_type() { - return 'question_automatically_gradable'; + public function is_compatible_question(question_definition $question) { + return $question instanceof question_automatically_gradable; } public function get_expected_data() { diff --git a/question/behaviour/behaviourbase.php b/question/behaviour/behaviourbase.php index a5f5575dc46cd..ca09117def6d5 100644 --- a/question/behaviour/behaviourbase.php +++ b/question/behaviour/behaviourbase.php @@ -79,6 +79,10 @@ public function __construct(question_attempt $qa, $preferredbehaviour) { /** * Some behaviours can only work with certing types of question. This method * allows the behaviour to verify that a question is compatible. + * + * This implementation is only provided for backwards-compatibility. You should + * override this method if you are implementing a behaviour. + * * @param question_definition $question the question. */ public function is_compatible_question(question_definition $question) { @@ -91,6 +95,9 @@ public function is_compatible_question(question_definition $question) { * of a particular subtype, or that implement a particular interface. * This method lets the behaviour document that. The type of * question passed to the constructor is then checked against this type. + * + * @deprecated since 2.2. Please use/override {@link is_compatible_question()} instead. + * * @return string class/interface name. */ protected function required_question_definition_type() { diff --git a/question/behaviour/deferredfeedback/behaviour.php b/question/behaviour/deferredfeedback/behaviour.php index 8bc59fc7a709a..5c5de7a31eed5 100644 --- a/question/behaviour/deferredfeedback/behaviour.php +++ b/question/behaviour/deferredfeedback/behaviour.php @@ -40,8 +40,8 @@ class qbehaviour_deferredfeedback extends question_behaviour_with_save { const IS_ARCHETYPAL = true; - public function required_question_definition_type() { - return 'question_automatically_gradable'; + public function is_compatible_question(question_definition $question) { + return $question instanceof question_automatically_gradable; } public static function get_unused_display_options() { diff --git a/question/behaviour/immediatefeedback/behaviour.php b/question/behaviour/immediatefeedback/behaviour.php index 2e7bbe02655f3..f12db5d90f433 100644 --- a/question/behaviour/immediatefeedback/behaviour.php +++ b/question/behaviour/immediatefeedback/behaviour.php @@ -42,8 +42,8 @@ class qbehaviour_immediatefeedback extends question_behaviour_with_save { const IS_ARCHETYPAL = true; - public function required_question_definition_type() { - return 'question_automatically_gradable'; + public function is_compatible_question(question_definition $question) { + return $question instanceof question_automatically_gradable; } public function get_min_fraction() { diff --git a/question/behaviour/informationitem/behaviour.php b/question/behaviour/informationitem/behaviour.php index 8c2cefed705d9..472a6e258c415 100644 --- a/question/behaviour/informationitem/behaviour.php +++ b/question/behaviour/informationitem/behaviour.php @@ -39,8 +39,8 @@ */ class qbehaviour_informationitem extends question_behaviour { - public function required_question_definition_type() { - return 'question_definition'; + public function is_compatible_question(question_definition $question) { + return true; } public function get_expected_data() { diff --git a/question/behaviour/interactive/behaviour.php b/question/behaviour/interactive/behaviour.php index 976bb08e95fa0..27e0b303ba411 100644 --- a/question/behaviour/interactive/behaviour.php +++ b/question/behaviour/interactive/behaviour.php @@ -52,8 +52,8 @@ class qbehaviour_interactive extends question_behaviour_with_save { */ const READONLY_EXCEPT_TRY_AGAIN = 23485299; - public function required_question_definition_type() { - return 'question_automatically_gradable'; + public function is_compatible_question(question_definition $question) { + return $question instanceof question_automatically_gradable; } public function get_right_answer_summary() { diff --git a/question/behaviour/interactivecountback/behaviour.php b/question/behaviour/interactivecountback/behaviour.php index 5b3e7f441645a..8a14cb76818d3 100644 --- a/question/behaviour/interactivecountback/behaviour.php +++ b/question/behaviour/interactivecountback/behaviour.php @@ -64,8 +64,8 @@ class qbehaviour_interactivecountback extends qbehaviour_interactive { const IS_ARCHETYPAL = false; - public function required_question_definition_type() { - return 'question_automatically_gradable_with_countback'; + public function is_compatible_question(question_definition $question) { + return $question instanceof question_automatically_gradable_with_countback; } protected function adjust_fraction($fraction, question_attempt_pending_step $pendingstep) { diff --git a/question/behaviour/missing/behaviour.php b/question/behaviour/missing/behaviour.php index 1726e01116629..3475040a76794 100644 --- a/question/behaviour/missing/behaviour.php +++ b/question/behaviour/missing/behaviour.php @@ -45,8 +45,9 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qbehaviour_missing extends question_behaviour { - public function required_question_definition_type() { - return 'question_definition'; + + public function is_compatible_question(question_definition $question) { + return true; } public function summarise_action(question_attempt_step $step) { diff --git a/question/behaviour/upgrade.txt b/question/behaviour/upgrade.txt index db780e8dbcdc7..63b941ee3de37 100644 --- a/question/behaviour/upgrade.txt +++ b/question/behaviour/upgrade.txt @@ -2,10 +2,15 @@ This files describes API changes for question behaviour plugins. === 2.2 === -* The old +1) The old public static function get_required_behaviours() method is no more. Instead use the ->dependencies facility in version.php. E.g. $plugin->dependencies = array( 'qbehaviour_immediatefeedback' => 2011102700, 'qbehaviour_deferredcbm' => 2011102700 ); + +2) The old required_question_definition_type method has been replaced by a new +is_compatible_question method. You should change your behaviour to override the +new method, not the old one. This change has been implemented in a +backwards-compatible way, so behaviours will not break. From 7a25d39873fefe768f795a9a29b46d0ff74b79d4 Mon Sep 17 00:00:00 2001 From: Nadav Kavalerchik Date: Thu, 17 Nov 2011 11:28:07 +1300 Subject: [PATCH 18/21] MDL-27516 Several CSS fixes for right to left languages --- mod/quiz/styles.css | 9 ++++- mod/wiki/styles.css | 4 ++ theme/base/style/core.css | 69 +++++++++++++++++++++++++++++++++++ theme/base/style/course.css | 2 +- theme/standard/style/core.css | 2 + webservice/renderer.php | 13 ++++++- 6 files changed, 95 insertions(+), 4 deletions(-) diff --git a/mod/quiz/styles.css b/mod/quiz/styles.css index 60d83d46150ff..f96340959e21e 100644 --- a/mod/quiz/styles.css +++ b/mod/quiz/styles.css @@ -96,6 +96,13 @@ div.editq div.question div.content .singlequestion a .questiontext{text-decorati #page-mod-quiz-mod #reviewoptionshdr fieldset.fgroup span label, #adminquizreviewoptions span label {margin-left: 0.4em;} +#page-mod-quiz-mod.dir-rtl #reviewoptionshdr .fitem, +#adminquizreviewoptions .group {float: right; width: 24%;} +#page-mod-quiz-mod.dir-rtl #reviewoptionshdr fieldset.fgroup span, +#adminquizreviewoptions span {float: right; clear: right;} +#page-mod-quiz-mod.dir-rtl #reviewoptionshdr .fitemtitle, +#adminquizreviewoptions .fitemtitle {text-align: right;} + /** Mod quiz view **/ #page-mod-quiz-view .quizinfo, #page-mod-quiz-view #page .quizgradefeedback, @@ -377,4 +384,4 @@ bank window's title is prominent enough*/ .qnum label {padding-right: 0.25em;} /** settings.php */ -#adminquizreviewoptions {margin-bottom: 0.5em;} +#adminquizreviewoptions {margin-bottom: 0.5em;} \ No newline at end of file diff --git a/mod/wiki/styles.css b/mod/wiki/styles.css index 18e0391422e8a..dcfd4804bbdd9 100644 --- a/mod/wiki/styles.css +++ b/mod/wiki/styles.css @@ -171,6 +171,10 @@ float: right; } +.dir-rtl .wiki_diffuserleft { + float: left; +} + .wiki_diffuserright { float: left; } diff --git a/theme/base/style/core.css b/theme/base/style/core.css index 4976044d817e3..3abeb99b9cfef 100644 --- a/theme/base/style/core.css +++ b/theme/base/style/core.css @@ -218,6 +218,8 @@ a.skip:active {position: static;display: block;} .mform .ftags label.accesshide {display: block;position: static;} .mform .ftags select {margin-bottom: 0.7em;min-width: 22em;} +input#id_externalurl {direction:ltr;} + /** Browser corrections for mforms **/ .ie .mform .fitem .felement {margin-left:0;text-align:left;float:left;} /** Fix IE double margin + float bugs **/ @@ -720,6 +722,23 @@ body.tag .managelink {padding: 5px;} .mod-indent-15, .mod-indent-huge {margin-left:300px;} +.dir-rtl .mod-indent-1 {margin-right:20px;margin-left:0;} +.dir-rtl .mod-indent-2 {margin-right:40px;margin-left:0;} +.dir-rtl .mod-indent-3 {margin-right:60px;margin-left:0;} +.dir-rtl .mod-indent-4 {margin-right:80px;margin-left:0;} +.dir-rtl .mod-indent-5 {margin-right:100px;margin-left:0;} +.dir-rtl .mod-indent-6 {margin-right:120px;margin-left:0;} +.dir-rtl .mod-indent-7 {margin-right:140px;margin-left:0;} +.dir-rtl .mod-indent-8 {margin-right:160px;margin-left:0;} +.dir-rtl .mod-indent-9 {margin-right:180px;margin-left:0;} +.dir-rtl .mod-indent-10 {margin-right:200px;margin-left:0;} +.dir-rtl .mod-indent-11 {margin-right:220px;margin-left:0;} +.dir-rtl .mod-indent-12 {margin-right:240px;margin-left:0;} +.dir-rtl .mod-indent-13 {margin-right:260px;margin-left:0;} +.dir-rtl .mod-indent-14 {margin-right:280px;margin-left:0;} +.dir-rtl .mod-indent-15, +.dir-rtl .mod-indent-huge {margin-right:300px;margin-left:0;} + .dir-rtl .felement.feditor select {margin-right:18.75%;} /* Resourcelib mp3 player size: only width could be changed here, height hardcoded in JS */ @@ -804,3 +823,53 @@ ul li, ol li, .course-content ul.weeks .content .summary ol li, .course-content ul.topics .content .summary ol li {list-style: decimal outside none;} + +.dir-rtl #adminsettings #id_s__pathtodu, +.dir-rtl #adminsettings #id_s__aspellpath, +.dir-rtl #adminsettings #id_s__pathtodot, +.dir-rtl #adminsettings #id_s__supportemail, +.dir-rtl #adminsettings #id_s__supportpage, +.dir-rtl #adminsettings #id_s__sessioncookie, +.dir-rtl #adminsettings #id_s__sessioncookiepath, +.dir-rtl #adminsettings #id_s__sessioncookiedomain, +.dir-rtl #adminsettings #id_s__proxyhost, +.dir-rtl #adminsettings #id_s__proxyuser, +.dir-rtl #adminsettings #id_s__proxypassword, +.dir-rtl #adminsettings #id_s__proxybypass, +.dir-rtl #adminsettings #id_s__jabberhost, +.dir-rtl #adminsettings #id_s__jabberserver, +.dir-rtl #adminsettings #id_s__jabberusername, +.dir-rtl #adminsettings #id_s__jabberpassword, +.dir-rtl #adminsettings #id_s__additionalhtmlhead, +.dir-rtl #adminsettings #id_s__additionalhtmltopofbody, +.dir-rtl #adminsettings #id_s__additionalhtmlfooter, +.dir-rtl #adminsettings #id_s__docroot, +.dir-rtl #adminsettings #id_s__filter_tex_latexpreamble, +.dir-rtl #adminsettings #id_s__filter_tex_latexbackground, +.dir-rtl #adminsettings #id_s__filter_tex_pathlatex, +.dir-rtl #adminsettings #id_s__filter_tex_pathdvips, +.dir-rtl #adminsettings #id_s__filter_tex_pathconvert, +.dir-rtl #adminsettings #id_s__blockedip, +.dir-rtl #adminsettings #id_s__pathtoclam, +.dir-rtl #adminsettings #id_s__quarantinedir, +.dir-rtl #adminsettings #id_s__sitepolicy, +.dir-rtl #adminsettings #id_s__sitepolicyguest, +.dir-rtl #adminsettings #id_s__cronremotepassword, +.dir-rtl #adminsettings #id_s__allowedip, +.dir-rtl #adminsettings #id_s__blockedip, +.dir-rtl #adminsettings #id_s_enrol_meta_nosyncroleids, +.dir-rtl #adminsettings #id_s_enrol_ldap_host_url, +.dir-rtl #adminsettings #id_s_enrol_ldap_ldapencoding, +.dir-rtl #adminsettings #id_s_enrol_ldap_bind_dn, +.dir-rtl #adminsettings #id_s_enrol_ldap_bind_pw, +.dir-rtl #adminsettings #admin-emoticons .form-text, +.dir-rtl #adminsettings #admin-role_mapping input[type=text], +.dir-rtl #adminsettings #id_s_enrol_paypal_paypalbusiness, +.dir-rtl #adminsettings #id_s_enrol_flatfile_location, +#page-admin-setting-enrolsettingsflatfile.dir-rtl input[type=text], +#page-admin-setting-enrolsettingsdatabase.dir-rtl input[type=text], +#page-admin-auth-db.dir-rtl input[type=text] {direction: ltr;} + +#page-admin-setting-enrolsettingsflatfile.dir-rtl .informationbox {direction: ltr;text-align: left;} + +#page-admin-grade-edit-scale-edit.dir-rtl .error input#id_name {margin-right: 170px;} \ No newline at end of file diff --git a/theme/base/style/course.css b/theme/base/style/course.css index 3062ac629a0b5..37f9792bf8760 100644 --- a/theme/base/style/course.css +++ b/theme/base/style/course.css @@ -27,7 +27,7 @@ .path-course-view li.activity form.togglecompletion .ajaxworking {position:absolute;top:0; left:20px;width: 20px; height: 20px;background: url([[pix:i/ajaxloader]]) no-repeat;} .dir-rtl.path-course-view li.activity {margin-right:0px;margin-left:20px;} .dir-rtl.path-course-view li.activity form.togglecompletion, -.dir-rtl.path-course-view li.activity span.autocompletion {right:auto;left:-20px;} +.dir-rtl.path-course-view li.activity span.autocompletion {right:auto;right:-20px;} .section img.movetarget {height:16px;width:80px;} diff --git a/theme/standard/style/core.css b/theme/standard/style/core.css index 12cf9d885144b..4b69618ca9fa5 100644 --- a/theme/standard/style/core.css +++ b/theme/standard/style/core.css @@ -277,6 +277,8 @@ h2.tag-heading {text-align:center;margin-left:auto;margin-right:auto;width:95%;} #tags-management-links, .tag .managelink {text-align:right;} table#tag-management-list {margin: 10px auto;width: 80%;} +#page-tag-index.dir-rtl .relatedpages {text-align:center;} +#page-tag-index.dir-rtl .user-box {float:right;} /** * Overriding base diff --git a/webservice/renderer.php b/webservice/renderer.php index 37b993561ff46..75668fd6a8aca 100644 --- a/webservice/renderer.php +++ b/webservice/renderer.php @@ -46,15 +46,24 @@ public function admin_authorised_user_selector(&$options) { $table->cellspacing = 0; $table->cellpadding = 0; + // LTR/RTL support, for drawing button arrows in the right direction + if (right_to_left()) { + $addarrow = '▶'; + $removearrow = '◀'; + } else { + $addarrow = '◀'; + $removearrow = '▶'; + } + //create the add and remove button $addinput = html_writer::empty_tag('input', array('name' => 'add', 'id' => 'add', 'type' => 'submit', - 'value' => '◀' . ' ' . get_string('add'), + 'value' => $addarrow . ' ' . get_string('add'), 'title' => get_string('add'))); $addbutton = html_writer::tag('div', $addinput, array('id' => 'addcontrols')); $removeinput = html_writer::empty_tag('input', array('name' => 'remove', 'id' => 'remove', 'type' => 'submit', - 'value' => '▶' . ' ' . get_string('remove'), + 'value' => $removearrow . ' ' . get_string('remove'), 'title' => get_string('remove'))); $removebutton = html_writer::tag('div', $removeinput, array('id' => 'removecontrols')); From 0850e6301a7abb9b9f2a72cffdb9cc39eeb0e8b6 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Thu, 17 Nov 2011 08:02:20 +0000 Subject: [PATCH 19/21] MDL-30182 fix missing include. Sorry. --- mod/quiz/grade.php | 1 + 1 file changed, 1 insertion(+) diff --git a/mod/quiz/grade.php b/mod/quiz/grade.php index 9334731706fa3..ddc8c07ef9106 100644 --- a/mod/quiz/grade.php +++ b/mod/quiz/grade.php @@ -26,6 +26,7 @@ require_once(dirname(__FILE__) . '/../../config.php'); +require_once($CFG->dirroot . '/mod/quiz/locallib.php'); require_once($CFG->dirroot . '/mod/quiz/report/reportlib.php'); From 8a9426bc17e4cd38bddafc5870f2a9c631c50cc7 Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Thu, 17 Nov 2011 20:10:02 +0100 Subject: [PATCH 20/21] MDL-29350 Prevent memory/time problems if there are zillions of combinations --- lib/db/upgrade.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index 097cfb10066f6..75e308827069c 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -6917,15 +6917,17 @@ function xmldb_main_upgrade($oldversion) { } if ($oldversion < 2011111500.01) { + upgrade_set_timeout(60*20); // this may take a while // Remove duplicate entries from groupings_groups table $sql = 'SELECT MIN(id) AS firstid, groupingid, groupid FROM {groupings_groups} '. 'GROUP BY groupingid, groupid HAVING COUNT(id)>1'; - $badrecs = $DB->get_records_sql($sql); - foreach ($badrecs as $badrec) { + $badrs = $DB->get_recordset_sql($sql); + foreach ($badrs as $badrec) { $where = 'groupingid = ? and groupid = ? and id > ?'; $params = array($badrec->groupingid, $badrec->groupid, $badrec->firstid); $DB->delete_records_select('groupings_groups', $where, $params); } + $badrs->close(); // Main savepoint reached upgrade_main_savepoint(true, 2011111500.01); From fe41ba7489f5a44e7325d20442e01751c7736d0a Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Fri, 18 Nov 2011 01:20:35 +0100 Subject: [PATCH 21/21] on-demand release 2.2beta --- version.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.php b/version.php index 19816d1a81fc9..9642f623bed7b 100644 --- a/version.php +++ b/version.php @@ -30,10 +30,10 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2011111500.01; // YYYYMMDD = weekly release date of this DEV branch +$version = 2011111800.00; // YYYYMMDD = weekly release date of this DEV branch // RR = release increments - 00 in DEV branches // .XX = incremental changes -$release = '2.2beta (Build: 20111115)';// Human-friendly version name +$release = '2.2beta (Build: 20111118)';// Human-friendly version name $maturity = MATURITY_BETA; // this version's maturity level