Merge branch 'master' into install_master
This commit is contained in:
@@ -802,7 +802,14 @@ class restore_groups_structure_step extends restore_structure_step {
|
||||
|
||||
$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() {
|
||||
|
||||
@@ -6916,6 +6916,23 @@ FROM
|
||||
upgrade_main_savepoint(true, 2011110200.02);
|
||||
}
|
||||
|
||||
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';
|
||||
$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);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+7
-2
@@ -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
|
||||
|
||||
+2
-10
@@ -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 = '<img src="' . $OUTPUT->pix_url('icon', $qtype->plugin_name()) . '" alt="' .
|
||||
$namestr . '" title="' . $namestr . '" />';
|
||||
|
||||
return $html;
|
||||
global $PAGE;
|
||||
return $PAGE->get_renderer('question', 'bank')->qtype_icon($question->qtype);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -527,7 +527,7 @@ WHERE
|
||||
$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 @@ WHERE
|
||||
),$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();
|
||||
|
||||
@@ -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 {
|
||||
|
||||
+2
-1
@@ -5943,8 +5943,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)
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 '<span class="questiontype">';
|
||||
print_question_icon($question);
|
||||
echo print_question_icon($question);
|
||||
echo ' ' . question_bank::get_qtype_name($question->qtype) . '</span>';
|
||||
echo '<span class="questionpreview">' .
|
||||
quiz_question_preview_button($quiz, $question, true) . '</span>';
|
||||
@@ -807,7 +807,7 @@ function quiz_print_randomquestion(&$question, &$pageurl, &$quiz, $quiz_qbanktoo
|
||||
}
|
||||
|
||||
echo '<div class="randomquestionfromcategory">';
|
||||
print_question_icon($question);
|
||||
echo print_question_icon($question);
|
||||
print_random_option_icon($question);
|
||||
echo ' ' . get_string('randomfromcategory', 'quiz') . '</div>';
|
||||
|
||||
@@ -886,7 +886,7 @@ function quiz_print_randomquestion(&$question, &$pageurl, &$quiz, $quiz_qbanktoo
|
||||
function quiz_print_singlequestion_reordertool($question, $returnurl, $quiz) {
|
||||
echo '<div class="singlequestion">';
|
||||
echo '<label for="s' . $question->id . '">';
|
||||
print_question_icon($question);
|
||||
echo print_question_icon($question);
|
||||
echo ' ' . quiz_question_tostring($question);
|
||||
echo '</label>';
|
||||
echo '<span class="questionpreview">' .
|
||||
@@ -920,7 +920,7 @@ function quiz_print_randomquestion_reordertool(&$question, &$pageurl, &$quiz) {
|
||||
echo '<div class="quiz_randomquestion">';
|
||||
echo '<div class="randomquestionfromcategory">';
|
||||
echo $reordercheckboxlabel;
|
||||
print_question_icon($question);
|
||||
echo print_question_icon($question);
|
||||
print_random_option_icon($question);
|
||||
|
||||
if ($questioncount == 0) {
|
||||
|
||||
+57
-16
@@ -26,27 +26,68 @@
|
||||
|
||||
|
||||
require_once(dirname(__FILE__) . '/../../config.php');
|
||||
require_once($CFG->dirroot . '/mod/quiz/locallib.php');
|
||||
require_once($CFG->dirroot . '/mod/quiz/report/reportlib.php');
|
||||
|
||||
|
||||
$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(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)));
|
||||
$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)));
|
||||
}
|
||||
|
||||
// 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) {
|
||||
|
||||
// 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))));
|
||||
|
||||
+1
-1
@@ -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');
|
||||
|
||||
@@ -621,13 +621,21 @@ abstract class quiz_attempt_report_table extends table_sql {
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -101,7 +101,7 @@ if ($lastattempt && !$lastattempt->timefinish) {
|
||||
$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)) {
|
||||
|
||||
+8
-1
@@ -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;}
|
||||
@@ -61,7 +61,7 @@ $messages = $accessmanager->prevent_access();
|
||||
$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));
|
||||
|
||||
+1
-1
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -171,6 +171,10 @@
|
||||
float: right;
|
||||
}
|
||||
|
||||
.dir-rtl .wiki_diffuserleft {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.wiki_diffuserright {
|
||||
float: left;
|
||||
}
|
||||
|
||||
@@ -38,8 +38,8 @@ defined('MOODLE_INTERNAL') || die();
|
||||
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() {
|
||||
|
||||
@@ -70,21 +70,39 @@ 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.
|
||||
*
|
||||
* 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) {
|
||||
$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.
|
||||
* 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.
|
||||
*/
|
||||
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
|
||||
|
||||
@@ -40,8 +40,8 @@ defined('MOODLE_INTERNAL') || die();
|
||||
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() {
|
||||
|
||||
@@ -42,8 +42,8 @@ defined('MOODLE_INTERNAL') || die();
|
||||
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() {
|
||||
|
||||
@@ -39,8 +39,8 @@ defined('MOODLE_INTERNAL') || die();
|
||||
*/
|
||||
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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -64,8 +64,8 @@ require_once(dirname(__FILE__) . '/../interactive/behaviour.php');
|
||||
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) {
|
||||
|
||||
@@ -45,8 +45,9 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @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) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -1793,7 +1793,7 @@ function print_qtype_to_add_option($qtype) {
|
||||
echo '<span class="qtypename">';
|
||||
$fakequestion = new stdClass();
|
||||
$fakequestion->qtype = $qtype->name();
|
||||
print_question_icon($fakequestion);
|
||||
echo print_question_icon($fakequestion);
|
||||
echo $qtype->menu_name() . '</span><span class="qtypesummary">' . $summary;
|
||||
echo "</span></label>\n";
|
||||
echo "</div>\n";
|
||||
|
||||
+35
-26
@@ -865,33 +865,42 @@ ORDER BY
|
||||
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
|
||||
/**
|
||||
* 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 {question_attempts} {$alias}qa
|
||||
JOIN {question_attempt_steps} {$alias}qas ON
|
||||
{$alias}qas.id = {$this->latest_step_for_qa_subquery($alias . 'qa.id')}
|
||||
) $alias";
|
||||
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') {
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
}
|
||||
@@ -344,7 +344,7 @@ abstract class question_edit_form extends moodleform {
|
||||
$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 @@ abstract class question_edit_form extends moodleform {
|
||||
$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'));
|
||||
}
|
||||
|
||||
|
||||
@@ -264,7 +264,7 @@ class qtype_numerical_edit_form extends question_edit_form {
|
||||
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');
|
||||
}
|
||||
|
||||
@@ -641,16 +641,17 @@ class qtype_numerical_answer_processor {
|
||||
|
||||
$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;
|
||||
|
||||
@@ -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;}
|
||||
@@ -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;}
|
||||
|
||||
|
||||
@@ -380,7 +380,7 @@ class theme_mymobile_core_renderer extends core_renderer {
|
||||
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 @@ class theme_mymobile_core_renderer extends core_renderer {
|
||||
}
|
||||
if (isguestuser()) {
|
||||
$loggedinas = $realuserinfo.get_string('loggedinasguest');
|
||||
if (!$loginapge) {
|
||||
if (!$loginpage) {
|
||||
$loggedinas .= " (<a href=\"$loginurl\">".get_string('login').'</a>)';
|
||||
}
|
||||
} else if (is_role_switched($course->id)) { // Has switched roles
|
||||
@@ -421,7 +421,7 @@ class theme_mymobile_core_renderer extends core_renderer {
|
||||
}
|
||||
} else {
|
||||
$loggedinas = get_string('loggedinnot', 'moodle');
|
||||
if (!$loginapge) {
|
||||
if (!$loginpage) {
|
||||
$loggedinas .= " (<a href=\"$loginurl\">".get_string('login').'</a>)';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
+2
-2
@@ -30,10 +30,10 @@
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
|
||||
$version = 2011111500.00; // 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
|
||||
|
||||
+11
-2
@@ -46,15 +46,24 @@ class core_webservice_renderer extends plugin_renderer_base {
|
||||
$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'));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user