//We need dataroot before lang download
-$dataroot = clean_param($options['dataroot'], PARAM_PATH);
-if ($dataroot !== $options['dataroot']) {
- $a = (object)array('option' => 'dataroot', 'value' => $options['dataroot']);
- cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
-}
-$CFG->dataroot = $dataroot;
+$CFG->dataroot = $options['dataroot'];
if ($interactive) {
cli_separator();
$i=0;
}
echo str_pad($table->name, 40). " - ";
- $DB->change_database_structure("ALTER TABLE {$table->name} TYPE = $engine");
+ $DB->change_database_structure("ALTER TABLE {$table->name} ENGINE = $engine");
echo "DONE\n";
$converted++;
}
$PAGE->set_pagelayout('maintenance');
$PAGE->set_popup_notification_allowed(false);
+ if (upgrade_stale_php_files_present()) {
+ $PAGE->set_title($stradministration);
+ $PAGE->set_cacheable(false);
+
+ $output = $PAGE->get_renderer('core', 'admin');
+ echo $output->upgrade_stale_php_files_page();
+ die();
+ }
+
if (empty($confirmupgrade)) {
$a->oldversion = "$CFG->release ($CFG->version)";
$a->newversion = "$release ($version)";
return $output;
}
+ /**
+ * Display page explaining proper upgrade process,
+ * there can not be any PHP file leftovers...
+ *
+ * @return string HTML to output.
+ */
+ public function upgrade_stale_php_files_page() {
+ $output = '';
+ $output .= $this->header();
+ $output .= $this->heading(get_string('upgradestalefiles', 'admin'));
+ $output .= $this->box_start('generalbox', 'notice');
+ $output .= get_string('upgradestalefilesinfo', 'admin', get_docs_url('Upgrading'));
+ $output .= html_writer::empty_tag('br');
+ $output .= html_writer::tag('div', $this->single_button($this->page->url, get_string('reload'), 'get'), array('class' => 'buttons'));
+ $output .= $this->box_end();
+ $output .= $this->footer();
+
+ return $output;
+ }
+
/**
* Display the 'environment check' page that is displayed during install.
* @param int $maturity
return '';
}
- return $this->warning(get_string('sitemaintenancewarning2', 'admin',
- new moodle_url('/admin/settings.php', array('section' => 'maintenancemode'))));
+ $url = new moodle_url('/admin/settings.php', array('section' => 'maintenancemode'));
+ $url = $url->out(); // get_string() does not support objects in params
+
+ return $this->warning(get_string('sitemaintenancewarning2', 'admin', $url));
}
/**
$sql = " FROM {user} u
WHERE u.id IN ($enrolsql) $wherecondition
AND u.id NOT IN (
- SELECT u.id
- FROM {role_assignments} r, {user} u
+ SELECT r.userid
+ FROM {role_assignments} r
WHERE r.contextid = :contextid
- AND u.id = r.userid
AND r.roleid = :roleid)";
$order = ' ORDER BY lastname ASC, firstname ASC';
$sql = " FROM {user}
WHERE $wherecondition
AND id NOT IN (
- SELECT u.id
- FROM {role_assignments} r, {user} u
+ SELECT r.userid
+ FROM {role_assignments} r
WHERE r.contextid = :contextid
- AND u.id = r.userid
AND r.roleid = :roleid)";
$order = ' ORDER BY lastname ASC, firstname ASC';
$DB->set_debug(true);
foreach ($tables as $table) {
$fulltable = $DB->get_prefix().$table;
- $DB->change_database_structure("ALTER TABLE $fulltable TYPE=INNODB");
+ $DB->change_database_structure("ALTER TABLE $fulltable ENGINE=INNODB");
}
$DB->set_debug(false);
}
function get_string($identifier, $a = NULL) {
return get_string($identifier, 'tool_unittest', $a);
}
+
+ function _htmlEntities($message) {
+ // Override subclass message that breaks UTF8.
+ return s($message);
+ }
}
$users = get_users_listing($sort, $dir, $page*$perpage, $perpage, '', '', '',
$extrasql, $params, $context);
$usercount = get_users(false);
- $usersearchcount = get_users(false, '', true, null, "", '', '', '', '', '*', $extrasql, $params);
+ $usersearchcount = get_users(false, '', false, null, "", '', '', '', '', '*', $extrasql, $params);
if ($extrasql !== '') {
echo $OUTPUT->heading("$usersearchcount / $usercount ".get_string('users'));
}
$mods = array(0=>get_string('allownone'));
- $mods += $DB->get_records_menu('modules', array('visible'=>1), 'name', 'id, name');
+ $allmods = $DB->get_records_menu('modules', array('visible' => 1),
+ 'name', 'id, name');
+ foreach ($allmods as $key => $value) {
+ // Add module to list unless it cannot be added by users anyway
+ if (plugin_supports('mod', $value, FEATURE_MOD_ARCHETYPE, MOD_ARCHETYPE_OTHER) !==
+ MOD_ARCHETYPE_SYSTEM) {
+ $mods[$key] = get_string('pluginname', $value);
+ }
+ }
$mform->addElement('select', 'allowedmods', get_string('to'), $mods, array('multiple'=>'multiple', 'size'=>'10'));
$mform->disabledIf('allowedmods', 'restrictmodules', 'eq', 0);
// defaults are already in $course
function make_log_url($module, $url) {
switch ($module) {
case 'course':
+ if (strpos($url, 'report/') === 0) {
+ // there is only one report type, course reports are deprecated
+ $url = "/$url";
+ break;
+ }
case 'file':
case 'login':
case 'lib':
$archetype = plugin_supports('mod', $modname, FEATURE_MOD_ARCHETYPE, MOD_ARCHETYPE_OTHER);
if ($archetype == MOD_ARCHETYPE_RESOURCE) {
$resources[$urlbase.$modname] = $modnamestr;
+ } else if ($archetype === MOD_ARCHETYPE_SYSTEM) {
+ // System modules cannot be added by user, do not add to dropdown
} else {
// all other archetypes are considered activity
$activities[$urlbase.$modname] = $modnamestr;
$str->duplicate = get_string("duplicate");
$str->hide = get_string("hide");
$str->show = get_string("show");
- $str->clicktochange = get_string("clicktochange");
- $str->forcedmode = get_string("forcedmode");
- $str->groupsnone = get_string("groupsnone");
- $str->groupsseparate = get_string("groupsseparate");
- $str->groupsvisible = get_string("groupsvisible");
+ $str->groupsnone = get_string('clicktochangeinbrackets', 'moodle', get_string("groupsnone"));
+ $str->groupsseparate = get_string('clicktochangeinbrackets', 'moodle', get_string("groupsseparate"));
+ $str->groupsvisible = get_string('clicktochangeinbrackets', 'moodle', get_string("groupsvisible"));
+ $str->forcedgroupsnone = get_string('forcedmodeinbrackets', 'moodle', get_string("groupsnone"));
+ $str->forcedgroupsseparate = get_string('forcedmodeinbrackets', 'moodle', get_string("groupsseparate"));
+ $str->forcedgroupsvisible = get_string('forcedmodeinbrackets', 'moodle', get_string("groupsvisible"));
}
$baseurl = new moodle_url('/course/mod.php', array('sesskey' => sesskey()));
if ($mod->groupmode == SEPARATEGROUPS) {
$groupmode = 0;
$grouptitle = $str->groupsseparate;
+ $forcedgrouptitle = $str->forcedgroupsseparate;
$groupclass = 'editing_groupsseparate';
$groupimage = 't/groups';
} else if ($mod->groupmode == VISIBLEGROUPS) {
$groupmode = 1;
$grouptitle = $str->groupsvisible;
+ $forcedgrouptitle = $str->forcedgroupsvisible;
$groupclass = 'editing_groupsvisible';
$groupimage = 't/groupv';
} else {
$groupmode = 2;
$grouptitle = $str->groupsnone;
+ $forcedgrouptitle = $str->forcedgroupsnone;
$groupclass = 'editing_groupsnone';
$groupimage = 't/groupn';
}
new moodle_url($baseurl, array('id' => $mod->id, 'groupmode' => $groupmode)),
new pix_icon($groupimage, $grouptitle, 'moodle', array('class' => 'iconsmall')),
null,
- array('class' => $groupclass, 'title' => $grouptitle.' ('.$str->clicktochange.')')
+ array('class' => $groupclass, 'title' => $grouptitle)
);
} else {
- $actions[] = new pix_icon($groupimage, $grouptitle, 'moodle', array('title' => $grouptitle.' ('.$str->forcedmode.')', 'class' => 'iconsmall'));
+ $actions[] = new pix_icon($groupimage, $forcedgrouptitle, 'moodle', array('title' => $forcedgrouptitle, 'class' => 'iconsmall'));
}
}
}
// construct the SQL to find all matching templates
-$sql = "SELECT DISTINCT gd.id, gd.areaid, gd.name, gd.description, gd.descriptionformat, gd.timecreated,
- gd.usercreated, gd.timemodified, gd.usermodified
+$sql = "SELECT DISTINCT gd.id, gd.areaid, gd.name, gd.usercreated
FROM {grading_definitions} gd
JOIN {grading_areas} ga ON (gd.areaid = ga.id)
JOIN {context} cx ON (ga.contextid = cx.id)";
clear:both;
}
-.path-grade-report-grader form {
-text-align:center;
-}
-
.path-grade-report-grader input.center {
margin:10px auto 0;
}
// prepare grouping
if (!empty($data->grouping)) {
- $groupingname = trim($data->groupingname);
if ($data->grouping < 0) {
$grouping = new stdClass();
$grouping->courseid = $COURSE->id;
- $grouping->name = $groupingname;
+ $grouping->name = trim($data->groupingname);
$grouping->id = groups_create_grouping($grouping);
$createdgrouping = $grouping->id;
} else {
$transaction = $DB->start_delegated_transaction();
-// TODO: this is problematic because the DB rollback does not handle deleting of group images!
foreach ($params['groupids'] as $groupid) {
// validate params
$groupid = validate_param($groupid, PARAM_INTEGER);
$string['configtimezone'] = 'You can set the default timezone here. This is the only the DEFAULT timezone for displaying dates - each user can override this by setting their own in their profile. "Server time" here will make Moodle default to the server\'s operating system setting, but "Server time" in the user profile will make the user default to this timezone setting. Cronjobs that depend on a time of day to run will use this timezone.';
$string['configunzip'] = 'Indicate the location of your unzip program (Unix only, optional). If specified, this will be used to unpack zip archives on the server. If you leave this blank, then Moodle will use internal routines.';
$string['configuseblogassociations'] = 'Should users be able to organize their blog by associating entries with courses and course modules?';
-$string['configuseexternalyui'] = 'Instead of using local files, use online files available on Yahoo‘s servers. WARNING: This requires an internet connection, or no AJAX will work on your site.';
+$string['configuseexternalyui'] = 'Instead of using local files, use online files available on Yahoo‘s servers. WARNING: This requires an internet connection, or no AJAX will work on your site. This setting is not compatible with sites using https.';
$string['configusesitenameforsitepages'] = 'If enabled the site\'s shortname will be used for the site pages node in the navigation rather than the string \'Site pages\'';
$string['configusetags'] = 'Should tags functionality across the site be enabled?';
$string['configvariables'] = 'Variables';
$string['upgradelogsinfo'] = 'Some changes have recently been made in the way logs are stored. To be able to view all of your old logs on a per-activity basis, your old logs need to be upgraded. Depending on your site this can take a long time (eg several hours) and can be quite taxing on the database for large sites. Once you start this process you should let it finish (by keeping the browser window open). Don\'t worry - your site will work fine for other people while the logs are being upgraded.<br /><br />Do you want to upgrade your logs now?';
$string['upgradesettings'] = 'New settings';
$string['upgradesettingsintro'] = 'The settings shown below were added during your last Moodle upgrade. Make any changes necessary to the defaults and then click the "Save changes" button at the bottom of this page.';
+$string['upgradestalefiles'] = 'Invalid installation files detected, upgrade cannot continue';
+$string['upgradestalefilesinfo'] = 'Some old PHP scripts have been detected which may indicate that you installed this version over an older one. Please fix the installation directory by removing all old scripts (except config.php) before installing the new version and then try the upgrade again. You can find more information in upgrade documentation at <a href="{$a}">{$a}</a>';
$string['upgradesure'] = 'Your Moodle files have been changed, and you are about to automatically upgrade your server to this version: <br /><br />
<strong>{$a}</strong> <br /><br />
Once you do this you can not go back again. <br /><br />
$string['clickhelpiconformoreinfo'] = '... continues ... Click on the help icon to read the full article';
$string['clickhere'] = 'Click here ...';
$string['clicktohideshow'] = 'Click to expand or collapse';
-$string['clicktochange'] = 'Click to change';
+$string['clicktochangeinbrackets'] = '{$a} (Click to change)';
$string['closewindow'] = 'Close this window';
$string['collapseall'] = 'Collapse all';
$string['commentincontext'] = 'Find this comment in context';
$string['followingoptional'] = 'The following items are optional';
$string['followingrequired'] = 'The following items are required';
$string['force'] = 'Force';
-$string['forcedmode'] = 'forced mode';
+$string['forcedmodeinbrackets'] = '{$a} (forced mode)';
$string['forcelanguage'] = 'Force language';
$string['forceno'] = 'Do not force';
$string['forcepasswordchange'] = 'Force password change';
*/
public function write_setting($data) {
global $DB, $CFG;
- if ($data['bloglevel'] == 0) {
+ if ($data == 0) {
$blogblocks = $DB->get_records_select('block', "name LIKE 'blog_%' AND visible = 1");
foreach ($blogblocks as $block) {
$DB->set_field('block', 'visible', 0, array('id' => $block->id));
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class admin_setting_configmultiselect_modules extends admin_setting_configmultiselect {
+ private $excludesystem;
+
/**
* Calls parent::__construct - note array $choices is not required
*
* @param string $visiblename localised setting name
* @param string $description setting description
* @param array $defaultsetting a plain array of default module ids
+ * @param bool $excludesystem If true, excludes modules with 'system' archetype
*/
- public function __construct($name, $visiblename, $description, $defaultsetting = array()) {
+ public function __construct($name, $visiblename, $description, $defaultsetting = array(),
+ $excludesystem = true) {
parent::__construct($name, $visiblename, $description, $defaultsetting, null);
+ $this->excludesystem = $excludesystem;
}
/**
global $CFG, $DB;
$records = $DB->get_records('modules', array('visible'=>1), 'name');
foreach ($records as $record) {
+ // Exclude modules if the code doesn't exist
if (file_exists("$CFG->dirroot/mod/$record->name/lib.php")) {
- $this->choices[$record->id] = $record->name;
+ // Also exclude system modules (if specified)
+ if (!($this->excludesystem &&
+ plugin_supports('mod', $record->name, FEATURE_MOD_ARCHETYPE) ===
+ MOD_ARCHETYPE_SYSTEM)) {
+ $this->choices[$record->id] = $record->name;
+ }
}
}
return true;
$output .= " main.portal.strings['moveleft']='".addslashes_js(get_string('moveleft'))."';\n";
$output .= " main.portal.strings['moveright']='".addslashes_js(get_string('moveright'))."';\n";
$output .= " main.portal.strings['update']='".addslashes_js(get_string('update'))."';\n";
- $output .= " main.portal.strings['groupsnone']='".addslashes_js(get_string('groupsnone'))."';\n";
- $output .= " main.portal.strings['groupsseparate']='".addslashes_js(get_string('groupsseparate'))."';\n";
- $output .= " main.portal.strings['groupsvisible']='".addslashes_js(get_string('groupsvisible'))."';\n";
- $output .= " main.portal.strings['clicktochange']='".addslashes_js(get_string('clicktochange'))."';\n";
+ $output .= " main.portal.strings['groupsnone']='".addslashes_js(get_string('clicktochangeinbrackets', 'moodle', get_string('groupsnone')))."';\n";
+ $output .= " main.portal.strings['groupsseparate']='".addslashes_js(get_string('clicktochangeinbrackets', 'moodle', get_string('groupsseparate')))."';\n";
+ $output .= " main.portal.strings['groupsvisible']='".addslashes_js(get_string('clicktochangeinbrackets', 'moodle', get_string('groupsvisible')))."';\n";
$output .= " main.portal.strings['deletecheck']='".addslashes_js(get_string('deletecheckfull','','_var_'))."';\n";
$output .= " main.portal.strings['resource']='".addslashes_js(get_string('resource'))."';\n";
$output .= " main.portal.strings['activity']='".addslashes_js(get_string('activity'))."';\n";
}
// Language strings.
- var strgroupsnone = main.portal.strings['groupsnone']+' ('+main.portal.strings['clicktochange']+')';
- var strgroupsseparate = main.portal.strings['groupsseparate']+' ('+main.portal.strings['clicktochange']+')';
- var strgroupsvisible = main.portal.strings['groupsvisible']+' ('+main.portal.strings['clicktochange']+')';
+ var strgroupsnone = main.portal.strings['groupsnone'];
+ var strgroupsseparate = main.portal.strings['groupsseparate'];
+ var strgroupsvisible = main.portal.strings['groupsvisible'];
this.commandContainer = commandContainer;
var buttons = commandContainer.getElementsByTagName('a');
switch (this.groupmode) {
case 0:
- newtitle = main.portal.strings['groupsnone']+' ('+main.portal.strings['clicktochange']+')';
+ newtitle = main.portal.strings['groupsnone'];
break;
case 1:
- newtitle = main.portal.strings['groupsseparate']+' ('+main.portal.strings['clicktochange']+')';
+ newtitle = main.portal.strings['groupsseparate'];
break;
case 2:
- newtitle = main.portal.strings['groupsvisible']+' ('+main.portal.strings['clicktochange']+')';
+ newtitle = main.portal.strings['groupsvisible'];
break;
}
<?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="lib/db" VERSION="20111214" COMMENT="XMLDB file for core Moodle tables"
+<XMLDB PATH="lib/db" VERSION="20120110" COMMENT="XMLDB file for core Moodle tables"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
>
<KEY NAME="userid" TYPE="foreign" FIELDS="userid" REFTABLE="user" REFFIELDS="id" PREVIOUS="contextid"/>
</KEYS>
<INDEXES>
- <INDEX NAME="sortorder" UNIQUE="false" FIELDS="sortorder"/>
+ <INDEX NAME="sortorder" UNIQUE="false" FIELDS="sortorder" NEXT="rolecontext"/>
+ <INDEX NAME="rolecontext" UNIQUE="false" FIELDS="roleid, contextid" COMMENT="Index on roleid and contextid" PREVIOUS="sortorder" NEXT="usercontextrole"/>
+ <INDEX NAME="usercontextrole" UNIQUE="false" FIELDS="userid, contextid, roleid" COMMENT="Index on userid, contextid and roleid" PREVIOUS="rolecontext"/>
</INDEXES>
</TABLE>
<TABLE NAME="role_capabilities" COMMENT="permission has to be signed, overriding a capability for a particular role in a particular context" PREVIOUS="role_assignments" NEXT="role_names">
upgrade_main_savepoint(true, 2011120500.03);
}
+ if ($oldversion < 2012020200.03) {
+
+ // Define index rolecontext (not unique) to be added to role_assignments
+ $table = new xmldb_table('role_assignments');
+ $index = new xmldb_index('rolecontext', XMLDB_INDEX_NOTUNIQUE, array('roleid', 'contextid'));
+
+ // Conditionally launch add index rolecontext
+ if (!$dbman->index_exists($table, $index)) {
+ $dbman->add_index($table, $index);
+ }
+
+ // Define index usercontextrole (not unique) to be added to role_assignments
+ $index = new xmldb_index('usercontextrole', XMLDB_INDEX_NOTUNIQUE, array('userid', 'contextid', 'roleid'));
+
+ // Conditionally launch add index usercontextrole
+ if (!$dbman->index_exists($table, $index)) {
+ $dbman->add_index($table, $index);
+ }
+
+ // Main savepoint reached
+ upgrade_main_savepoint(true, 2012020200.03);
+ }
+
return true;
}
print_error('siteblogdisable', 'blog');
}
+ $entryid = (int)array_shift($args);
+ if (!$entry = $DB->get_record('post', array('module'=>'blog', 'id'=>$entryid))) {
+ send_file_not_found();
+ }
if ($CFG->bloglevel < BLOG_GLOBAL_LEVEL) {
require_login();
if (isguestuser()) {
}
}
}
- $entryid = (int)array_shift($args);
- if (!$entry = $DB->get_record('post', array('module'=>'blog', 'id'=>$entryid))) {
- send_file_not_found();
- }
if ('publishstate' === 'public') {
if ($CFG->forcelogin) {
define('MOD_ARCHETYPE_RESOURCE', 1);
/** Assignment module archetype */
define('MOD_ARCHETYPE_ASSIGNMENT', 2);
+/** System (not user-addable) module archetype */
+define('MOD_ARCHETYPE_SYSTEM', 3);
/**
* Security token used for allowing access
}
// Split showuseridentity on comma
- if ($CFG->showuseridentity === '') {
+ if (empty($CFG->showuseridentity)) {
// Explode gives wrong result with empty string
$extra = array();
} else {
function setnew_password_and_mail($user) {
global $CFG, $DB;
+ // we try to send the mail in language the user understands,
+ // unfortunately the filter_string() does not support alternative langs yet
+ // so multilang will not work properly for site->fullname
+ $lang = empty($user->lang) ? $CFG->lang : $user->lang;
+
$site = get_site();
$supportuser = generate_email_supportuser();
$a->link = $CFG->wwwroot .'/login/';
$a->signoff = generate_email_signoff();
- $message = get_string('newusernewpasswordtext', '', $a);
+ $message = (string)new lang_string('newusernewpasswordtext', '', $a, $lang);
- $subject = format_string($site->fullname) .': '. get_string('newusernewpasswordsubj');
+ $subject = format_string($site->fullname) .': '. (string)new lang_string('newusernewpasswordsubj', '', $a, $lang);
//directly email rather than using the messaging system to ensure its not routed to a popup or jabber
return email_to_user($user, $supportuser, $subject, $message);
* Detect a custom script replacement in the data directory that will
* replace an existing moodle script
*
- * @param string $urlpath path to the original script
* @return string|bool full path name if a custom script exists, false if no custom script exists
*/
-function custom_script_path($urlpath='') {
- global $CFG;
+function custom_script_path() {
+ global $CFG, $SCRIPT;
- // set default $urlpath, if necessary
- if (empty($urlpath)) {
- $urlpath = qualified_me(); // e.g. http://www.this-server.com/moodle/this-script.php
- }
-
- // $urlpath is invalid if it is empty or does not start with the Moodle wwwroot
- if (empty($urlpath) or (strpos($urlpath, $CFG->wwwroot) === false )) {
+ if ($SCRIPT === null) {
+ // Probably some weird external script
return false;
}
- // replace wwwroot with the path to the customscripts folder and clean path
- $scriptpath = $CFG->customscripts . clean_param(substr($urlpath, strlen($CFG->wwwroot)), PARAM_PATH);
-
- // remove the query string, if any
- if (($strpos = strpos($scriptpath, '?')) !== false) {
- $scriptpath = substr($scriptpath, 0, $strpos);
- }
-
- // remove trailing slashes, if any
- $scriptpath = rtrim($scriptpath, '/\\');
-
- // append index.php, if necessary
- if (is_dir($scriptpath)) {
- $scriptpath .= '/index.php';
- }
+ $scriptpath = $CFG->customscripts . $SCRIPT;
// check the custom script exists
- if (file_exists($scriptpath)) {
+ if (file_exists($scriptpath) and is_file($scriptpath)) {
return $scriptpath;
} else {
return false;
/**
* Loads all of the activities for a section into the navigation structure.
*
- * @todo 2.2 - $activities should always be an array and we should no longer check for it being a
- * course_modinfo object
- *
* @param navigation_node $sectionnode
* @param int $sectionnumber
- * @param course_modinfo $modinfo Object returned from {@see get_fast_modinfo()}
+ * @param array $activities An array of activites as returned by {@see global_navigation::generate_sections_and_activities()}
+ * @param stdClass $course The course object the section and activities relate to.
* @return array Array of activity nodes
*/
- protected function load_section_activities(navigation_node $sectionnode, $sectionnumber, $activities, $course = null) {
+ protected function load_section_activities(navigation_node $sectionnode, $sectionnumber, array $activities, $course = null) {
global $CFG;
// A static counter for JS function naming
static $legacyonclickcounter = 0;
- if ($activities instanceof course_modinfo) {
- debugging('global_navigation::load_section_activities argument 3 should now recieve an array of activites. See that method for an example.', DEBUG_DEVELOPER);
- list($sections, $activities) = $this->generate_sections_and_activities($activities->course);
- }
-
$activitynodes = array();
if (empty($activities)) {
return $activitynodes;
$this->yui3loader->filter = null;
$this->yui2loader->filter = null;
}
- if (!empty($CFG->useexternalyui)) {
+ if (!empty($CFG->useexternalyui) and strpos($CFG->httpswwwroot, 'https:') !== 0) {
$this->yui3loader->base = 'http://yui.yahooapis.com/' . $CFG->yui3version . '/build/';
$this->yui2loader->base = 'http://yui.yahooapis.com/' . $CFG->yui2version . '/build/';
$this->yui3loader->comboBase = 'http://yui.yahooapis.com/combo?';
public function test_substr() {
$str = "Žluťoučký koníček";
+ $this->assertIdentical(textlib::substr($str, 0), $str);
+ $this->assertIdentical(textlib::substr($str, 1), 'luťoučký koníček');
$this->assertIdentical(textlib::substr($str, 1, 3), 'luť');
$this->assertIdentical(textlib::substr($str, 0, 100), $str);
$this->assertIdentical(textlib::substr($str, -3, 2), 'če');
$this->assertTrue($url1->compare($url2, URL_MATCH_EXACT));
}
+ function test_out_as_local_url() {
+ $url1 = new moodle_url('/lib/simpletest/testweblib.php');
+ $this->assertEqual('/lib/simpletest/testweblib.php', $url1->out_as_local_url());
+
+ $url2 = new moodle_url('http://www.google.com/lib/simpletest/testweblib.php');
+ $this->expectException('coding_exception');
+ $url2->out_as_local_url();
+ }
+
public function test_html_to_text_simple() {
$this->assertEqual("\n\n_Hello_ WORLD!", html_to_text('<p><i>Hello</i> <b>world</b>!</p>'));
}
}
/**
- * Multibyte safe substr() function, uses iconv for utf-8, falls back to typo3.
+ * Multibyte safe substr() function, uses mbstring or iconv for UTF-8, falls back to typo3.
*
* @param string $text
* @param int $start negative value means from end
$charset = self::parse_charset($charset);
if ($charset === 'utf-8') {
- return iconv_substr($text, $start, $len, $charset);
+ if (function_exists('mb_substr')) {
+ // this is much faster than iconv - see MDL-31142
+ if ($len === null) {
+ $oldcharset = mb_internal_encoding();
+ mb_internal_encoding('UTF-8');
+ $result = mb_substr($text, $start);
+ mb_internal_encoding($oldcharset);
+ return $result;
+ } else {
+ return mb_substr($text, $start, $len, 'UTF-8');
+ }
+
+ } else {
+ if ($len === null) {
+ $len = iconv_strlen($text, 'UTF-8');
+ }
+ return iconv_substr($text, $start, $len, 'UTF-8');
+ }
}
$oldlevel = error_reporting(E_PARSE);
- $result = self::typo3()->substr($charset, $text, $start, $len);
+ if ($len === null) {
+ $result = self::typo3()->substr($charset, $text, $start);
+ } else {
+ $result = self::typo3()->substr($charset, $text, $start, $len);
+ }
error_reporting($oldlevel);
return $result;
}
/**
- * Multibyte safe strlen() function, uses iconv for utf-8, falls back to typo3.
+ * Multibyte safe strlen() function, uses mbstring or iconv for UTF-8, falls back to typo3.
*
* @param string $text
* @param string $charset encoding of the text
$charset = self::parse_charset($charset);
if ($charset === 'utf-8') {
- return iconv_strlen($text, $charset);
+ if (function_exists('mb_strlen')) {
+ return mb_strlen($text, 'UTF-8');
+ } else {
+ return iconv_strlen($text, 'UTF-8');
+ }
}
$oldlevel = error_reporting(E_PARSE);
$charset = self::parse_charset($charset);
if ($charset === 'utf-8' and function_exists('mb_strtolower')) {
- return mb_strtolower($text, $charset);
+ return mb_strtolower($text, 'UTF-8');
}
$oldlevel = error_reporting(E_PARSE);
$charset = self::parse_charset($charset);
if ($charset === 'utf-8' and function_exists('mb_strtoupper')) {
- return mb_strtoupper($text, $charset);
+ return mb_strtoupper($text, 'UTF-8');
}
$oldlevel = error_reporting(E_PARSE);
}
/**
- * UTF-8 ONLY safe strpos(), uses iconv..
+ * UTF-8 ONLY safe strpos(), uses mbstring, falls back to iconv.
*
* @param string $haystack
* @param string $needle
* @return string
*/
public static function strpos($haystack, $needle, $offset=0) {
- return iconv_strpos($haystack, $needle, $offset, 'utf-8');
+ if (function_exists('mb_strpos')) {
+ return mb_strpos($haystack, $needle, $offset, 'UTF-8');
+ } else {
+ return iconv_strpos($haystack, $needle, $offset, 'UTF-8');
+ }
}
/**
- * UTF-8 ONLY safe strrpos(), uses iconv.
+ * UTF-8 ONLY safe strrpos(), uses mbstring, falls back to iconv.
*
* @param string $haystack
* @param string $needle
* @return string
*/
public static function strrpos($haystack, $needle) {
- return iconv_strrpos($haystack, $needle, 'utf-8');
+ if (function_exists('mb_strpos')) {
+ return mb_strrpos($haystack, $needle, null, 'UTF-8');
+ } else {
+ return iconv_strrpos($haystack, $needle, 'UTF-8');
+ }
}
/**
}
}
+/**
+ * Detect if there are leftovers in PHP source files.
+ *
+ * During main version upgrades administrators MUST move away
+ * old PHP source files and start from scratch (or better
+ * use git).
+ *
+ * @return bool true means borked upgrade, false means previous PHP files were properly removed
+ */
+function upgrade_stale_php_files_present() {
+ global $CFG;
+
+ $someexamplesofremovedfiles = array(
+ // removed in 2.2dev
+ '/lib/yui/3.4.1pr1/',
+ // removed in 2.2
+ '/search/cron_php5.php',
+ '/course/report/log/indexlive.php',
+ '/admin/report/backups/index.php',
+ '/admin/generator.php',
+ // removed in 2.1
+ '/lib/yui/2.8.0r4/',
+ // removed in 2.0
+ '/blocks/admin/block_admin.php',
+ '/blocks/admin_tree/block_admin_tree.php',
+ );
+
+ foreach ($someexamplesofremovedfiles as $file) {
+ if (file_exists($CFG->dirroot.$file)) {
+ return true;
+ }
+ }
+
+ return false;
+}
/**
* Upgrade plugins
$urlbase = "$CFG->wwwroot/file.php";
return self::make_file_url($urlbase, '/'.$courseid.'/'.$filepath, $forcedownload);
}
+
+ /**
+ * Returns URL a relative path from $CFG->wwwroot
+ *
+ * Can be used for passing around urls with the wwwroot stripped
+ *
+ * @param boolean $escaped Use & as params separator instead of plain &
+ * @param array $overrideparams params to add to the output url, these override existing ones with the same name.
+ * @return string Resulting URL
+ * @throws coding_exception if called on a non-local url
+ */
+ public function out_as_local_url($escaped = true, array $overrideparams = null) {
+ global $CFG;
+
+ $url = $this->out($escaped, $overrideparams);
+
+ if (strpos($url, $CFG->wwwroot) !== 0) {
+ throw new coding_exception('out_as_local_url called on a non-local URL');
+ }
+
+ return str_replace($CFG->wwwroot, '', $url);
+ }
}
/**
throw new moodle_quiz_exception($attemptobj->get_quizobj(), 'noquestionsfound');
}
+// Update attempt page
+if ($attemptobj->get_currentpage() != $page) {
+ $DB->set_field('quiz_attempts', 'currentpage', $page);
+}
+
// Initialise the JavaScript.
$headtags = $attemptobj->get_html_head_contributions($page);
$PAGE->requires->js_init_call('M.mod_quiz.init_attempt_form', null, false, quiz_get_js_module());
if ($getcontext && !empty($cm->id)) {
$this->context = get_context_instance(CONTEXT_MODULE, $cm->id);
}
- $this->questionids = explode(',', quiz_questions_in_quiz($this->quiz->questions));
+ $questionids = quiz_questions_in_quiz($this->quiz->questions);
+ if ($questionids) {
+ $this->questionids = explode(',', quiz_questions_in_quiz($this->quiz->questions));
+ } else {
+ $this->questionids = array(); // Which idiot made explode(',', '') = array('')?
+ }
}
/**
return $this->attempt->userid;
}
+ /** @return int the current page of the attempt. */
+ public function get_currentpage() {
+ return $this->attempt->currentpage;
+ }
+
/**
* @return bool whether this attempt has been finished (true) or is still
* in progress (false).
<FIELD NAME="timestart" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="sumgrades" NEXT="timefinish"/>
<FIELD NAME="timefinish" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="timestart" NEXT="timemodified"/>
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="timefinish" NEXT="layout"/>
- <FIELD NAME="layout" TYPE="text" LENGTH="small" NOTNULL="true" SEQUENCE="false" PREVIOUS="timemodified" NEXT="preview"/>
- <FIELD NAME="preview" TYPE="int" LENGTH="3" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="layout" NEXT="needsupgradetonewqe"/>
+ <FIELD NAME="layout" TYPE="text" LENGTH="small" NOTNULL="true" SEQUENCE="false" PREVIOUS="timemodified" NEXT="currentpage"/>
+ <FIELD NAME="currentpage" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="layout" NEXT="preview"/>
+ <FIELD NAME="preview" TYPE="int" LENGTH="3" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="currentpage" NEXT="needsupgradetonewqe"/>
<FIELD NAME="needsupgradetonewqe" TYPE="int" LENGTH="3" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="preview"/>
</FIELDS>
<KEYS>
upgrade_mod_savepoint(true, 2011120701, 'quiz');
}
+ if ($oldversion < 2011120703) {
+ // Track page of quiz attempts
+ $table = new xmldb_table('quiz_attempts');
+
+ $field = new xmldb_field('currentpage', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0);
+
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ }
+ upgrade_mod_savepoint(true, 2011120703, 'quiz');
+ }
+
return true;
}
$remove = optional_param('remove', false, PARAM_INT);
if (($remove = optional_param('remove', false, PARAM_INT)) && confirm_sesskey()) {
quiz_remove_question($quiz, $remove);
- quiz_update_sumgrades($quiz);
quiz_delete_previews($quiz);
+ quiz_update_sumgrades($quiz);
redirect($afteractionurl);
}
quiz_print_status_bar($quiz);
$tabindex = 0;
-if (!$quiz_reordertool) {
- quiz_print_grading_form($quiz, $thispageurl, $tabindex);
-}
+quiz_print_grading_form($quiz, $thispageurl, $tabindex);
$notifystrings = array();
if ($quizhasattempts) {
$randomform = new quiz_add_random_form(new moodle_url('/mod/quiz/addrandom.php'), $contexts);
$randomform->set_data(array(
'category' => $pagevars['cat'],
- 'returnurl' => str_replace($CFG->wwwroot, '', $thispageurl->out(false)),
+ 'returnurl' => $thispageurl->out_as_local_url(false),
'cmid' => $cm->id,
));
?>
function quiz_save_new_layout($quiz) {
global $DB;
$DB->set_field('quiz', 'questions', $quiz->questions, array('id' => $quiz->id));
- quiz_update_sumgrades($quiz);
quiz_delete_previews($quiz);
+ quiz_update_sumgrades($quiz);
}
/**
$pageopen = false;
- $returnurl = str_replace($CFG->wwwroot, '', $pageurl->out(false));
+ $returnurl = $pageurl->out_as_local_url(false);
$questiontotalcount = count($order);
foreach ($order as $count => $qnum) {
$returnurladdtoquiz = new moodle_url($pageurl, array('addonpage' => $page));
// Print a button linking to the choose question type page.
- $returnurladdtoquiz = str_replace($CFG->wwwroot, '', $returnurladdtoquiz->out(false));
+ $returnurladdtoquiz = $returnurladdtoquiz->out_as_local_url(false);
$newquestionparams = array('returnurl' => $returnurladdtoquiz,
'cmid' => $quiz->cmid, 'appendqnumstring' => 'addquestion');
create_new_question_button($defaultcategoryid, $newquestionparams,
$string['cannotsavequestion'] = 'Cannot save question list';
$string['cannotsetgrade'] = 'Could not set a new maximum grade for the quiz';
$string['cannotsetsumgrades'] = 'Failed to set sumgrades';
+$string['cannotstartgradesmismatch'] = 'Cannot start an attempt at this quiz. The quiz is supposed to be graded, but there are no questions in the quiz that are worth any marks.';
$string['cannotstartmissingquestion'] = 'Cannot start an attempt at this quiz. The quiz definition includes a question that does not exist.';
+$string['cannotstartnoquestions'] = 'Cannot start an attempt at this quiz. The quiz has not been set up yet. No questions have been added.';
$string['cannotwrite'] = 'Cannot write to export file ({$a})';
$string['caseno'] = 'No, case is unimportant';
$string['casesensitive'] = 'Case sensitivity';
function quiz_create_attempt($quiz, $attemptnumber, $lastattempt, $timenow, $ispreview = false) {
global $USER;
+ if ($quiz->sumgrades < 0.000005 && $quiz->grade > 0.000005) {
+ throw new moodle_exception('cannotstartgradesmismatch', 'quiz',
+ new moodle_url('/mod/quiz/view.php', array('q' => $quiz->id)));
+ }
+
if ($attemptnumber == 1 || !$quiz->attemptonlast) {
// We are not building on last attempt so create a new attempt.
$attempt = new stdClass();
* the grading structure of the quiz is changed. For example if a question is
* added or removed, or a question weight is changed.
*
+ * You should call {@link quiz_delete_previews()} before you call this function.
+ *
* @param object $quiz a quiz.
*/
function quiz_update_sumgrades($quiz) {
global $DB;
+
$sql = 'UPDATE {quiz}
SET sumgrades = COALESCE((
SELECT SUM(grade)
WHERE id = ?';
$DB->execute($sql, array($quiz->id));
$quiz->sumgrades = $DB->get_field('quiz', 'sumgrades', array('id' => $quiz->id));
- if ($quiz->sumgrades < 0.000005 && quiz_clean_layout($quiz->questions, true)) {
- // If there is at least one question in the quiz, and the sumgrades has been
- // set to 0, then also set the maximum possible grade to 0.
+
+ if ($quiz->sumgrades < 0.000005 && quiz_has_attempts($quiz->id)) {
+ // If the quiz has been attempted, and the sumgrades has been
+ // set to 0, then we must also set the maximum possible grade to 0, or
+ // we will get a divide by zero error.
quiz_set_grade(0, $quiz);
}
}
+/**
+ * Update the sumgrades field of the attempts at a quiz.
+ *
+ * @param object $quiz a quiz.
+ */
function quiz_update_all_attempt_sumgrades($quiz) {
global $DB;
$dm = new question_engine_data_mapper();
// Build the icon.
if ($action) {
if ($returnurl instanceof moodle_url) {
- $returnurl = str_replace($CFG->wwwroot, '', $returnurl->out(false));
+ $returnurl = $returnurl->out_as_local_url(false);
}
$questionparams = array('returnurl' => $returnurl, 'cmid' => $cmid, 'id' => $question->id);
$questionurl = new moodle_url("$CFG->wwwroot/question/question.php", $questionparams);
SELECT AVG(quiza.sumgrades) AS grade, COUNT(quiza.sumgrades) AS numaveraged
FROM $from
WHERE $where", $params);
- $record->grade = quiz_rescale_grade($record->grade, $this->quiz);
+ $record->grade = quiz_rescale_grade($record->grade, $this->quiz, false);
if ($this->is_downloading()) {
$namekey = 'lastname';
} else {
$record = new stdClass();
$record->grade = null;
- $record->numaveraged = null;
+ $record->numaveraged = 0;
}
$row['qsgrade' . $question->slot] = $this->format_average($record, true);
if ($this->download) {
return $average;
- } else if (is_null($record->numaveraged)) {
+ } else if (is_null($record->numaveraged) || $record->numaveraged == 0) {
return html_writer::tag('span', html_writer::tag('span',
$average, array('class' => 'average')), array('class' => 'avgcell'));
} else {
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2011062600;
-$plugin->requires = 2011060313;
+$plugin->version = 2011122300;
+$plugin->requires = 2012020200;
$plugin->cron = 18000;
$plugin->component = 'quiz_statistics';
$this->assertEqual(get_string('noreviewuntil', 'quiz', userdate($closetime)),
$quizobj->cannot_review_message(mod_quiz_display_options::LATER_WHILE_OPEN));
}
+
+ public function test_empty_quiz() {
+ $quiz = new stdClass();
+ $quiz->reviewattempt = 0x10010;
+ $quiz->timeclose = 0;
+ $quiz->attempts = 0;
+ $quiz->questions = '0';
+
+ $cm = new stdClass();
+ $cm->id = 123;
+
+ $quizobj = new quiz($quiz, $cm, new stdClass(), false);
+
+ $this->assertFalse($quizobj->has_questions());
+ }
}
// Get submitted parameters.
$id = required_param('cmid', PARAM_INT); // Course module id
$forcenew = optional_param('forcenew', false, PARAM_BOOL); // Used to force a new preview
-$page = optional_param('page', 0, PARAM_INT); // Page to jump to in the attempt.
+$page = optional_param('page', -1, PARAM_INT); // Page to jump to in the attempt.
if (!$cm = get_coursemodule_from_id('quiz', $id)) {
print_error('invalidcoursemodule');
require_login($quizobj->get_courseid(), false, $quizobj->get_cm());
require_sesskey();
-// if no questions have been set up yet redirect to edit.php
-if (!$quizobj->has_questions() && $quizobj->has_capability('mod/quiz:manage')) {
- redirect($quizobj->edit_url());
+// if no questions have been set up yet redirect to edit.php or display an error.
+if (!$quizobj->has_questions()) {
+ if ($quizobj->has_capability('mod/quiz:manage')) {
+ redirect($quizobj->edit_url());
+ } else {
+ print_error('cannotstartnoquestions', 'quiz', $quizobj->view_url());
+ }
}
// Create an object to manage all the other (non-roles) access rules.
$currentattemptid = $lastattempt->id;
$messages = $accessmanager->prevent_access();
+ if ($page == -1) {
+ $page = $lastattempt->currentpage;
+ }
+
} else {
// Get number for the next or unfinished attempt
if ($lastattempt && !$lastattempt->preview && !$quizobj->is_preview_user()) {
$messages = $accessmanager->prevent_access() +
$accessmanager->prevent_new_attempt(count($attempts), $lastattempt);
+
+ if ($page == -1) {
+ $page = 0;
+ }
}
// Check access.
defined('MOODLE_INTERNAL') || die();
-$module->version = 2011120702; // The current module version (Date: YYYYMMDDXX)
+$module->version = 2011120703; // The current module version (Date: YYYYMMDDXX)
$module->requires = 2011112900; // Requires this Moodle version
$module->component = 'mod_quiz'; // Full name of the plugin (used for diagnostics)
$module->cron = 60;
var CMIInteger = '^\\d+$';
var CMISInteger = '^-?([0-9]+)$';
var CMIDecimal = '^-?([0-9]{1,5})(\\.[0-9]{1,18})?$';
- var CMIIdentifier = '^\\S{0,250}[a-zA-Z0-9]$';
+ var CMIIdentifier = '^\\S{1,250}[a-zA-Z0-9]$';
var CMIShortIdentifier = '^[\\w\.]{1,250}$';
- var CMILongIdentifier = '^\\S{0,4000}$';
+ var CMILongIdentifier = '^(?:(?!urn:)\\S{1,4000}|urn:[A-Za-z0-9-]{1,31}:\\S{1,4000})$';
var CMIFeedback = '^.*$'; // This must be redefined
var CMIIndex = '[._](\\d+).';
var CMIIndexStore = '.N(\\d+).';
defined('MOODLE_INTERNAL') || die();
-require_once($CFG->dirroot.'/mod/workshop/form/accumulative/db/upgradelib.php');
-
/**
* Conversion handler for the accumulative grading strategy data
*/
return $data;
}
}
+
+/**
+ * Transforms a given record from workshop_elements_old into an object to be saved into workshopform_accumulative
+ *
+ * @param stdClass $old legacy record from workshop_elements_old
+ * @param array $newscaleids mapping from old scale types into new standard ones
+ * @param int $newworkshopid id of the new workshop instance that replaced the previous one
+ * @return stdclass to be saved in workshopform_accumulative
+ */
+function workshopform_accumulative_upgrade_element(stdclass $old, array $newscaleids, $newworkshopid) {
+ $new = new stdclass();
+ $new->workshopid = $newworkshopid;
+ $new->sort = $old->elementno;
+ $new->description = $old->description;
+ $new->descriptionformat = FORMAT_HTML;
+ // calculate new grade/scale of the element
+ if ($old->scale >= 0 and $old->scale <= 6 and isset($newscaleids[$old->scale])) {
+ $new->grade = -$newscaleids[$old->scale];
+ } elseif ($old->scale == 7) {
+ $new->grade = 10;
+ } elseif ($old->scale == 8) {
+ $new->grade = 20;
+ } elseif ($old->scale == 9) {
+ $new->grade = 100;
+ } else {
+ $new->grade = 0; // something is wrong
+ }
+ // calculate new weight of the element. Negative weights are not supported any more and
+ // are replaced with weight = 0. Legacy workshop did not store the raw weight but the index
+ // in the array of weights (see $WORKSHOP_EWEIGHTS in workshop 1.x)
+ // workshop 2.0 uses integer weights only (0-16) so all previous weights are multiplied by 4.
+ switch ($old->weight) {
+ case 8: $new->weight = 1; break;
+ case 9: $new->weight = 2; break;
+ case 10: $new->weight = 3; break;
+ case 11: $new->weight = 4; break;
+ case 12: $new->weight = 6; break;
+ case 13: $new->weight = 8; break;
+ case 14: $new->weight = 16; break;
+ default: $new->weight = 0;
+ }
+ return $new;
+}
defined('MOODLE_INTERNAL') || die();
-require_once($CFG->dirroot.'/mod/workshop/form/comments/db/upgradelib.php');
-
/**
* Conversion handler for the comments grading strategy data
*/
return $converted;
}
}
+
+/**
+ * Transforms a given record from workshop_elements_old into an object to be saved into workshopform_comments
+ *
+ * @param stdClass $old legacy record from workshop_elements_old
+ * @param int $newworkshopid id of the new workshop instance that replaced the previous one
+ * @return stdclass to be saved in workshopform_comments
+ */
+function workshopform_comments_upgrade_element(stdclass $old, $newworkshopid) {
+ $new = new stdclass();
+ $new->workshopid = $newworkshopid;
+ $new->sort = $old->elementno;
+ $new->description = $old->description;
+ $new->descriptionformat = FORMAT_HTML;
+ return $new;
+}
defined('MOODLE_INTERNAL') || die();
-require_once($CFG->dirroot.'/mod/workshop/form/numerrors/db/upgradelib.php');
require_once($CFG->libdir.'/gradelib.php'); // grade_floatval() called here
/**
}
}
}
+
+/**
+ * Transforms a given record from workshop_elements_old into an object to be saved into workshopform_numerrors
+ *
+ * @param stdClass $old legacy record from workshop_elements_old
+ * @param int $newworkshopid id of the new workshop instance that replaced the previous one
+ * @return stdclass to be saved in workshopform_numerrors
+ */
+function workshopform_numerrors_upgrade_element(stdclass $old, $newworkshopid) {
+ $new = new stdclass();
+ $new->workshopid = $newworkshopid;
+ $new->sort = $old->elementno;
+ $new->description = $old->description;
+ $new->descriptionformat = FORMAT_HTML;
+ $new->grade0 = get_string('grade0default', 'workshopform_numerrors');
+ $new->grade1 = get_string('grade1default', 'workshopform_numerrors');
+ // calculate new weight of the element. Negative weights are not supported any more and
+ // are replaced with weight = 0. Legacy workshop did not store the raw weight but the index
+ // in the array of weights (see $WORKSHOP_EWEIGHTS in workshop 1.x)
+ // workshop 2.0 uses integer weights only (0-16) so all previous weights are multiplied by 4.
+ switch ($old->weight) {
+ case 8: $new->weight = 1; break;
+ case 9: $new->weight = 2; break;
+ case 10: $new->weight = 3; break;
+ case 11: $new->weight = 4; break;
+ case 12: $new->weight = 6; break;
+ case 13: $new->weight = 8; break;
+ case 14: $new->weight = 16; break;
+ default: $new->weight = 0;
+ }
+ return $new;
+}
defined('MOODLE_INTERNAL') || die();
-require_once($CFG->dirroot.'/mod/workshop/form/rubric/db/upgradelib.php');
-
/**
* Conversion handler for the rubric grading strategy data
*/
}
}
}
+
+/**
+ * Transforms given record into an object to be saved into workshopform_rubric_levels
+ *
+ * This is used during Rubric 1.9 -> Rubric 2.0 conversion
+ *
+ * @param stdClass $old legacy record from joined workshop_elements_old + workshop_rubrics_old
+ * @param int $newdimensionid id of the new workshopform_rubric dimension record to be linked to
+ * @return stdclass to be saved in workshopform_rubric_levels
+ */
+function workshopform_rubric_upgrade_rubric_level(stdclass $old, $newdimensionid) {
+ $new = new stdclass();
+ $new->dimensionid = $newdimensionid;
+ $new->grade = $old->rgrade * workshopform_rubric_upgrade_weight($old->eweight);
+ $new->definition = $old->rdesc;
+ $new->definitionformat = FORMAT_HTML;
+ return $new;
+}
}
// Create the url of the new question page to forward to.
- $returnurl = str_replace($CFG->wwwroot, '', $pageurl->out(false));
+ $returnurl = $pageurl->out_as_local_url(false);
$this->editquestionurl = new moodle_url('/question/question.php',
array('returnurl' => $returnurl));
if ($cm !== null){
echo $OUTPUT->render($pagingbar);
if ($totalnumber > DEFAULT_QUESTIONS_PER_PAGE) {
if ($perpage == DEFAULT_QUESTIONS_PER_PAGE) {
- $url = new moodle_url('edit.php', ($pageurl->params()+array('qperpage'=>1000)));
+ $url = new moodle_url('edit.php', array_merge($pageurl->params(), array('qperpage'=>1000)));
$showall = '<a href="'.$url.'">'.get_string('showall', 'moodle', $totalnumber).'</a>';
} else {
- $url = new moodle_url('edit.php', ($pageurl->params()+array('qperpage'=>DEFAULT_QUESTIONS_PER_PAGE)));
+ $url = new moodle_url('edit.php', array_merge($pageurl->params(), array('qperpage'=>DEFAULT_QUESTIONS_PER_PAGE)));
$showall = '<a href="'.$url.'">'.get_string('showperpage', 'moodle', DEFAULT_QUESTIONS_PER_PAGE).'</a>';
}
echo "<div class='paging'>$showall</div>";
$params = $options->editquestionparams;
if ($params['returnurl'] instanceof moodle_url) {
- $params['returnurl'] = str_replace($CFG->wwwroot, '',
- $params['returnurl']->out(false));
+ $params['returnurl'] = $params['returnurl']->out_as_local_url(false);
}
$params['id'] = $qa->get_question()->id;
$editurl = new moodle_url('/question/question.php', $params);
// Start the question form.
echo '<form method="post" action="' . $actionurl .
'" enctype="multipart/form-data" id="responseform">', "\n";
+echo '<div>';
echo '<input type="hidden" name="sesskey" value="' . sesskey() . '" />', "\n";
echo '<input type="hidden" name="slots" value="' . $slot . '" />', "\n";
+echo '</div>';
// Output the question.
echo $quba->render_question($slot, $options, $displaynumber);
get_string('responsehistory', 'question'), $hiddenofvisible);
$mform->addElement('submit', 'submit',
- get_string('restartwiththeseoptions', 'question'), $hiddenofvisible);
+ get_string('restartwiththeseoptions', 'question'));
}
}
require_once($CFG->libdir.'/questionlib.php');
// Get URL parameters.
-$requestedqtype = optional_param('qtype', '', PARAM_PLUGIN);
+$requestedqtype = optional_param('qtype', '', PARAM_SAFEDIR);
// Print the header & check permissions.
admin_externalpage_setup('reportquestioninstances', '', null, '', array('pagelayout'=>'report'));
// Work out the bits needed for the SQL WHERE clauses.
if ($requestedqtype == 'missingtype') {
+ $title = get_string('reportformissingqtypes', 'report_questioninstances');
+
$othertypes = array_keys($qtypes);
$key = array_search('missingtype', $othertypes);
unset($othertypes[$key]);
list($sqlqtypetest, $params) = $DB->get_in_or_equal($othertypes, SQL_PARAMS_QM, '', false);
$sqlqtypetest = 'WHERE qtype ' . $sqlqtypetest;
- $title = get_string('reportformissingqtypes', 'report_questioninstances');
+
} else if ($requestedqtype == '_all_') {
+ $title = get_string('reportforallqtypes', 'report_questioninstances');
+
$sqlqtypetest = '';
$params = array();
- $title = get_string('reportforallqtypes', 'report_questioninstances');
+
} else {
- $sqlqtypetest = 'WHERE qtype = ?';
- $params = array($requestedqtype);
$title = get_string('reportforqtype', 'report_questioninstances',
question_bank::get_qtype($requestedqtype)->local_name());
+
+ $sqlqtypetest = 'WHERE qtype = ?';
+ $params = array($requestedqtype);
}
// Get the question counts, and all the context information, for each
}
if ($record->repositorytype == 'coursefiles') {
// coursefiles plugin needs managefiles permission
- $capability = $capability && has_capability('moodle/course:managefiles', $current_context);
+ if (!empty($current_context)) {
+ $capability = $capability && has_capability('moodle/course:managefiles', $current_context);
+ } else {
+ $capability = $capability && has_capability('moodle/course:managefiles', get_system_context());
+ }
}
if ($is_supported && $capability) {
$repositories[$repository->id] = $repository;
$THEME->sheets = array(
+ 'pagelayout',
'core',
- 'pagelayout',
'settings',
);
width: 100%;
}
-
.has_dock.side-post-only .page-middle #region-main {
margin-left: 200px;
}
/** No blocks whatsoever **/
-.content-only #page-content #region-main-box {
- margin-left: 0px;
-}
-
-.content-only #page-content #region-post-box {
- margin-left: 0px;
-}
-
-.content-only #page-content #region-main {
+.content-only #page-content #region-main-box,
+.content-only #page-content #region-main-box #region-post-box,
+.content-only #page-content #region-main-box #region-main-wrap #region-main {
margin-left: 0px;
}
-.content-only #page-content #region-pre {
- width: 0px;
-}
-
-.content-only #page-content #region-post {
+.content-only #page-content #region-main-box #region-post-box #region-pre,
+.content-only #page-content #region-main-box #region-post-box #region-post {
width: 0px;
}
#dockeditempanel .dockeditempanel_content {background-color:#fff;border:1px solid #000;z-index:12050;}
#dockeditempanel .dockeditempanel_bd {overflow:auto;width:auto;}
#dockeditempanel .dockeditempanel_bd .block_docked {margin:10px;}
+#dockeditempanel .dockeditempanel_bd .block_navigation .block_tree li {overflow:visible;}
#dockeditempanel .dockeditempanel_hd {border-bottom:1px solid #000;text-align:right;}
#dockeditempanel .dockeditempanel_hd h2 {display:inline;margin:0;padding-right:1em;}
#dockeditempanel .dockeditempanel_hd .commands {display:inline;}
margin-right: 7px;
}
-/* Login
--------------------------*/
-
-.loginbox {
- margin: 15px 25%;
-}
-
-.loginbox .loginerrors {
- color: #f00;
-}
-
-.loginbox .loginform {
- margin: 15px auto 0;
- width: 175px;
-}
-
-.loginbox .loginform .form-label {
- float: none;
- width: 100%;
- margin: 0 auto;
- text-align: left;
-}
-.dir-rtl .loginbox .loginform .form-label {
- text-align: right;
-}
-.loginbox .loginform .form-input {
- float: none;
- width: 100%;
- margin: 0 auto;
-}
-
-.loginbox .loginform .form-input #username,
-.loginbox .loginform .form-input #password {
- width: 97%;
- padding: 3px;
- font-size: 1.1em;
- font-family: Helvetica, Arial, sans-serif;
- border: 2px solid #ddd;
- margin: 0 0 5px;
- color: #333;
-}
-
-.loginbox .loginform .form-input #loginbtn {
- margin: 0.5em auto;
-}
-
-.loginbox .forgetpass {
- margin: 1em 0 0;
- font-size: 0.95em;
-}
-
-.loginbox.twocolumns {
- width: 90%;
- margin-left: 5%;
-}
-
-.loginbox .guestsub {
- border-top: 1px solid #DDDDDD;
- margin: 5px 20%
-}
-
-.loginbox.twocolumns .loginpanel {
- border-color: #ddd;
- padding-right: 0.5%;
-}
-
-.loginbox.twocolumns .signuppanel {
- padding-left: 1%;
- width: 48%;
-}
-
-#page-course-loginas #notice {
- border: none;
-}
-
-#page-login-forgot_password .generalbox {
- margin: 0 auto 1.5em;
- width: 75%;
- padding: 10px;
-}
-
-#page-login-signup .mform {
- width: 85%;
- margin: 0 auto;
-}
-
-#page-login-signup .mform .fitem .fitemtitle {
- width: 20%;
-}
-
-#page-login-signup .mform .fitem .felement {
- margin-left: 21%;
-}
-
/* Calendar
-------------------------*/
'core',
'pagelayout',
'menu',
- 'report'
+ 'report',
+ 'admin'
);
////////////////////////////////////////////////////
'defaultregion' => 'side-post',
),
'admin' => array(
- 'file' => 'general.php',
+ 'theme' => 'base',
+ 'file' => 'report.php',
'regions' => array('side-pre'),
'defaultregion' => 'side-pre',
),
--- /dev/null
+/** Admin layout **/
+
+body.pagelayout-admin {
+ background-image: none;
+ background-color: #fff;
+}
+
+body.pagelayout-admin.has_dock {
+ margin-left: 30px;
+}
+.pagelayout-admin #page {
+ width: 100%;
+ margin: 0 auto;
+ position: relative;
+}
+.pagelayout-admin #page-header,
+.pagelayout-admin #page-footer {
+ float: none;
+ background: #f3f3f3 none;
+ width: 100%;
+ margin: 0;
+ padding: 0;
+ text-align: left;
+}
+.pagelayout-admin #page-header {
+ background:#97d3f4 url([[pix:theme|header]]) no-repeat top right;
+ margin-bottom: 0px;
+ height: 105px;
+ border-bottom: 1px solid #FFF;
+}
+
+.pagelayout-admin #page-header #custommenu {
+ display: none;
+}
+.pagelayout-admin .navbar {
+ background-color: #FFF;
+ height: 20px;
+ margin: 0;
+ padding: 5px 0;
+}
+
+.pagelayout-admin #page-footer {
+ text-align: center;
+ height: auto;
+}
+.pagelayout-admin #page-footer .logininfo,
+.pagelayout-admin #page-footer .homelink {
+ margin: 1em 0 0;
+ padding: 0;
+ text-align: center;
+}
+
+.pagelayout-admin #page-content {
+ background: #FFF url([[pix:theme|top_bg]]) repeat-x center top;
+ float: none;
+ overflow: visible;
+ width: auto;
+ padding-top: 1em;
+}
+.pagelayout-admin #report-main-content {
+ float: left;
+ width: 100%;
+}
+.pagelayout-admin #report-main-content .region-content {
+ margin-left: 210px;
+ overflow: visible;
+ padding-bottom: 20px;
+}
+.pagelayout-admin #report-main-content .region-content table.generaltable {
+ background-color: #FFF;
+ width: 98%;
+ margin: 0 auto;
+ padding: 0;
+}
+.pagelayout-admin #report-region-wrap {
+ width: 0;
+ float: right;
+ position: relative;
+ left: -100%;
+}
+.pagelayout-admin #report-region-pre {
+ width: 200px;
+ margin-left: 5px;
+}
+
+/** CONTENT ONLY **/
+.pagelayout-admin.content-only #report-main-content .region-content {
+ margin-left: 10px;
+}
+.pagelayout-admin.content-only #report-region-pre {
+ width: 0;
+}
+
+/** Correct for right to left languages **/
+.dir-rtl.pagelayout-admin #report-main-content .region-content {
+ margin-left: 0;
+ margin-right: 210px;
+}
+.dir-rtl.pagelayout-admin #report-region-wrap {
+ left:0;
+}
+
+/** Stabalise IE6 behaviour on the report layout **/
+.ie6.pagelayout-admin #report-main-content {
+ float: none;
+ width: auto;
+}
+.ie6.pagelayout-admin #report-region-wrap {
+ float: none;
+ width: 200px;
+ left: auto;
+ position: absolute;
+ top: 0;
+}
+.ie6.pagelayout-admin #report-region-pre,
+.ie6.pagelayout-admin #report-region-pre .block {
+ width: 100%;
+}
+
+@media print {
+ .pagelayout-admin .region-content {margin-left: 0px !important;}
+ .pagelayout-admin #report-region-pre {width: 0px !important;}
+ .pagelayout-admin .region-content table.generaltable {font-size:70% !important;}
+ .pagelayout-admin #report-region-pre,
+ .pagelayout-admin #page-header,
+ .pagelayout-admin #page-footer,
+ .pagelayout-admin #dock { display: none;}
+}
.pagelayout-report .region-content {margin-left: 0px !important;}
.pagelayout-report #report-region-pre {width: 0px !important;}
.pagelayout-report .region-content table.generaltable {font-size:70% !important;}
+ .pagelayout-report #report-region-pre,
.pagelayout-report #page-header,
.pagelayout-report #page-footer,
.pagelayout-report #dock { display: none;}
**
*********************************************************/
-/* Global
+/* Global
------------------------*/
html { /* Reset html page to 0 padding/margins */
padding: 0;
width: 100%;
}
-body,h1,h2,h3,h4,h5,h6,p,ul,ol,dl,input,textarea { /* Set fonttype for site */
+body,h1,h2,h3,h4,h5,h6,p,ul,ol,dl,input,textarea { /* Set fonttype for site */
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
display: none;
}
-.loginpanel {
- background: url([[pix:theme|loginpanel]]) top center no-repeat;
+.loginbox.twocolumns .loginpanel {
+ border-right: 1px solid #ddd;
+}
+
+.loginpanel, .signuppanel {
+ background: url([[pix:theme|loginpanel]]) center top no-repeat;
height: 480px;
+ margin-top: -5px;
}
.loginbox .loginpanel .subcontent {
clear: right;
width: 300px;
}
-/* fix issues conflicting with the floating columns */
+/* fix issues conflicting with the floating columns */
.clearer {
clear:left;
}
-/* Header
+/* Header
-----------------------*/
#page-header { /* Set height for header */
height: 60px;
}
-#userdetails_loggedout h1{ /* positioning of user h1 tag*/
+#userdetails_loggedout h1{ /* positioning of user h1 tag*/
padding-top:40px
}
/* Mini Calendar
------------------------*/
-.block .minicalendar { /* setting background colour for mini cal*/
+.block .minicalendar { /* setting background colour for mini cal*/
background: #fff;
}
-.block .minicalendar td.weekend { /* setting weekend date colour */
+.block .minicalendar td.weekend { /* setting weekend date colour */
color:#7c3041;
}
// See if we got anything.
if ($this->multiselect) {
$userids = optional_param_array($this->name, array(), PARAM_INTEGER);
- } else {
- $userid = optional_param($this->name, 0, PARAM_INTEGER);
- if (empty($userid)) {
- return array();
- }
+ } else if ($userid = optional_param($this->name, 0, PARAM_INTEGER)) {
$userids = array($userid);
}
+ // If there are no users there is nobody to load
+ if (empty($userids)) {
+ return array();
+ }
// If we did, use the find_users method to validate the ids.
$this->validatinguserids = $userids;