Merge branch 'MDL-30408-master' of git://github.com/sammarshallou/moodle
authorEloy Lafuente (stronk7) <stronk7@moodle.org>
Tue, 17 Jan 2012 00:43:19 +0000 (01:43 +0100)
committerEloy Lafuente (stronk7) <stronk7@moodle.org>
Tue, 17 Jan 2012 00:43:19 +0000 (01:43 +0100)
62 files changed:
admin/cli/install.php
admin/cli/mysql_engine.php
admin/index.php
admin/renderer.php
admin/roles/lib.php
admin/tool/innodb/index.php
admin/tool/unittest/ex_reporter.php
admin/user.php
course/lib.php
grade/grading/pick.php
grade/report/grader/styles.css
group/autogroup.php
group/externallib.php
lang/en/admin.php
lang/en/moodle.php
lib/adminlib.php
lib/ajax/ajaxlib.php
lib/ajax/section_classes.js
lib/db/install.xml
lib/db/upgrade.php
lib/filelib.php
lib/moodlelib.php
lib/navigationlib.php
lib/outputrequirementslib.php
lib/simpletest/testtextlib.php
lib/simpletest/testweblib.php
lib/textlib.class.php
lib/upgradelib.php
lib/weblib.php
mod/quiz/attempt.php
mod/quiz/attemptlib.php
mod/quiz/db/install.xml
mod/quiz/db/upgrade.php
mod/quiz/edit.php
mod/quiz/editlib.php
mod/quiz/lang/en/quiz.php
mod/quiz/locallib.php
mod/quiz/report/overview/overview_table.php
mod/quiz/report/statistics/version.php
mod/quiz/simpletest/testquizobj.php
mod/quiz/startattempt.php
mod/quiz/version.php
mod/scorm/datamodels/scorm_13.js.php
mod/workshop/form/accumulative/backup/moodle1/lib.php
mod/workshop/form/comments/backup/moodle1/lib.php
mod/workshop/form/numerrors/backup/moodle1/lib.php
mod/workshop/form/rubric/backup/moodle1/lib.php
question/editlib.php
question/engine/renderer.php
question/preview.php
question/previewlib.php
report/questioninstances/index.php
repository/lib.php
theme/arialist/config.php
theme/arialist/style/pagelayout.css
theme/base/style/dock.css
theme/canvas/style/core.css
theme/sky_high/config.php
theme/sky_high/style/admin.css [new file with mode: 0644]
theme/sky_high/style/report.css
theme/splash/style/sl.css
user/selector/lib.php

index facda35..b812aaf 100644 (file)
@@ -337,12 +337,7 @@ $CFG->httpswwwroot  = $CFG->wwwroot;
 
 
 //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;
index 53c4b84..c6d7c6e 100644 (file)
@@ -76,7 +76,7 @@ if (!empty($options['engine'])) {
         }
         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++;
     }
index b4bcff7..7e8a6fc 100644 (file)
@@ -190,6 +190,15 @@ if ($version > $CFG->version) {  // upgrade
     $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)";
