--- /dev/null
+#page-admin-tool-unittest-index .exception pre {padding: 8px;}
+#page-admin-tool-unittest-index .unittestsummary {padding: 8px;margin-top: 1em;}
+#page-admin-tool-unittest-index span.notice {color: teal;}
+#page-admin-tool-unittest-index b.pass {color: green;}
+#page-admin-tool-unittest-index b.fail, b.exception {color: red;}
+#page-admin-tool-unittest-index .exception, .exception pre {background-color: #FDD;}
+#page-admin-tool-unittest-index .unittestsummary {color: white;}
+#page-admin-tool-unittest-index .unittestsummary.failed {background-color: red;}
+#page-admin-tool-unittest-index .unittestsummary.passed {background-color: green;}
--- /dev/null
+<?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/>.
+
+/**
+ * @package xmldb-editor
+ * @copyright 2011 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * This class will check all the varchar2() columns
+ * in the Moodle installed DB, looking for incorrect (INT)
+ * length semanticas providing one SQL script to fix all
+ * them by changing to cross-db (CHAR) length semantics.
+ * See MDL-29322 for more details.
+ *
+ * @package xmldb-editor
+ * @copyright 2011 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class check_oracle_semantics extends XMLDBCheckAction {
+
+ /**
+ * Init method, every subclass will have its own
+ */
+ function init() {
+ $this->introstr = 'confirmcheckoraclesemantics';
+ parent::init();
+
+ // Set own core attributes
+
+ // Set own custom attributes
+
+ // Get needed strings
+ $this->loadStrings(array(
+ 'wrongoraclesemantics' => 'tool_xmldb',
+ 'nowrongoraclesemanticsfound' => 'tool_xmldb',
+ 'yeswrongoraclesemanticsfound' => 'tool_xmldb',
+ 'expected' => 'tool_xmldb',
+ 'actual' => 'tool_xmldb',
+ ));
+ }
+
+ protected function check_table(xmldb_table $xmldb_table, array $metacolumns) {
+ global $DB;
+ $o = '';
+ $wrong_fields = array();
+
+ // Get and process XMLDB fields
+ if ($xmldb_fields = $xmldb_table->getFields()) {
+ $o .= '<ul>';
+ foreach ($xmldb_fields as $xmldb_field) {
+
+ // Get the type of the column, we only will process CHAR (VARCHAR2) ones
+ if ($xmldb_field->getType() != XMLDB_TYPE_CHAR) {
+ continue;
+ }
+
+ $o.='<li>' . $this->str['field'] . ': ' . $xmldb_field->getName() . ' ';
+
+ // Get current semantic from dictionary, we only will process B (BYTE) ones
+ // suplying the SQL code to change them to C (CHAR) semantic
+ $params = array(
+ 'table_name' => textlib::strtoupper($DB->get_prefix() . $xmldb_table->getName()),
+ 'column_name' => textlib::strtoupper($xmldb_field->getName()),
+ 'data_type' => 'VARCHAR2');
+ $currentsemantic = $DB->get_field_sql('
+ SELECT char_used
+ FROM user_tab_columns
+ WHERE table_name = :table_name
+ AND column_name = :column_name
+ AND data_type = :data_type', $params);
+
+ // If using byte semantics, we'll need to change them to char semantics
+ if ($currentsemantic == 'B') {
+ $info = '(' . $this->str['expected'] . " 'CHAR', " . $this->str['actual'] . " 'BYTE')";
+ $o .= '<font color="red">' . $this->str['wrong'] . " $info</font>";
+ // Add the wrong field to the list
+ $obj = new stdClass();
+ $obj->table = $xmldb_table;
+ $obj->field = $xmldb_field;
+ $wrong_fields[] = $obj;
+ } else {
+ $o .= '<font color="green">' . $this->str['ok'] . '</font>';
+ }
+ $o .= '</li>';
+ }
+ $o .= '</ul>';
+ }
+
+ return array($o, $wrong_fields);
+ }
+
+ protected function display_results(array $wrong_fields) {
+ global $DB;
+ $dbman = $DB->get_manager();
+
+ $s = '';
+ $r = '<table class="generalbox boxaligncenter boxwidthwide" border="0" cellpadding="5" cellspacing="0" id="results">';
+ $r.= ' <tr><td class="generalboxcontent">';
+ $r.= ' <h2 class="main">' . $this->str['searchresults'] . '</h2>';
+ $r.= ' <p class="centerpara">' . $this->str['wrongoraclesemantics'] . ': ' . count($wrong_fields) . '</p>';
+ $r.= ' </td></tr>';
+ $r.= ' <tr><td class="generalboxcontent">';
+
+ // If we have found wrong defaults inform about them
+ if (count($wrong_fields)) {
+ $r.= ' <p class="centerpara">' . $this->str['yeswrongoraclesemanticsfound'] . '</p>';
+ $r.= ' <ul>';
+ foreach ($wrong_fields as $obj) {
+ $xmldb_table = $obj->table;
+ $xmldb_field = $obj->field;
+
+ $r.= ' <li>' . $this->str['table'] . ': ' . $xmldb_table->getName() . '. ' .
+ $this->str['field'] . ': ' . $xmldb_field->getName() . ', ' .
+ $this->str['expected'] . ' ' . "'CHAR'" . ' ' .
+ $this->str['actual'] . ' ' . "'BYTE'" . '</li>';
+
+ $sql = 'ALTER TABLE ' . $DB->get_prefix() . $xmldb_table->getName() . ' MODIFY ' .
+ $xmldb_field->getName() . ' VARCHAR2(' . $xmldb_field->getLength() . ' CHAR)';
+ $sql = $dbman->generator->getEndedStatements($sql);
+ $s.= '<code>' . str_replace("\n", '<br />', $sql) . '</code><br />';
+ }
+ $r.= ' </ul>';
+ // Add the SQL statements (all together)
+ $r.= '<hr />' . $s;
+ } else {
+ $r.= ' <p class="centerpara">' . $this->str['nowrongoraclesemanticsfound'] . '</p>';
+ }
+ $r.= ' </td></tr>';
+ $r.= ' <tr><td class="generalboxcontent">';
+ // Add the complete log message
+ $r.= ' <p class="centerpara">' . $this->str['completelogbelow'] . '</p>';
+ $r.= ' </td></tr>';
+ $r.= '</table>';
+
+ return $r;
+ }
+}
'checkdefaults' => 'tool_xmldb',
'checkforeignkeys' => 'tool_xmldb',
'checkbigints' => 'tool_xmldb',
+ 'checkoraclesemantics' => 'tool_xmldb',
'doc' => 'tool_xmldb',
'viewxml' => 'tool_xmldb',
'pendingchangescannotbesavedreload' => 'tool_xmldb'
if ($DB->get_dbfamily() == 'mysql' || $DB->get_dbfamily() == 'postgres') {
$b .= ' <a href="index.php?action=check_bigints&sesskey=' . sesskey() . '">[' . $this->str['checkbigints'] . ']</a>';
}
+ /// The check semantics button (only for Oracle) MDL-29416
+ if ($DB->get_dbfamily() == 'oracle') {
+ $b .= ' <a href="index.php?action=check_oracle_semantics&sesskey=' . sesskey() . '">[' . $this->str['checkoraclesemantics'] . ']</a>';
+ }
$b .= ' <a href="index.php?action=check_foreign_keys&sesskey=' . sesskey() . '">[' . $this->str['checkforeignkeys'] . ']</a>';
$b .= '</p>';
/// Send buttons to output
Once generated you can copy such statements and execute them safely with your favourite SQL interface (don\'t forget to backup your data before doing that).<br /><br />
It\'s highly recommended to be running the latest (+ version) available of your Moodle release (1.8, 1.9, 2.x ...) before executing the search of missing indexes.<br /><br />
This functionality doesn\'t perform any action against the DB (just reads from it), so can be safely executed at any moment.';
+$string['confirmcheckoraclesemantics'] = 'This functionality will search for <a href="http://tracker.moodle.org/browse/MDL-29322">Oracle varchar2 columns using BYTE semantics</a> in your Moodle server, generating (but not executing!) automatically the needed SQL statements to have all the columns converted to use CHAR semantics instead (better for cross-db compatibility and increased contents max. length).<br /><br />
+Once generated you can copy such statements and execute them safely with your favourite SQL interface (don\'t forget to backup your data before doing that).<br /><br />
+It\'s highly recommended to be running the latest (+ version) available of your Moodle release (2.2, 2.3, 2.x ...) before executing the search of BYTE semantics.<br /><br />
+This functionality doesn\'t perform any action against the DB (just reads from it), so can be safely executed at any moment.';
$string['confirmrevertchanges'] = 'Are you absolutely sure that you want to revert changes performed over:';
$string['create'] = 'Create';
$string['createtable'] = 'Create table:';
$string['check_foreign_keys'] = 'Look for foreign key violations';
$string['checkindexes'] = 'Check indexes';
$string['check_indexes'] = 'Look for missing DB indexes';
+$string['checkoraclesemantics'] = 'Check semantics';
+$string['check_oracle_semantics'] = 'Look for incorrect length semantics';
$string['incorrectfieldname'] = 'Incorrect name';
$string['index'] = 'Index';
$string['indexes'] = 'Indexes';
$string['noviolatedforeignkeysfound'] = 'No violated foreign keys found';
$string['nowrongdefaultsfound'] = 'No inconsistent default values have been found, your DB does not need further actions.';
$string['nowrongintsfound'] = 'No wrong integers have been found, your DB doesn\'t need further actions.';
+$string['nowrongoraclesemanticsfound'] = 'No Oracle columns using BYTE semantics have been found, your DB doesn\'t need further actions.';
$string['numberincorrectdecimals'] = 'Incorrect number of decimals for number field';
$string['numberincorrectlength'] = 'Incorrect length for number field';
$string['pendingchanges'] = 'Note: You have performed changes to this file. They can be saved at any moment.';
$string['wrongints'] = 'Wrong integers found';
$string['wronglengthforenum'] = 'Incorrect length for enum field';
$string['wrongreservedwords'] = 'Currently used reserved words<br />(note that table names aren\'t important if using $CFG->prefix)';
+$string['wrongoraclesemantics'] = 'Wrong Oracle BYTE semantics found';
$string['yesmissingindexesfound'] = 'Some missing indexes have been found in your DB. Here are their details and the needed SQL statements to be executed with your favourite SQL interface to create all them (don\'t forget to backup your data before doing that).<br /><br />After doing that, it\'s highly recommended to execute this utility again to check that no more missing indexes are found.';
$string['yeswrongdefaultsfound'] = 'Some inconsistent defaults have been found in your DB. Here are their details and the needed SQL statements to be executed with your favourite SQL interface to fix them all (don\'t forget to backup your data before doing that).<br /><br />After doing that, it\'s highly recommended to execute this utility again to check that no more inconsistent defaults are found.';
$string['yeswrongintsfound'] = 'Some wrong integers have been found in your DB. Here are their details and the needed SQL statements to be executed with your favourite SQL interface to create all them (don\'t forget to backup your data before doing that).<br /><br />After doing that, it\'s highly recommended to execute this utility again to check that no more wrong integers are found.';
+$string['yeswrongoraclesemanticsfound'] = 'Some Oracle columns using BYTE semantics have been found in your DB. Here are their details and the needed SQL statements to be executed with your favourite SQL interface to create all them (don\'t forget to backup your data before doing that).<br /><br />After doing that, it\'s highly recommended to execute this utility again to check that no more wrong semantics are found.';
$a = new stdClass();
$a->user = fullname($user);
- $a->course = format_string($course->fullname, true, array('context' => get_context_instance(CONTEXT_COURSE, $courseid)));
+ $a->course = format_string($course->fullname, true, array('context' => get_context_instance(CONTEXT_COURSE, $course->id)));
$a->type = get_string('course');
$headers['heading'] = get_string('blogentriesbyuseraboutcourse', 'blog', $a);
$headers['stradd'] = get_string('blogaboutthis', 'blog', $a);
$a = new stdClass();
$a->group = $group->name;
- $a->course = format_string($course->fullname, true, array('context' => get_context_instance(CONTEXT_COURSE, $courseid)));
+ $a->course = format_string($course->fullname, true, array('context' => get_context_instance(CONTEXT_COURSE, $course->id)));
$a->type = get_string('course');
$headers['heading'] = get_string('blogentriesbygroupaboutcourse', 'blog', $a);
$headers['stradd'] = get_string('blogaboutthis', 'blog', $a);
$PAGE->set_heading("$siteshortname: $courseshortname: " . get_string('blogentries', 'blog'));
$a = new stdClass();
$a->type = get_string('course');
- $headers['heading'] = get_string('blogentriesabout', 'blog', format_string($course->fullname, true, array('context' => get_context_instance(CONTEXT_COURSE, $courseid))));
+ $headers['heading'] = get_string('blogentriesabout', 'blog', format_string($course->fullname, true, array('context' => get_context_instance(CONTEXT_COURSE, $course->id))));
$headers['stradd'] = get_string('blogaboutthis', 'blog', $a);
$headers['strview'] = get_string('viewblogentries', 'blog', $a);
$blogurl->remove_params(array('userid'));
*/
require_once($CFG->dirroot . '/blog/locallib.php');
+require_once($CFG->dirroot . '/blog/lib.php');
/**
* Test functions that rely on the DB tables
*/
class bloglib_test extends UnitTestCaseUsingDatabase {
- public static $includecoverage = array('blog/locallib.php');
+ public static $includecoverage = array('blog/locallib.php', 'blog/lib.php');
private $courseid; // To store important ids to be used in tests
private $groupid;
$mform->setType('id', PARAM_INT);
$mform->addElement('header', 'general', get_string('importfile', 'grades'));
+ $mform->disabledIf('url', 'userfile', 'noteq', '');
$mform->addElement('advcheckbox', 'feedback', get_string('importfeedback', 'grades'));
$mform->setDefault('feedback', 0);
$mform->disabledIf('userfile', 'url', 'noteq', '');
$mform->addElement('text', 'url', get_string('fileurl', 'gradeimport_xml'), 'size="80"');
- $mform->disabledIf('url', 'userfile', 'noteq', '');
if (!empty($CFG->gradepublishing)) {
$mform->addElement('header', 'publishing', get_string('publishing', 'grades'));
api: M.cfg.wwwroot+'/repository/draftfiles_ajax.php',
menus: {},
initializer: function(options) {
- //For client side validation, remove hidden draft_id
- Y.one('#id_'+options.elementname).set('value', '');
-
this.options = options;
if (options.mainfile) {
this.enablemainfile = options.mainfile;
this.filepicker_options.maxbytes = this.maxbytes;
this.filepicker_options.env = 'filemanager';
this.filepicker_options.itemid = options.itemid;
- this.filepicker_options.elementname = options.elementname;
if (options.filecount) {
this.filecount = options.filecount;
button_addfile.setStyle('display', 'none');
}
this.refresh(this.currentpath);
- //When file is added then set draftid for validation
- var elementname = M.core_filepicker.instances[this.client_id].options.elementname;
- var itemid = M.core_filepicker.instances[this.client_id].options.itemid;
- Y.one('#id_'+elementname).set('value', itemid);
- //generate event to indicate changes which will be used by disable if code.
- Y.one('#id_'+elementname).simulate('change');
},
refresh: function(filepath) {
var scope = this;
if (!empty($options['maxbytes'])) {
$this->_options['maxbytes'] = get_max_upload_file_size($CFG->maxbytes, $options['maxbytes']);
}
- $this->_type = 'filemanager';
parent::HTML_QuickForm_element($elementName, $elementLabel, $attributes);
}
$options->accepted_types = $accepted_types;
$options->return_types = FILE_INTERNAL;
$options->context = $PAGE->context;
- $options->elementname = $elname;
$html = $this->_getTabs();
$html .= form_filemanager_render($options);
- $html .= '<input id="id_'.$elname.'" value="'.$draftitemid.'" name="'.$elname.'" type="hidden" class="filemanagerhidden"/>';
+ $html .= '<input value="'.$draftitemid.'" name="'.$elname.'" type="hidden" />';
+ // label element needs 'for' attribute work
+ $html .= '<input value="" id="id_'.$elname.'" type="hidden" />';
+
return $html;
}
}
$module = array(
'name'=>'form_filemanager',
'fullpath'=>'/lib/form/filemanager.js',
- 'requires' => array('core_filepicker', 'base', 'io-base', 'node', 'node-event-simulate', 'json', 'yui2-button', 'yui2-container', 'yui2-layout', 'yui2-menu', 'yui2-treeview'),
+ 'requires' => array('core_filepicker', 'base', 'io-base', 'node', 'json', 'yui2-button', 'yui2-container', 'yui2-layout', 'yui2-menu', 'yui2-treeview'),
'strings' => array(array('loading', 'repository'), array('nomorefiles', 'repository'), array('confirmdeletefile', 'repository'),
array('add', 'repository'), array('accessiblefilepicker', 'repository'), array('move', 'moodle'),
array('cancel', 'moodle'), array('download', 'moodle'), array('ok', 'moodle'),
M.form_filepicker.callback = function(params) {
var html = '<a href="'+params['url']+'">'+params['file']+'</a>';
document.getElementById('file_info_'+params['client_id']).innerHTML = html;
- //When file is added then set draftid for validation
- var elementname = M.core_filepicker.instances[params['client_id']].options.elementname;
- var itemid = M.core_filepicker.instances[params['client_id']].options.itemid;
- M.form_filepicker.YUI.one('#id_'+elementname).set('value', itemid);
- //generate event to indicate changes which will be used by disable if code.
- M.form_filepicker.YUI.one('#id_'+elementname).simulate('change');
};
/**
* This fucntion is called for each file picker on page.
*/
M.form_filepicker.init = function(Y, options) {
- //For client side validation, remove hidden draft_id
- M.form_filepicker.YUI = Y;
- Y.one('#id_'+options.elementname).set('value', '');
options.formcallback = M.form_filepicker.callback;
if (!M.core_filepicker.instances[options.client_id]) {
M.core_filepicker.init(Y, options);
if (!empty($options['maxbytes'])) {
$this->_options['maxbytes'] = get_max_upload_file_size($CFG->maxbytes, $options['maxbytes']);
}
- $this->_type = 'filepicker';
parent::HTML_QuickForm_input($elementName, $elementLabel, $attributes);
}
$args->maxbytes = $this->_options['maxbytes'];
$args->context = $PAGE->context;
$args->buttonname = $elname.'choose';
- $args->elementname = $elname;
$html = $this->_getTabs();
$fp = new file_picker($args);
$options = $fp->options;
$options->context = $PAGE->context;
- $fp->options->elementname = $elname;
$html .= $OUTPUT->render($fp);
$html .= '<input type="hidden" name="'.$elname.'" id="'.$id.'" value="'.$draftitemid.'" class="filepickerhidden"/>';
- $module = array('name'=>'form_filepicker', 'fullpath'=>'/lib/form/filepicker.js', 'requires'=>array('core_filepicker', 'node', 'node-event-simulate'));
+ $module = array('name'=>'form_filepicker', 'fullpath'=>'/lib/form/filepicker.js', 'requires'=>array('core_filepicker'));
$PAGE->requires->js_init_call('M.form_filepicker.init', array($fp->options), true, $module);
$nonjsfilepicker = new moodle_url('/repository/draftfiles_manager.php', array(
<?php
+require_once('HTML/QuickForm/input.php');
+
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
}
}
- /**
- * Internal method. Validates filepicker and filemanager files if they are
- * set as required fields. Also, sets the error message if encountered one.
- *
- * @return bool/array with errors
- */
- protected function validate_draft_files() {
- global $USER;
- $mform =& $this->_form;
-
- $errors = array();
- //Go through all the required elements and make sure you hit filepicker or
- //filemanager element.
- foreach ($mform->_rules as $elementname => $rules) {
- $elementtype = $mform->getElementType($elementname);
- //If element is of type filepicker then do validation
- if (($elementtype == 'filepicker') || ($elementtype == 'filemanager')){
- //Check if rule defined is required rule
- foreach ($rules as $rule) {
- if ($rule['type'] == 'required') {
- $draftid = (int)$mform->getSubmitValue($elementname);
- $fs = get_file_storage();
- $context = get_context_instance(CONTEXT_USER, $USER->id);
- if (!$files = $fs->get_area_files($context->id, 'user', 'draft', $draftid, 'id DESC', false)) {
- $errors[$elementname] = $rule['message'];
- }
- }
- }
- }
- }
- if (empty($errors)) {
- return true;
- } else {
- return $errors;
- }
- }
-
/**
* Load in existing data as form defaults. Usually new entry defaults are stored directly in
* form definition (new entry form); this function is used to load in data where values
$files = array();
$file_val = $this->_validate_files($files);
- //check draft files for validation and flag them if required files
- //are not in draft area.
- $draftfilevalue = $this->validate_draft_files();
-
- if ($file_val !== true && $draftfilevalue !== true) {
- $file_val = array_merge($file_val, $draftfilevalue);
- } else if ($draftfilevalue !== true) {
- $file_val = $draftfilevalue;
- } //default is file_val, so no need to assign.
-
if ($file_val !== true) {
if (!empty($file_val)) {
foreach ($file_val as $element=>$msg) {
if (!$form->isFrozen()) {
$args = $form->getLockOptionObject();
if (count($args[1]) > 0) {
- $PAGE->requires->js_init_call('M.form.initFormDependencies', $args, true, moodleform::get_js_module());
+ $PAGE->requires->js_init_call('M.form.initFormDependencies', $args, false, moodleform::get_js_module());
}
}
}
public function test_pagetype_defaults_to_script() {
// Exercise SUT and validate
- $this->assertEqual('admin-report-unittest-index', $this->testpage->pagetype);
+ $this->assertEqual('admin-tool-unittest-index', $this->testpage->pagetype);
}
public function test_set_pagetype() {
// Exercise SUT
$this->testpage->initialise_default_pagetype('admin/tool/unittest/index.php');
// Validate
- $this->assertEqual('admin-report-unittest-index', $this->testpage->pagetype);
+ $this->assertEqual('admin-tool-unittest-index', $this->testpage->pagetype);
}
public function test_initialise_default_pagetype_fp() {
echo $OUTPUT->footer();
-?>
\ No newline at end of file
return $textlib->convert($text, $enc);
}
}
-?>
\ No newline at end of file
echo $OUTPUT->footer();
-?>
\ No newline at end of file
echo $OUTPUT->footer();
-?>
\ No newline at end of file
}
if(has_capability('moodle/course:bulkmessaging', $coursecontext)) {
$usehtmleditor = can_use_html_editor();
- echo '<br /><div class="buttons">';
+ echo '<div class="buttons"><br />';
echo '<input type="button" id="checkall" value="'.get_string('selectall').'" /> ';
echo '<input type="button" id="checknone" value="'.get_string('deselectall').'" /> ';
- echo '</div';
+ echo '</div>';
echo '<fieldset class="clearfix">';
echo '<legend class="ftoggler">'.get_string('send_message', 'feedback').'</legend>';
echo '<div><label for="feedback_subject">'.get_string('subject', 'feedback').' </label><input type="text" id="feedback_subject" size="50" maxlength="255" name="subject" value="'.$subject.'" /></div>';
echo '<br /><div class="buttons">';
echo '<input type="submit" name="send_message" value="'.get_string('send', 'feedback').'" />';
echo '</div>';
- echo '</fieldset>';
echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
echo '<input type="hidden" name="action" value="sendmessage" />';
echo '<input type="hidden" name="id" value="'.$id.'" />';
+ echo '</fieldset>';
echo '</form>';
//include the needed js
$module = array('name'=>'mod_feedback', 'fullpath'=>'/mod/feedback/feedback.js');
echo $OUTPUT->footer();
-?>
\ No newline at end of file
$records = $data->numerrors; // data to be saved into {workshopform_numerrors}
$mappings = $data->mappings; // data to be saved into {workshopform_numerrors_map}
$todelete = array(); // dimension ids to be deleted
+ $maxnonegative = 0; // maximum number of (weighted) negative responses
for ($i=0; $i < $norepeats; $i++) {
$record = $records[$i];
// exiting field
$DB->update_record('workshopform_numerrors', $record);
}
+ $maxnonegative += $record->weight;
// re-save with correct path to embeded media files
$record = file_postupdate_standard_editor($record, 'description', $this->descriptionopts, $PAGE->context,
'workshopform_numerrors', 'description', $record->id);
$insql = '';
}
$sql = "DELETE FROM {workshopform_numerrors_map}
- WHERE (($insql nonegative > :nodimensions) AND (workshopid = :workshopid))";
- $params['nodimensions'] = $norepeats;
+ WHERE (($insql nonegative > :maxnonegative) AND (workshopid = :workshopid))";
+ $params['maxnonegative'] = $maxnonegative;
$params['workshopid'] = $this->workshop->id;
$DB->execute($sql, $params);
}
$mform->addElement('text', 'maxmark', get_string('markedoutof', 'question'),
array('size' => '5'));
- $mform->setType('maxmark', PARAM_NUMBER);
+ $mform->setType('maxmark', PARAM_FLOAT);
if ($this->_customdata['maxvariant'] > 1) {
$variants = range(1, $this->_customdata['maxvariant']);
$mform->addElement('select', 'variant', get_string('questionvariant', 'question'),
array_combine($variants, $variants));
}
- $mform->setType('maxmark', PARAM_INT);
+ $mform->setType('variant', PARAM_INT);
$mform->addElement('select', 'correctness', get_string('whethercorrect', 'question'),
$hiddenofvisible);
$mform->addElement('text', 'defaultmark', get_string('defaultmark', 'question'),
array('size' => 3));
- $mform->setType('defaultmark', PARAM_INT);
+ $mform->setType('defaultmark', PARAM_FLOAT);
$mform->setDefault('defaultmark', 1);
$mform->addRule('defaultmark', null, 'required', null, 'client');
protected $testtables = array(
'lib' => array(
- 'rating', 'scale'));
+ 'rating', 'scale', 'context', 'capabilities', 'role_assignments', 'role_capabilities', 'course'));
+
+ protected $syscontext;
+ protected $neededcaps = array('view', 'viewall', 'viewany', 'rate');
+ protected $originaldefaultfrontpageroleid;
public function setUp() {
+ global $CFG;
parent::setUp();
- $this->switch_to_test_db(); // Switch to test DB for all the execution
+ // Make sure accesslib has cached a sensible system context object
+ // before we switch to the test DB.
+ $this->syscontext = get_context_instance(CONTEXT_SYSTEM);
foreach ($this->testtables as $dir => $tables) {
$this->create_test_tables($tables, $dir); // Create tables
}
+
+ $this->switch_to_test_db(); // Switch to test DB for all the execution
+
+ $this->fill_records();
+
+ // Ignore any frontpageroleid, that would require to crete more contexts
+ $this->originaldefaultfrontpageroleid = $CFG->defaultfrontpageroleid;
+ $CFG->defaultfrontpageroleid = null;
+ }
+
+ public function tearDown() {
+ global $CFG;
+ // Recover original frontpageroleid
+ $CFG->defaultfrontpageroleid = $this->originaldefaultfrontpageroleid;
+ parent::tearDown();
+ }
+
+ private function fill_records() {
+ global $DB;
+
+ // Set up systcontext in the test database.
+ $this->syscontext->id = $this->testdb->insert_record('context', $this->syscontext);
+
+ // Add the capabilities used by ratings
+ foreach ($this->neededcaps as $neededcap) {
+ $this->testdb->insert_record('capabilities', (object)array('name' => 'moodle/rating:' . $neededcap,
+ 'contextlevel' => CONTEXT_COURSE));
+ }
}
/**
function test_get_ratings_sql() {
// We load 3 items. Each is rated twice. For simplicity itemid == user id of the item owner
- $ctxid = SYSCONTEXTID;
+ $ctxid = $this->syscontext->id;
$this->load_test_data('rating',
array('contextid', 'component', 'ratingarea', 'itemid', 'scaleid', 'rating', 'userid', 'timecreated', 'timemodified'), array(
// Prepare the default options
$defaultoptions = array (
- 'context' => get_context_instance(CONTEXT_SYSTEM),
+ 'context' => $this->syscontext,
'component' => 'mod_forum',
'ratingarea' => 'post',
'scaleid' => 10,
'aggregate' => RATING_AGGREGATE_AVERAGE);
- $rm = new rating_manager();
+ $rm = new mockup_rating_manager();
// STEP 1: Retreive ratings using the current user
$this->assertEqual($result[0]->rating->aggregate, 3);//should still get the aggregate
}
}
+
+/**
+ * rating_manager subclass for unit testing without requiring capabilities to be loaded
+ */
+class mockup_rating_manager extends rating_manager {
+
+ /**
+ * Overwrite get_plugin_permissions_array() so it always return granted perms for unit testing
+ */
+ public function get_plugin_permissions_array($contextid, $component, $ratingarea) {
+ return array(
+ 'rate' => true,
+ 'view' => true,
+ 'viewany' => true,
+ 'viewall' => true);
+ }
+
+}
#page-admin-course-index .editcourse td {padding-left:10px;padding-right:10px;}
#page-admin-course-index .editcourse .count {text-align:right;}
-#page-admin-report-unittest-index .exception pre {padding: 8px;}
-#page-admin-report-unittest-index .unittestsummary {padding: 8px;margin-top: 1em;}
-#page-admin-report-unittest-index span.notice {color: teal;}
-#page-admin-report-unittest-index b.pass {color: green;}
-#page-admin-report-unittest-index b.fail, b.exception {color: red;}
-#page-admin-report-unittest-index .exception, .exception pre {background-color: #FDD;}
-#page-admin-report-unittest-index .unittestsummary {color: white;}
-#page-admin-report-unittest-index .unittestsummary.failed {background-color: red;}
-#page-admin-report-unittest-index .unittestsummary.passed {background-color: green;}
-
#page-admin-report-security-index .timewarninghidden {display:none;}
#page-admin-report-security-index .statuswarning {background-color: #f0e000;}
#page-admin-report-security-index .statusserious {background-color: #f07000;}
.course-report-outline td.lastaccess {font-size: 0.8em;}
#page-admin-uploaduser table#uuresults {font-size: 0.9em;}
#page-admin-auth_config .required {background-color:#DDDDDD;}
-#page-admin-report-unittest-index .sep {color:#AAAAAA;}
+#page-admin-tool-unittest-index .sep {color:#AAAAAA;}
.path-admin-roles .capabilitysearchui {text-align:center;margin:0.5em;}
.path-admin .rolecap .cap-name,
// RR = release increments - 00 in DEV branches
// .XX = incremental changes
-$release = '2.2dev (Build: 20110921)'; // Human-friendly version name
+$release = '2.2dev (Build: 20110925)'; // Human-friendly version name
$maturity = MATURITY_ALPHA; // this version's maturity level