index d823e0e..0142950 100644 (file)
@@ -57,6 +57,26 @@ class core_admin_renderer extends plugin_renderer_base {
         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
@@ -339,8 +359,10 @@ class core_admin_renderer extends plugin_renderer_base {
             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));
     }
 
     /**
index 68a3c8b..d2dbaba 100644 (file)
@@ -1044,10 +1044,9 @@ class potential_assignees_below_course extends role_assign_user_selector_base {
         $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';
 
@@ -1096,10 +1095,9 @@ class potential_assignees_course_and_above extends role_assign_user_selector_bas
         $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';
 
index faaea89..bbe4d85 100644 (file)
@@ -50,7 +50,7 @@ if (data_submitted() and $confirm and confirm_sesskey()) {
         $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);
     }
index 995bebd..5d440f3 100644 (file)
@@ -289,4 +289,9 @@ class ExHtmlReporter extends HtmlReporter {
     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);
+    }
 }
index 1ccb69f..56e457e 100644 (file)
     $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'));
index 383eb53..e5dc991 100644 (file)
@@ -49,6 +49,11 @@ define('MOD_CLASS_RESOURCE', 1);
 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':
@@ -3101,11 +3106,12 @@ function make_editing_buttons(stdClass $mod, $absolute_ignored = true, $movesele
         $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()));
@@ -3222,16 +3228,19 @@ function make_editing_buttons(stdClass $mod, $absolute_ignored = true, $movesele
         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';
         }
@@ -3240,10 +3249,10 @@ function make_editing_buttons(stdClass $mod, $absolute_ignored = true, $movesele
                 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'));
         }
     }
 
index fd4d6ef..779e95c 100644 (file)
@@ -144,8 +144,7 @@ if ($searchdata = $searchform->get_data()) {
 }
 
 // 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)";
index 20c78ed..4730ba5 100644 (file)
@@ -342,10 +342,6 @@ text-align:center;
 clear:both;
 }
 
-.path-grade-report-grader form {
-text-align:center;
-}
-
 .path-grade-report-grader input.center {
 margin:10px auto 0;
 }
index a575c33..42fc1dc 100644 (file)
@@ -172,11 +172,10 @@ if ($editform->is_cancelled()) {
 
         // 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 {
index 160dcbf..7ff57d5 100644 (file)
@@ -267,7 +267,6 @@ class core_group_external extends external_api {
 
         $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);
index ba6d8f7..13953e8 100644 (file)
@@ -330,7 +330,7 @@ For example:  standard,orangewhite.';
 $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&#145;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&#145;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';
@@ -971,6 +971,8 @@ $string['upgradelogs'] = 'For full functionality, your old logs need to be upgra
 $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 &quot;Save changes&quot; 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 />
index 7f8fb12..28e82c6 100644 (file)
@@ -236,7 +236,7 @@ $string['clear'] = 'Clear';
 $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';
@@ -672,7 +672,7 @@ $string['folderopened'] = 'Opened folder';
 $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';
index a071fdf..72d6df3 100644 (file)
@@ -3051,7 +3051,7 @@ class admin_setting_bloglevel extends admin_setting_configselect {
      */
     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));
index 37d0f29..f7d378f 100644 (file)
@@ -149,10 +149,9 @@ class jsportal {
         $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";
index cac7cec..c787e3f 100644 (file)
@@ -620,9 +620,9 @@ resource_class.prototype.init_buttons = function() {
     }
 
     // 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');
@@ -864,13 +864,13 @@ resource_class.prototype.toggle_groupmode = function() {
 
     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;
     }
 
index dc937ce..657814d 100644 (file)
@@ -1,5 +1,5 @@
 <?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">
index ea92158..ca60e07 100644 (file)
@@ -112,6 +112,29 @@ function xmldb_main_upgrade($oldversion) {
         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;
 }
 
index e3b4a22..ee4db2f 100644 (file)
@@ -3187,6 +3187,10 @@ function file_pluginfile($relativepath, $forcedownload) {
             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()) {
@@ -3198,10 +3202,6 @@ function file_pluginfile($relativepath, $forcedownload) {
                 }
             }
         }
-        $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) {
index 2b62236..0b718aa 100644 (file)
@@ -3367,7 +3367,7 @@ function get_extra_user_fields($context, $already = array()) {
     }
 
     // Split showuseridentity on comma
-    if ($CFG->showuseridentity === '') {
+    if (empty($CFG->showuseridentity)) {
         // Explode gives wrong result with empty string
         $extra = array();
     } else {
@@ -5240,6 +5240,11 @@ function generate_email_supportuser() {
 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();
@@ -5256,9 +5261,9 @@ function setnew_password_and_mail($user) {
     $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);
@@ -10055,40 +10060,20 @@ function object_property_exists( $obj, $property ) {
  * 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;
index 22a7f68..4f30b84 100644 (file)
@@ -1707,24 +1707,17 @@ class global_navigation extends navigation_node {
     /**
      * 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;
index 0e31bdd..56fbe20 100644 (file)
@@ -132,7 +132,7 @@ class page_requirements_manager {
             $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?';
index 09f1458..2b86475 100644 (file)
@@ -83,6 +83,8 @@ class textlib_test extends UnitTestCase {
 
     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');
index 35caaca..bdcdd55 100644 (file)
@@ -127,6 +127,15 @@ class web_test extends UnitTestCase {
         $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>'));
     }
index 558be5c..9702738 100644 (file)
@@ -182,7 +182,7 @@ class textlib {
     }
 
     /**
-     * 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
@@ -194,18 +194,39 @@ class textlib {
         $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
@@ -215,7 +236,11 @@ class textlib {
         $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);
@@ -236,7 +261,7 @@ class textlib {
         $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);
@@ -257,7 +282,7 @@ class textlib {
         $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);
@@ -268,7 +293,7 @@ class textlib {
     }
 
     /**
-     * UTF-8 ONLY safe strpos(), uses iconv..
+     * UTF-8 ONLY safe strpos(), uses mbstring, falls back to iconv.
      *
      * @param string $haystack
      * @param string $needle
@@ -276,18 +301,26 @@ class textlib {
      * @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');
+        }
     }
 
     /**
index b2db2b8..6fed9b1 100644 (file)
@@ -257,6 +257,41 @@ function upgrade_plugin_savepoint($result, $version, $type, $plugin, $allowabort
     }
 }
 
+/**
+ * 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
index 89bdce5..c97e06b 100644 (file)
@@ -717,6 +717,28 @@ class moodle_url {
         $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 &amp; 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);
+    }
 }
 
 /**
index 5c5395d..1440106 100644 (file)
@@ -96,6 +96,11 @@ if (empty($slots)) {
     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());
index 385832d..3dbbe75 100644 (file)
@@ -90,7 +90,12 @@ class quiz {
         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('')?
+        }
     }
 
     /**
@@ -602,6 +607,11 @@ class quiz_attempt {
         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).
index d57135c..7eb850d 100644 (file)
@@ -61,8 +61,9 @@
         <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>
index 92d7d98..a512fc2 100644 (file)
@@ -70,6 +70,18 @@ function xmldb_quiz_upgrade($oldversion) {
         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;
 }
 
index 257208e..1d4d665 100644 (file)
@@ -275,8 +275,8 @@ if (($deleteemptypage !== false) && confirm_sesskey()) {
 $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);
 }
 
@@ -496,9 +496,7 @@ if ($quiz_reordertool) {
 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) {
@@ -561,7 +559,7 @@ if (!$quiz_reordertool) {
     $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,
     ));
     ?>
index 608e38e..6294f16 100644 (file)
@@ -248,8 +248,8 @@ function quiz_add_page_break_after($layout, $questionid) {
 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);
 }
 
 /**
@@ -453,7 +453,7 @@ function quiz_print_question_list($quiz, $pageurl, $allowdelete, $reordertool,
 
     $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) {
@@ -731,7 +731,7 @@ function quiz_print_pagecontrols($quiz, $pageurl, $page, $hasattempts, $defaultc
     $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,
index 897a16d..528166a 100644 (file)
@@ -127,7 +127,9 @@ $string['cannotsavenumberofquestion'] = 'Could not save number of questions per
 $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';
index 7e10d16..9682ca0 100644 (file)
@@ -69,6 +69,11 @@ define('QUIZ_SHOW_TIME_BEFORE_DEADLINE', '3600');
 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();
@@ -386,10 +391,13 @@ function quiz_has_feedback($quiz) {
  * 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)
@@ -399,13 +407,20 @@ function quiz_update_sumgrades($quiz) {
             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();
@@ -829,7 +844,7 @@ function quiz_question_edit_button($cmid, $question, $returnurl, $contentafteric
     // 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);
index fd55a97..89214d5 100644 (file)
@@ -81,7 +81,7 @@ class quiz_report_overview_table extends quiz_attempt_report_table {
                 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';
@@ -127,7 +127,7 @@ class quiz_report_overview_table extends quiz_attempt_report_table {
             } else {
                 $record = new stdClass();
                 $record->grade = null;
-                $record->numaveraged = null;
+                $record->numaveraged = 0;
             }
 
             $row['qsgrade' . $question->slot] = $this->format_average($record, true);
@@ -151,7 +151,7 @@ class quiz_report_overview_table extends quiz_attempt_report_table {
 
         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 {
index cfd14ce..e0675e1 100644 (file)
@@ -25,7 +25,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2011062600;
-$plugin->requires  = 2011060313;
+$plugin->version   = 2011122300;
+$plugin->requires  = 2012020200;
 $plugin->cron      = 18000;
 $plugin->component = 'quiz_statistics';
index 625e8d5..59e83fb 100644 (file)
@@ -64,4 +64,19 @@ class quiz_class_test extends UnitTestCase {
         $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());
+    }
 }
index c3e31d8..5732193 100644 (file)
@@ -33,7 +33,7 @@ require_once($CFG->dirroot . '/mod/quiz/locallib.php');
 // 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');
@@ -50,9 +50,13 @@ $PAGE->set_url($quizobj->view_url());
 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.
@@ -83,6 +87,10 @@ if ($lastattempt && !$lastattempt->timefinish) {
     $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()) {
@@ -95,6 +103,10 @@ if ($lastattempt && !$lastattempt->timefinish) {
 
     $messages = $accessmanager->prevent_access() +
             $accessmanager->prevent_new_attempt(count($attempts), $lastattempt);
+
+    if ($page == -1) {
+        $page = 0;
+    }
 }
 
 // Check access.
index 33124f0..578958f 100644 (file)
@@ -25,7 +25,7 @@
 
 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;
index 8349cb1..899985e 100644 (file)
@@ -90,9 +90,9 @@ function SCORMapi1_3() {
     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+).';
index 20293f8..c33e8bc 100644 (file)
@@ -26,8 +26,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-require_once($CFG->dirroot.'/mod/workshop/form/accumulative/db/upgradelib.php');
-
 /**
  * Conversion handler for the accumulative grading strategy data
  */
@@ -171,3 +169,46 @@ class moodle1_workshopform_accumulative_handler extends moodle1_workshopform_han
         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;
+}
index a0aed8b..10b6b28 100644 (file)
@@ -26,8 +26,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-require_once($CFG->dirroot.'/mod/workshop/form/comments/db/upgradelib.php');
-
 /**
  * Conversion handler for the comments grading strategy data
  */
@@ -48,3 +46,19 @@ class moodle1_workshopform_comments_handler extends moodle1_workshopform_handler
         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;
+}
index 5bff2d5..a88a2b3 100644 (file)
@@ -26,7 +26,6 @@
 
 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
 
 /**
@@ -96,3 +95,35 @@ class moodle1_workshopform_numerrors_handler extends moodle1_workshopform_handle
         }
     }
 }
+
+/**
+ * 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;
+}
index b1c5cb2..be16f7c 100644 (file)
@@ -26,8 +26,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-require_once($CFG->dirroot.'/mod/workshop/form/rubric/db/upgradelib.php');
-
 /**
  * Conversion handler for the rubric grading strategy data
  */
@@ -141,3 +139,21 @@ class moodle1_workshopform_rubric_handler extends moodle1_workshopform_handler {
         }
     }
 }
+
+/**
+ * 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;
+}
index 7f781a1..a0cc6b3 100644 (file)
@@ -871,7 +871,7 @@ class question_bank_view {
         }
 
         // 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){
@@ -1360,10 +1360,10 @@ class question_bank_view {
         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>";
index 96b8353..006729a 100644 (file)
@@ -278,8 +278,7 @@ class core_question_renderer extends plugin_renderer_base {
 
         $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);
index 6981dd4..a50f9cc 100644 (file)
@@ -228,8 +228,10 @@ echo $OUTPUT->header();
 // 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);
index 6af8f58..5d40879 100644 (file)
@@ -89,7 +89,7 @@ class preview_options_form extends moodleform {
                 get_string('responsehistory', 'question'), $hiddenofvisible);
 
         $mform->addElement('submit', 'submit',
-                get_string('restartwiththeseoptions', 'question'), $hiddenofvisible);
+                get_string('restartwiththeseoptions', 'question'));
     }
 }
 
index 9f8a3f7..393bfa6 100644 (file)
@@ -28,7 +28,7 @@ require_once($CFG->libdir.'/adminlib.php');
 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'));
@@ -62,21 +62,26 @@ if ($requestedqtype) {
 
     // 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
index d390420..5db4888 100644 (file)
@@ -869,7 +869,11 @@ abstract class repository {
                     }
                     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;
index a469b5a..751523c 100644 (file)
@@ -54,8 +54,8 @@ $THEME->parents = array(
 
 
 $THEME->sheets = array(
+    'pagelayout',
        'core',
-       'pagelayout',
        'settings',
 );
 
index 5c8249c..dbaf485 100644 (file)
@@ -75,29 +75,19 @@ body {
     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;
 }
 
index 4dd92f0..30acfef 100644 (file)
@@ -22,6 +22,7 @@ body.has_dock {margin-left:30px;}
 #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;}
index f763f97..b1e5f48 100644 (file)
@@ -81,100 +81,6 @@ input[type="radio"] {
     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
 -------------------------*/
 
index 5f6d6c6..2f7c358 100644 (file)
@@ -55,7 +55,8 @@ $THEME->sheets = array(
     'core',
     'pagelayout',
     'menu',
-    'report'
+    'report',
+    'admin'
 );
 
 ////////////////////////////////////////////////////
@@ -119,7 +120,8 @@ $THEME->layouts = array(
         'defaultregion' => 'side-post',
     ),
     'admin' => array(
-        'file' => 'general.php',
+        'theme' => 'base',
+        'file' => 'report.php',
         'regions' => array('side-pre'),
         'defaultregion' => 'side-pre',
     ),
diff --git a/theme/sky_high/style/admin.css b/theme/sky_high/style/admin.css
new file mode 100644 (file)
index 0000000..0cf29a7
--- /dev/null
@@ -0,0 +1,128 @@
+/** 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;}
+}
index 5e8f3ae..570bb96 100644 (file)
@@ -121,6 +121,7 @@ body.pagelayout-report.has_dock {
     .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;}
index eadc4ff..2f4e50a 100644 (file)
@@ -7,7 +7,7 @@
 **
 *********************************************************/
 
-/* Global 
+/* Global
 ------------------------*/
 html {                /* Reset html page to 0 padding/margins */
     padding: 0;
@@ -22,7 +22,7 @@ body {                /* Define margins and background colour/image */
     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;
 }
 
@@ -58,9 +58,14 @@ a:active {
     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 {
@@ -68,12 +73,12 @@ a:active {
     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 */
@@ -151,7 +156,7 @@ a:active {
     height: 60px;
 }
 
-#userdetails_loggedout h1{ /* positioning of user h1 tag*/ 
+#userdetails_loggedout h1{ /* positioning of user h1 tag*/
     padding-top:40px
 }
 
@@ -462,11 +467,11 @@ div.summary {
 /* 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;
 }
 
index 9dd55f6..b2aa1c4 100644 (file)
@@ -369,13 +369,13 @@ abstract class user_selector_base {
         // 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;