Merge branch 'w36_MDL-29025_m22_verboseauthdb' of git://github.com/skodak/moodle
authorSam Hemelryk <sam@moodle.com>
Mon, 12 Sep 2011 05:48:09 +0000 (17:48 +1200)
committerSam Hemelryk <sam@moodle.com>
Mon, 12 Sep 2011 05:48:09 +0000 (17:48 +1200)
26 files changed:
admin/settings/courses.php
backup/controller/backup_controller.class.php
backup/util/checks/backup_check.class.php
backup/util/checks/restore_check.class.php
backup/util/dbops/backup_controller_dbops.class.php
course/lib.php
course/modduplicate.php
course/recent_form.php
course/rest.php
enrol/database/lib.php
files/externallib.php
lang/en/admin.php
lang/en/moodle.php
lib/db/upgrade.php
lib/filterlib.php
lib/outputcomponents.php
lib/textlib.class.php
mod/wiki/instancecomments.php
mod/wiki/lang/en/wiki.php
mod/wiki/pagelib.php
mod/wiki/restoreversion.php
mod/wiki/styles.css
question/type/multianswer/edit_multianswer_form.php
repository/lib.php
theme/formal_white/style/pagelayout.css
version.php

index 45b1ab3..f94775c 100644 (file)
@@ -142,7 +142,7 @@ if ($hassiteconfig
 
 
     $temp->add(new admin_setting_heading('automatedsettings', get_string('automatedsettings','backup'), ''));
-    $temp->add(new admin_setting_configcheckbox('backup/backup_auto_users', get_string('users'), get_string('backupusershelp'), 1));
+    $temp->add(new admin_setting_configcheckbox('backup/backup_auto_users', get_string('generalusers', 'backup'), get_string('configgeneralusers', 'backup'), 1));
     $temp->add(new admin_setting_configcheckbox('backup/backup_auto_role_assignments', get_string('generalroleassignments','backup'), get_string('configgeneralroleassignments','backup'), 1));
     $temp->add(new admin_setting_configcheckbox('backup/backup_auto_user_files', get_string('generaluserfiles', 'backup'), get_string('configgeneraluserfiles','backup'), 1));
     $temp->add(new admin_setting_configcheckbox('backup/backup_auto_activities', get_string('generalactivities','backup'), get_string('configgeneralactivities','backup'), 1));
@@ -150,7 +150,7 @@ if ($hassiteconfig
     $temp->add(new admin_setting_configcheckbox('backup/backup_auto_filters', get_string('generalfilters','backup'), get_string('configgeneralfilters','backup'), 1));
     $temp->add(new admin_setting_configcheckbox('backup/backup_auto_comments', get_string('generalcomments','backup'), get_string('configgeneralcomments','backup'), 1));
     $temp->add(new admin_setting_configcheckbox('backup/backup_auto_userscompletion', get_string('generaluserscompletion','backup'), get_string('configgeneraluserscompletion','backup'), 1));
-    $temp->add(new admin_setting_configcheckbox('backup/backup_auto_logs', get_string('logs'), get_string('backuplogshelp'), 0));
+    $temp->add(new admin_setting_configcheckbox('backup/backup_auto_logs', get_string('generallogs', 'backup'), get_string('configgenerallogs', 'backup'), 0));
     $temp->add(new admin_setting_configcheckbox('backup/backup_auto_histories', get_string('generalhistories','backup'), get_string('configgeneralhistories','backup'), 0));
 
 
index cd05481..1bab62b 100644 (file)
@@ -339,7 +339,7 @@ class backup_controller extends backup implements loggable {
 
     protected function apply_defaults() {
         $this->log('applying plan defaults', backup::LOG_DEBUG);
-        backup_controller_dbops::apply_general_config_defaults($this);
+        backup_controller_dbops::apply_config_defaults($this);
         $this->set_status(backup::STATUS_CONFIGURED);
     }
 }
index 39d0e96..881c73c 100644 (file)
@@ -102,45 +102,31 @@ abstract class backup_check {
         // Note: all the checks along the function MUST be performed for $userid, that
         // is the user who "requested" the course backup, not current $USER at all!!
 
-        // First of all, check the main backup[course|section|activity] principal caps
-        // Lacking the corresponding one makes this to break with exception always
+        // First of all, decide which caps/contexts are we going to check
+        // for common backups (general, automated...) based exclusively
+        // in the type (course, section, activity). And store them into
+        // one capability => context array structure
+        $typecapstocheck = array();
         switch ($type) {
             case backup::TYPE_1COURSE :
                 $DB->get_record('course', array('id' => $id), '*', MUST_EXIST); // course exists
-                if (!has_capability('moodle/backup:backupcourse', $coursectx, $userid)) {
-                    $a = new stdclass();
-                    $a->userid = $userid;
-                    $a->courseid = $courseid;
-                    $a->capability = 'moodle/backup:backupcourse';
-                    throw new backup_controller_exception('backup_user_missing_capability', $a);
-                }
+                $typecapstocheck['moodle/backup:backupcourse'] = $coursectx;
                 break;
             case backup::TYPE_1SECTION :
                 $DB->get_record('course_sections', array('course' => $courseid, 'id' => $id), '*', MUST_EXIST); // sec exists
-                if (!has_capability('moodle/backup:backupsection', $coursectx, $userid)) {
-                    $a = new stdclass();
-                    $a->userid = $userid;
-                    $a->courseid = $courseid;
-                    $a->capability = 'moodle/backup:backupsection';
-                    throw new backup_controller_exception('backup_user_missing_capability', $a);
-                }
+                $typecapstocheck['moodle/backup:backupsection'] = $coursectx;
                 break;
             case backup::TYPE_1ACTIVITY :
                 get_coursemodule_from_id(null, $id, $courseid, false, MUST_EXIST); // cm exists
                 $modulectx = get_context_instance(CONTEXT_MODULE, $id);
-                if (!has_capability('moodle/backup:backupactivity', $modulectx, $userid)) {
-                    $a = new stdclass();
-                    $a->userid = $userid;
-                    $a->cmid = $id;
-                    $a->capability = 'moodle/backup:backupactivity';
-                    throw new backup_controller_exception('backup_user_missing_capability', $a);
-                }
+                $typecapstocheck['moodle/backup:backupactivity'] = $modulectx;
                 break;
             default :
-                print_error('unknownbackuptype');
+                throw new backup_controller_exception('backup_unknown_backup_type', $type);
         }
 
         // Now, if backup mode is hub or import, check userid has permissions for those modes
+        // other modes will perform common checks only (backupxxxx capabilities in $typecapstocheck)
         switch ($mode) {
             case backup::MODE_HUB:
                 if (!has_capability('moodle/backup:backuptargethub', $coursectx, $userid)) {
@@ -160,6 +146,18 @@ abstract class backup_check {
                     throw new backup_controller_exception('backup_user_missing_capability', $a);
                 }
                 break;
+            // Common backup (general, automated...), let's check all the $typecapstocheck
+            // capability => context pairs
+            default:
+                foreach ($typecapstocheck as $capability => $context) {
+                    if (!has_capability($capability, $context, $userid)) {
+                        $a = new stdclass();
+                        $a->userid = $userid;
+                        $a->courseid = $courseid;
+                        $a->capability = $capability;
+                        throw new backup_controller_exception('backup_user_missing_capability', $a);
+                    }
+                }
         }
 
         // Now, enforce 'moodle/backup:userinfo' to 'users' setting, applying changes if allowed,
@@ -219,15 +217,19 @@ abstract class backup_check {
         }
 
         // Check the user has the ability to configure the backup. If not then we need
-        // to lock all settings by permission so that no changes can be made.
-        $hasconfigcap = has_capability('moodle/backup:configure', $coursectx, $userid);
-        if (!$hasconfigcap) {
-            $settings = $backup_controller->get_plan()->get_settings();
-            foreach ($settings as $setting) {
-                if ($setting->get_name()=='filename') {
-                    continue;
+        // to lock all settings by permission so that no changes can be made. This does
+        // not apply to the import facility, where the activities must be always enabled
+        // to be able to pick them
+        if ($mode != backup::MODE_IMPORT) {
+            $hasconfigcap = has_capability('moodle/backup:configure', $coursectx, $userid);
+            if (!$hasconfigcap) {
+                $settings = $backup_controller->get_plan()->get_settings();
+                foreach ($settings as $setting) {
+                    if ($setting->get_name() == 'filename') {
+                        continue;
+                    }
+                    $setting->set_status(base_setting::LOCKED_BY_PERMISSION);
                 }
-                $setting->set_status(base_setting::LOCKED_BY_PERMISSION);
             }
         }
 
index 20e1f94..915112c 100644 (file)
@@ -68,41 +68,27 @@ abstract class restore_check {
         // Note: all the checks along the function MUST be performed for $userid, that
         // is the user who "requested" the course restore, not current $USER at all!!
 
-        // First of all, check the main restore[course|section|activity] principal caps
-        // Lacking the corresponding one makes this to break with exception always
+        // First of all, decide which caps/contexts are we going to check
+        // for common backups (general, automated...) based exclusively
+        // in the type (course, section, activity). And store them into
+        // one capability => context array structure
+        $typecapstocheck = array();
         switch ($type) {
             case backup::TYPE_1COURSE :
-                if (!has_capability('moodle/restore:restorecourse', $coursectx, $userid)) {
-                    $a = new stdclass();
-                    $a->userid = $userid;
-                    $a->courseid = $courseid;
-                    $a->capability = 'moodle/restore:restorecourse';
-                    throw new restore_controller_exception('restore_user_missing_capability', $a);
-                }
+                $typecapstocheck['moodle/restore:restorecourse'] = $coursectx;
                 break;
             case backup::TYPE_1SECTION :
-                if (!has_capability('moodle/restore:restoresection', $coursectx, $userid)) {
-                    $a = new stdclass();
-                    $a->userid = $userid;
-                    $a->courseid = $courseid;
-                    $a->capability = 'moodle/restore:restoresection';
-                    throw new restore_controller_exception('restore_user_missing_capability', $a);
-                }
+                $typecapstocheck['moodle/restore:restoresection'] = $coursectx;
                 break;
             case backup::TYPE_1ACTIVITY :
-                if (!has_capability('moodle/restore:restoreactivity', $coursectx, $userid)) {
-                    $a = new stdclass();
-                    $a->userid = $userid;
-                    $a->courseid = $courseid;
-                    $a->capability = 'moodle/restore:restoreactivity';
-                    throw new restore_controller_exception('restore_user_missing_capability', $a);
-                }
+                $typecapstocheck['moodle/restore:restoreactivity'] = $coursectx;
                 break;
             default :
-                print_error('unknownrestoretype');
+                throw new restore_controller_exception('restore_unknown_restore_type', $type);
         }
 
         // Now, if restore mode is hub or import, check userid has permissions for those modes
+        // other modes will perform common checks only (restorexxxx capabilities in $typecapstocheck)
         switch ($mode) {
             case backup::MODE_HUB:
                 if (!has_capability('moodle/restore:restoretargethub', $coursectx, $userid)) {
@@ -122,6 +108,18 @@ abstract class restore_check {
                     throw new restore_controller_exception('restore_user_missing_capability', $a);
                 }
                 break;
+            // Common backup (general, automated...), let's check all the $typecapstocheck
+            // capability => context pairs
+            default:
+                foreach ($typecapstocheck as $capability => $context) {
+                    if (!has_capability($capability, $context, $userid)) {
+                        $a = new stdclass();
+                        $a->userid = $userid;
+                        $a->courseid = $courseid;
+                        $a->capability = $capability;
+                        throw new restore_controller_exception('restore_user_missing_capability', $a);
+                    }
+                }
         }
 
         // Now, enforce 'moodle/restore:userinfo' to 'users' setting, applying changes if allowed,
@@ -158,12 +156,16 @@ abstract class restore_check {
         }
 
         // Check the user has the ability to configure the restore. If not then we need
-        // to lock all settings by permission so that no changes can be made.
-        $hasconfigcap = has_capability('moodle/restore:configure', $coursectx, $userid);
-        if (!$hasconfigcap) {
-            $settings = $restore_controller->get_plan()->get_settings();
-            foreach ($settings as $setting) {
-                $setting->set_status(base_setting::LOCKED_BY_PERMISSION);
+        // to lock all settings by permission so that no changes can be made. This does
+        // not apply to the import facility, where all the activities (picked on backup)
+        // are restored automatically without restore UI
+        if ($mode != backup::MODE_IMPORT) {
+            $hasconfigcap = has_capability('moodle/restore:configure', $coursectx, $userid);
+            if (!$hasconfigcap) {
+                $settings = $restore_controller->get_plan()->get_settings();
+                foreach ($settings as $setting) {
+                    $setting->set_status(base_setting::LOCKED_BY_PERMISSION);
+                }
             }
         }
 
index d760871..cd89d82 100644 (file)
@@ -401,12 +401,40 @@ abstract class backup_controller_dbops extends backup_dbops {
         return $DB->get_record('course', array('id' => $courseid), 'fullname, shortname, startdate');
     }
 
+    /**
+     * Sets the default values for the settings in a backup operation
+     *
+     * Based on the mode of the backup it will delegate the process to
+     * other methods like {@link apply_general_config_defaults} ...
+     * to get proper defaults loaded
+     *
+     * @param backup_controller $controller
+     */
+    public static function apply_config_defaults(backup_controller $controller) {
+        // Based on the mode of the backup (general, automated, import, hub...)
+        // decide the action to perform to get defaults loaded
+        $mode = $controller->get_mode();
+
+        switch ($mode) {
+            case backup::MODE_GENERAL:
+                // Load the general defaults
+                self::apply_general_config_defaults($controller);
+                break;
+            case backup::MODE_AUTOMATED:
+                // TODO: Move the loading from automatic stuff to here
+                break;
+            default:
+                // Nothing to do for other modes (IMPORT/HUB...). Some day we
+                // can define defaults (admin UI...) for them if we want to
+        }
+    }
+
     /**
      * Sets the controller settings default values from the backup config.
      *
      * @param backup_controller $controller
      */
-    public static function apply_general_config_defaults(backup_controller $controller) {
+    private static function apply_general_config_defaults(backup_controller $controller) {
         $settings = array(
             // Config name                      => Setting name
             'backup_general_users'              => 'users',
index fe8630f..f98e9b3 100644 (file)
@@ -3161,13 +3161,16 @@ function make_editing_buttons(stdClass $mod, $absolute = true, $moveselect = tru
         array('class' => 'editing_update', 'title' => $str->update)
     );
 
-    // Duplicate
-    $actions[] = new action_link(
-        new moodle_url($baseurl, array('duplicate' => $mod->id)),
-        new pix_icon('t/copy', $str->duplicate, 'moodle', array('class' => 'iconsmall')),
-        null,
-        array('class' => 'editing_duplicate', 'title' => $str->duplicate)
-    );
+    // Duplicate (require both target import caps to be able to duplicate, see modduplicate.php)
+    $dupecaps = array('moodle/backup:backuptargetimport', 'moodle/restore:restoretargetimport');
+    if (has_all_capabilities($dupecaps, $coursecontext)) {
+        $actions[] = new action_link(
+            new moodle_url($baseurl, array('duplicate' => $mod->id)),
+            new pix_icon('t/copy', $str->duplicate, 'moodle', array('class' => 'iconsmall')),
+            null,
+            array('class' => 'editing_duplicate', 'title' => $str->duplicate)
+        );
+    }
 
     // Delete
     $actions[] = new action_link(
index 632f191..a9006b1 100644 (file)
@@ -44,6 +44,7 @@ $section    = $DB->get_record('course_sections', array('id' => $cm->section, 'co
 require_login($course);
 require_sesskey();
 require_capability('moodle/course:manageactivities', $context);
+// Require both target import caps to be able to duplicate, see make_editing_buttons()
 require_capability('moodle/backup:backuptargetimport', $context);
 require_capability('moodle/restore:restoretargetimport', $context);
 
index a9f78ef..b79e443 100644 (file)
@@ -40,31 +40,63 @@ class recent_form extends moodleform {
 
         $mform->addElement('header', 'filters', get_string('managefilters')); //TODO: add better string
 
+        $groupoptions = array();
+        if (groups_get_course_groupmode($COURSE) == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) {
+            // limited group access
+            $groups = groups_get_user_groups($COURSE->id);
+            $allgroups = groups_get_all_groups($COURSE->id);
+            if (!empty($groups[$COURSE->defaultgroupingid])) {
+                foreach ($groups[$COURSE->defaultgroupingid] AS $groupid) {
+                    $groupoptions[$groupid] = format_string($allgroups[$groupid]->name, true, array('context'=>$context));
+                }
+            }
+        } else {
+            $groupoptions = array('0'=>get_string('allgroups'));
+            if (has_capability('moodle/site:accessallgroups', $context)) {
+                // user can see all groups
+                $allgroups = groups_get_all_groups($COURSE->id);
+            } else {
+                // user can see course level groups
+                $allgroups = groups_get_all_groups($COURSE->id, 0, $COURSE->defaultgroupingid);
+            }
+            foreach($allgroups as $group) {
+                $groupoptions[$group->id] = format_string($group->name, true, array('context'=>$context));
+            }
+        }
+
         if ($COURSE->id == SITEID) {
             $viewparticipants = has_capability('moodle/site:viewparticipants', get_context_instance(CONTEXT_SYSTEM));
         } else {
             $viewparticipants = has_capability('moodle/course:viewparticipants', $context);
         }
 
-        $viewfullnames = has_capability('moodle/site:viewfullnames', get_context_instance(CONTEXT_COURSE, $COURSE->id));
-
         if ($viewparticipants) {
+            $viewfullnames = has_capability('moodle/site:viewfullnames', get_context_instance(CONTEXT_COURSE, $COURSE->id));
+
             $options = array();
             $options[0] = get_string('allparticipants');
             $options[$CFG->siteguest] = get_string('guestuser');
 
-            if (groups_get_course_groupmode($COURSE) == SEPARATEGROUPS) {
-                $groups = groups_get_user_groups($COURSE->id);
-                $group = $groups[0];
+            if (isset($groupoptions[0])) {
+                // can see all enrolled users
+                if ($enrolled = get_enrolled_users($context, null, 0, user_picture::fields('u'))) {
+                    foreach ($enrolled as $euser) {
+                        $options[$euser->id] = fullname($euser, $viewfullnames);
+                    }
+                }
             } else {
-                $group = '';
-            }
-
-            if ($enrolled = get_enrolled_users($context, null, $group, user_picture::fields('u'))) {
-                foreach ($enrolled as $euser) {
-                    $options[$euser->id] = fullname($euser, $viewfullnames);
+                // can see users from some groups only
+                foreach ($groupoptions as $groupid=>$unused) {
+                    if ($enrolled = get_enrolled_users($context, null, $groupid, user_picture::fields('u'))) {
+                        foreach ($enrolled as $euser) {
+                            if (!array_key_exists($euser->id, $options)) {
+                                $options[$euser->id] = fullname($euser, $viewfullnames);
+                            }
+                        }
+                    }
                 }
             }
+
             $mform->addElement('select', 'user', get_string('participants'), $options);
             $mform->setAdvanced('user');
         }
@@ -110,23 +142,14 @@ class recent_form extends moodleform {
         $mform->setAdvanced('modid');
 
 
-        if (has_capability('moodle/site:accessallgroups', $context)) {
-            if ($groups = groups_get_all_groups($COURSE->id)) {
-                $options = array('0'=>get_string('allgroups'));
-                foreach($groups as $group) {
-                    $options[$group->id] = format_string($group->name);
-                }
-                $mform->addElement('select', 'group', get_string('groups'), $options);
-                $mform->setAdvanced('group');
-            } else {
-                $mform->addElement('hidden','group');
-                $mform->setType('group', PARAM_INT);
-                $mform->setConstants(array('group'=>0));
-            }
+        if ($groupoptions) {
+            $mform->addElement('select', 'group', get_string('groups'), $groupoptions);
+            $mform->setAdvanced('group');
         } else {
+            // no access to groups in separate mode
             $mform->addElement('hidden','group');
             $mform->setType('group', PARAM_INT);
-            $mform->setConstants(array('group'=>0));
+            $mform->setConstants(array('group'=>-1));
         }
 
         $options = array('default'  => get_string('bycourseorder'),
index 7c6c04f..17be668 100644 (file)
@@ -209,6 +209,14 @@ switch($requestmethod) {
                     error_log("Ajax rest.php: Could not delete the $cm->modname $cm->name from section");
                 }
 
+                // Trigger a mod_deleted event with information about this module.
+                $eventdata = new stdClass();
+                $eventdata->modulename = $cm->modname;
+                $eventdata->cmid       = $cm->id;
+                $eventdata->courseid   = $course->id;
+                $eventdata->userid     = $USER->id;
+                events_trigger('mod_deleted', $eventdata);
+
                 rebuild_course_cache($course->id);
 
                 add_to_log($courseid, "course", "delete mod",
index 814e723..f7606b6 100644 (file)
@@ -464,6 +464,17 @@ class enrol_database_plugin extends enrol_plugin {
                     }
                 }
 
+                // assign extra roles
+                foreach ($userroles as $roleid) {
+                    if (empty($current_roles[$userid][$roleid])) {
+                        role_assign($roleid, $userid, $context->id, 'enrol_database', $instance->id);
+                        $current_roles[$userid][$roleid] = $roleid;
+                        if ($verbose) {
+                            mtrace("  assigning roles: $userid ==> $course->shortname as ".$allroles[$roleid]->shortname);
+                        }
+                    }
+                }
+
                 // unassign removed roles
                 foreach($current_roles[$userid] as $cr) {
                     if (empty($userroles[$cr])) {
index eba388b..dc351b6 100644 (file)
@@ -210,7 +210,7 @@ class moodle_file_external extends external_api {
         $dir = make_upload_directory('temp/wsupload');
 
         if (empty($fileinfo['filename'])) {
-            $filename = uniqid('wsupload').'_'.time().'.tmp';
+            $filename = uniqid('wsupload', true).'_'.time().'.tmp';
         } else {
             $filename = $fileinfo['filename'];
         }
index 56e87ae..8c817be 100644 (file)
@@ -438,7 +438,7 @@ $string['denyemailaddresses'] = 'Denied email domains';
 $string['development'] = 'Development';
 $string['devicedetectregex'] = 'Device detection regular expressions';
 $string['devicedetectregex_desc'] = '<p>By default, Moodle can detect devices of the type default (desktop PCs, laptops, etc), mobile (phones and small hand held devices), tablet (iPads, Android tablets) and legacy (Internet Explorer 6 users).  The theme selector can be used to apply separate themes to all of these.  This setting allows regular expressions that allow the detection of extra device types (these take precedence over the default types).</p>
-<p>For example, you could enter the regular expression \'/(MIDP-1.0|Maemo|Windows CE)/\' to detect some commonly used feasture phones add the return value \'featurephone\'.  This adds \'featurephone\' on the theme selector that would allow you to add a theme that would be used on these devices.  Other phones would still use the theme selected for the mobile device type.</p>';
+<p>For example, you could enter the regular expression \'/(MIDP-1.0|Maemo|Windows CE)/\' to detect some commonly used feature phones add the return value \'featurephone\'.  This adds \'featurephone\' on the theme selector that would allow you to add a theme that would be used on these devices.  Other phones would still use the theme selected for the mobile device type.</p>';
 $string['devicedetectregexexpression'] = 'Regular expression';
 $string['devicedetectregexvalue'] = 'Return value';
 $string['devicetype'] = 'Device type';
index f71435d..ecd7141 100644 (file)
@@ -178,7 +178,6 @@ $string['backupincludemoduleuserdatahelp'] = 'Choose whether you want to include
 $string['backupkeephelp'] = 'How many recent backups for each course do you want to keep? (older ones will be deleted automatically)';
 $string['backuplogdetailed'] = 'Detailed execution log';
 $string['backuploglaststatus'] = 'Last execution log';
-$string['backuplogshelp'] = 'If enabled, then course logs will be included in automated backups';
 $string['backupmissinguserinfoperms'] = 'Note: This backup contains no user data. Exercise and Workshop activities will not be included in the backup, since these modules are not compatible with this type of backup.';
 $string['backupnext'] = 'Next backup';
 $string['backupnonisowarning'] = 'Warning: this backup is from a non-Unicode version of Moodle (pre 1.6).  If this backup contains any non-ISO-8859-1 texts then they may be CORRUPTED if you try to restore them to this Unicode version of Moodle.  See the <a href="http://docs.moodle.org/en/Backup_FAQ">Backup FAQ</a> for more information about how to recover this backup correctly.';
@@ -189,7 +188,6 @@ $string['backupsitefileshelp'] = 'If enabled then site files used in courses wil
 $string['backuptakealook'] = 'Please take a look at your backup logs in:
   {$a}';
 $string['backupuserfileshelp'] = 'Choose whether user files (eg profile images) should be included in automated backups';
-$string['backupusershelp'] = 'Select whether you want to include all the users in the server or only the needed users for each course';
 $string['backupversion'] = 'Backup version';
 $string['block'] = 'Block';
 $string['blockconfiga'] = 'Configuring a {$a} block';
index a4f8809..83c897f 100644 (file)
@@ -6051,11 +6051,12 @@ WHERE gradeitemid IS NOT NULL AND grademax IS NOT NULL");
          // Define field secret to be added to registration_hubs
         $table = new xmldb_table('registration_hubs');
         $field = new xmldb_field('secret', XMLDB_TYPE_CHAR, '255', null, null, null,
-                $CFG->siteidentifier, 'confirmed');
+                null, 'confirmed');
 
-        // Conditionally launch add field secret
+        // Conditionally launch add field secret and set its value
         if (!$dbman->field_exists($table, $field)) {
             $dbman->add_field($table, $field);
+            $DB->set_field('registration_hubs', 'secret', $CFG->siteidentifier);
         }
 
         // Main savepoint reached
@@ -6696,6 +6697,18 @@ FROM
         upgrade_main_savepoint(true, 2011083100.02);
     }
 
+    if ($oldversion < 2011090700.01) {
+        // Changing the default of field secret on table registration_hubs to NULL
+        $table = new xmldb_table('registration_hubs');
+        $field = new xmldb_field('secret', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'confirmed');
+
+        // Launch change of default for field secret
+        $dbman->change_field_default($table, $field);
+
+        // Main savepoint reached
+        upgrade_main_savepoint(true, 2011090700.01);
+    }
+
     return true;
 }
 
index 125f43a..a120277 100644 (file)
@@ -977,9 +977,11 @@ function filter_context_may_have_filter_settings($context) {
  * @param array $link_array       an array of filterobjects
  * @param array $ignoretagsopen   an array of opening tags that we should ignore while filtering
  * @param array $ignoretagsclose  an array of corresponding closing tags
+ * @param bool $overridedefaultignore True to only use tags provided by arguments
  * @return string
  **/
-function filter_phrases($text, &$link_array, $ignoretagsopen=NULL, $ignoretagsclose=NULL) {
+function filter_phrases($text, &$link_array, $ignoretagsopen=NULL, $ignoretagsclose=NULL,
+        $overridedefaultignore=false) {
 
     global $CFG;
 
@@ -988,11 +990,30 @@ function filter_phrases($text, &$link_array, $ignoretagsopen=NULL, $ignoretagscl
     $ignoretags = array();  //To store all the enclosig tags to be completely ignored
     $tags = array();        //To store all the simple tags to be ignored
 
-/// A list of open/close tags that we should not replace within
-/// No reason why you can't put full preg expressions in here too
-/// eg '<script(.+?)>' to match any type of script tag
-    $filterignoretagsopen  = array('<head>' , '<nolink>' , '<span class="nolink">');
-    $filterignoretagsclose = array('</head>', '</nolink>', '</span>');
+    if (!$overridedefaultignore) {
+        // A list of open/close tags that we should not replace within
+        // Extended to include <script>, <textarea>, <select> and <a> tags
+        // Regular expression allows tags with or without attributes
+        $filterignoretagsopen  = array('<head>' , '<nolink>' , '<span class="nolink">',
+                '<script(\s[^>]*?)?>', '<textarea(\s[^>]*?)?>',
+                '<select(\s[^>]*?)?>', '<a(\s[^>]*?)?>');
+        $filterignoretagsclose = array('</head>', '</nolink>', '</span>',
+                 '</script>', '</textarea>', '</select>','</a>');
+    } else {
+        // Set an empty default list
+        $filterignoretagsopen = array();
+        $filterignoretagsclose = array();
+    }
+    // Add the user defined ignore tags to the default list
+    if ( is_array($ignoretagsopen) ) {
+        foreach ($ignoretagsopen as $open) {
+            $filterignoretagsopen[] = $open;
+        }
+        foreach ($ignoretagsclose as $close) {
+            $filterignoretagsclose[] = $close;
+        }
+    }
 
 /// Invalid prefixes and suffixes for the fullmatch searches
 /// Every "word" character, but the underscore, is a invalid suffix or prefix.
@@ -1000,19 +1021,6 @@ function filter_phrases($text, &$link_array, $ignoretagsopen=NULL, $ignoretagscl
     $filterinvalidprefixes = '([^\W_])';
     $filterinvalidsuffixes = '([^\W_])';
 
-/// Add the user defined ignore tags to the default list
-/// Unless specified otherwise, we will not replace within <a></a> tags
-    if ( $ignoretagsopen === NULL ) {
-        //$ignoretagsopen  = array('<a(.+?)>');
-        $ignoretagsopen  = array('<a\s[^>]+?>');
-        $ignoretagsclose = array('</a>');
-    }
-
-    if ( is_array($ignoretagsopen) ) {
-        foreach ($ignoretagsopen as $open) $filterignoretagsopen[] = $open;
-        foreach ($ignoretagsclose as $close) $filterignoretagsclose[] = $close;
-    }
-
     //// Double up some magic chars to avoid "accidental matches"
     $text = preg_replace('/([#*%])/','\1\1',$text);
 
index 9a4a123..f822ef9 100644 (file)
@@ -999,7 +999,15 @@ class html_writer {
      * @return string
      */
     public static function random_id($base='random') {
-        return uniqid($base);
+        static $counter = 0;
+        static $uniq;
+
+        if (!isset($uniq)) {
+            $uniq = uniqid();
+        }
+
+        $counter++;
+        return $base.$uniq.$counter;
     }
 
     /**
index c6d9d95..a488b8c 100644 (file)
@@ -592,40 +592,46 @@ abstract class collatorlib {
                 $collator = new Collator($locale);
                 if (!empty($collator) && $collator instanceof Collator) {
                     // Check for non fatal error messages. This has to be done immediately
-                    // after instantiation as any futher calls to collation will cause
-                    // it to reset to 0 again (or another error code if one occured)
+                    // after instantiation as any further calls to collation will cause
+                    // it to reset to 0 again (or another error code if one occurred)
                     $errorcode = $collator->getErrorCode();
                     $errormessage = $collator->getErrorMessage();
-                    // Check for an error code, 0 means no error occured
+                    // Check for an error code, 0 means no error occurred
                     if ($errorcode !== 0) {
                         // Get the actual locale being used, e.g. en, he, zh
                         $localeinuse = $collator->getLocale(Locale::ACTUAL_LOCALE);
-                        // Check for the common fallback wardning error code. If this occured
-                        // there is normally little to worry about. (U_USING_FALLBACK_WARNING)
-                        if ($errorcode === -128) {
-                            // Check if the local in use is anything like the locale we asked for
-                            if (strpos($locale, $localeinuse) !== 0) {
+                        // Check for the common fallback warning error codes. If this occurred
+                        // there is normally little to worry about:
+                        // - U_USING_DEFAULT_WARNING (127)  - default fallback locale used (pt => UCA)
+                        // - U_USING_FALLBACK_WARNING (128) - fallback locale used (de_CH => de)
+                        // (UCA: Unicode Collation Algorithm http://unicode.org/reports/tr10/)
+                        if ($errorcode === -127 || $errorcode === -128) {
+                            // Check if the locale in use is UCA default one ('root') or
+                            // if it is anything like the locale we asked for
+                            if ($localeinuse !== 'root' && strpos($locale, $localeinuse) !== 0) {
                                 // The locale we asked for is completely different to the locale
-                                // we have recieved, let the user know via debugging
-                                debugging('Invalid locale, falling back to the system default locale "'.$collator->getLocale(Locale::VALID_LOCALE).'"');
+                                // we have received, let the user know via debugging
+                                debugging('Invalid locale: "' . $locale . '", with warning (not fatal) "' . $errormessage .
+                                    '", falling back to "' . $collator->getLocale(Locale::VALID_LOCALE) . '"');
                             } else {
                                 // Nothing to do here, this is expected!
                                 // The Moodle locale setting isn't what the collator expected but
                                 // it is smart enough to match the first characters of our locale
-                                // to find the correct locale
-                                // debugging('Invalid locale, falling back to closest match "'.$localeinuse.'" which may not be the exact locale');
+                                // to find the correct locale or to use UCA collation
                             }
                         } else {
                             // We've recieved some other sort of non fatal warning - let the
                             // user know about it via debugging.
-                            debugging('Locale collator generated warnings (not fatal) "'.$errormessage.'" falling back to '.$collator->getLocale(Locale::VALID_LOCALE));
+                            debugging('Problem with locale: "' . $locale . '", with message "' . $errormessage .
+                                '", falling back to "' . $collator->getLocale(Locale::VALID_LOCALE) . '"');
                         }
                     }
-                    // Store the collator object now that we can be sure it is in a workable condition.
+                    // Store the collator object now that we can be sure it is in a workable condition
                     self::$collator = $collator;
                 } else {
-                    // Fatal error while trying to instantiate the collator... who know what went wrong.
-                    debugging('Error instantiating collator: ['.collator_get_error_code($collator).']'.collator_get_error_message($collator));
+                    // Fatal error while trying to instantiate the collator... something went wrong
+                    debugging('Error instantiating collator for locale: "' . $locale . '", with error [' .
+                        intl_get_error_code() . '] ' . intl_get_error_message($collator));
                 }
             }
         }
index cec3f4a..80aa427 100644 (file)
@@ -42,6 +42,7 @@ $action = optional_param('action', '', PARAM_ACTION);
 $id = optional_param('id', 0, PARAM_INT);
 $commentid = optional_param('commentid', 0, PARAM_INT);
 $newcontent = optional_param('newcontent', '', PARAM_CLEANHTML);
+$confirm = optional_param('confirm', 0, PARAM_BOOL);
 
 if (!$page = wiki_get_page($pageid)) {
     print_error('incorrectpageid', 'wiki');
@@ -59,8 +60,26 @@ if (!$wiki = wiki_get_wiki($subwiki->wikiid)) {
 }
 require_login($course->id, true, $cm);
 
-$comm = new page_wiki_handlecomments($wiki, $subwiki, $cm);
-$comm->set_page($page);
+if ($action == 'add' || $action == 'edit') {
+    //just check sesskey
+    if (!confirm_sesskey()) {
+        print_error(get_string('invalidsesskey', 'wiki'));
+    }
+    $comm = new page_wiki_handlecomments($wiki, $subwiki, $cm);
+    $comm->set_page($page);
+} else {
+    if(!$confirm) {
+        $comm = new page_wiki_deletecomment($wiki, $subwiki, $cm);
+        $comm->set_page($page);
+        $comm->set_url();
+    } else {
+        $comm = new page_wiki_handlecomments($wiki, $subwiki, $cm);
+        $comm->set_page($page);
+        if (!confirm_sesskey()) {
+            print_error(get_string('invalidsesskey', 'wiki'));
+        }
+    }
+}
 
 if ($action == 'delete') {
     $comm->set_action($action, $commentid, 0);
index e2ce468..bbe4e64 100644 (file)
@@ -42,6 +42,8 @@ $string['defaultformat_help'] = 'This setting determines the default format used
 * Creole - A common wiki markup language for which a small edit toolbar is available
 * Nwiki - Mediawiki-like markup language used in the contributed Nwiki module';
 $string['deletecomment'] = 'Deleting comment';
+$string['deletecommentcheck'] = 'Delete comment';
+$string['deletecommentcheckfull'] = 'Are you sure you want to delete the comment?';
 $string['deleteupload'] = 'Delete';
 $string['deletedbegins'] = 'Deleted begins';
 $string['deletedends'] = 'Deleted ends';
index 0c7c8b9..751a001 100644 (file)
@@ -761,6 +761,10 @@ class page_wiki_editcomment extends page_wiki {
         $pageid = $this->page->id;
 
         if ($this->format == 'html') {
+            $com = new stdClass();
+            $com->action = 'add';
+            $com->commentoptions = array('trusttext' => true, 'maxfiles' => 0);
+            $this->form->set_data($com);
             $this->form->display();
         } else {
             wiki_print_editor_wiki($this->page->id, null, $this->format, -1, null, false, null, 'addcomments');
@@ -773,18 +777,14 @@ class page_wiki_editcomment extends page_wiki {
         require_once($CFG->dirroot . '/mod/wiki/editors/wiki_editor.php');
 
         if ($this->format == 'html') {
-            $commentoptions = array('trusttext' => true, 'maxfiles' => 0);
             $com->action = 'edit';
             $com->entrycomment_editor['text'] = $com->content;
+            $com->commentoptions = array('trusttext' => true, 'maxfiles' => 0);
 
-            $this->form->set_data($com, $commentoptions);
+            $this->form->set_data($com);
             $this->form->display();
         } else {
-            $action = 'edit';
-            $commentid = $com->id;
-            $pageid = $this->page->id;
-            $destination = $CFG->wwwroot . '/mod/wiki/instancecomments.php?pageid=' . $pageid . '&id=' . $commentid . '&action=' . $action;
-            wiki_print_editor_wiki($this->page->id, $com->content, $this->format, -1, null, false, array(), 'editcomments', $commentid);
+            wiki_print_editor_wiki($this->page->id, $com->content, $this->format, -1, null, false, array(), 'editcomments', $com->id);
         }
 
     }
@@ -1859,24 +1859,95 @@ class page_wiki_restoreversion extends page_wiki {
      *     If true, restores the old version and redirects the user to the 'view' tab.
      */
     private function print_restoreversion() {
-        global $CFG, $OUTPUT;
+        global $OUTPUT;
 
         $version = wiki_get_version($this->version->id);
 
+        $optionsyes = array('confirm'=>1, 'pageid'=>$this->page->id, 'versionid'=>$version->id, 'sesskey'=>sesskey());
+        $restoreurl = new moodle_url('/mod/wiki/restoreversion.php', $optionsyes);
+        $return = new moodle_url('/mod/wiki/viewversion.php', array('pageid'=>$this->page->id, 'versionid'=>$version->id));
+
         echo $OUTPUT->heading(get_string('restoreconfirm', 'wiki', $version->version), 2);
         print_container_start(false, 'wiki_restoreform');
-        echo '<form class="wiki_restore_yes" action="' . $CFG->wwwroot . '/mod/wiki/restoreversion.php?pageid=' . $this->page->id . '&amp;versionid=' . $version->id . '" method="post" id="restoreversion">';
+        echo '<form class="wiki_restore_yes" action="' . $restoreurl . '" method="post" id="restoreversion">';
         echo '<div><input type="submit" name="confirm" value="' . get_string('yes') . '" /></div>';
         echo '</form>';
-        echo '<form class="wiki_restore_no" action="' . $CFG->wwwroot . '/mod/wiki/viewversion.php?pageid=' . $this->page->id . '&amp;versionid=' . $version->id . '" method="post">';
+        echo '<form class="wiki_restore_no" action="' . $return . '" method="post">';
         echo '<div><input type="submit" name="norestore" value="' . get_string('no') . '" /></div>';
         echo '</form>';
         print_container_end();
     }
 }
-
 /**
+ * Class that models the behavior of wiki's delete comment confirmation page
  *
+ */
+class page_wiki_deletecomment extends page_wiki {
+    private $commentid;
+
+    function print_header() {
+        parent::print_header();
+        $this->print_pagetitle();
+    }
+
+    function print_content() {
+        $this->printconfirmdelete();
+    }
+
+    function set_url() {
+        global $PAGE;
+        $PAGE->set_url('/mod/wiki/instancecomments.php', array('pageid' => $this->page->id, 'commentid' => $this->commentid));
+    }
+
+    public function set_action($action, $commentid, $content) {
+        $this->action = $action;
+        $this->commentid = $commentid;
+        $this->content = $content;
+    }
+
+    protected function create_navbar() {
+        global $PAGE;
+
+        parent::create_navbar();
+        $PAGE->navbar->add(get_string('deletecommentcheck', 'wiki'));
+    }
+
+    protected function setup_tabs() {
+        parent::setup_tabs(array('linkedwhenactive' => 'comments', 'activetab' => 'comments'));
+    }
+
+    /**
+     * Prints the comment deletion confirmation form
+     *
+     * @param page $page The page whose version will be restored
+     * @param int  $versionid The version to be restored
+     * @param bool $confirm If false, shows a yes/no confirmation page.
+     *     If true, restores the old version and redirects the user to the 'view' tab.
+     */
+    private function printconfirmdelete() {
+        global $OUTPUT;
+
+        $strdeletecheck = get_string('deletecommentcheck', 'wiki');
+        $strdeletecheckfull = get_string('deletecommentcheckfull', 'wiki');
+
+        //ask confirmation
+        $optionsyes = array('confirm'=>1, 'pageid'=>$this->page->id, 'action'=>'delete', 'commentid'=>$this->commentid, 'sesskey'=>sesskey());
+        $deleteurl = new moodle_url('/mod/wiki/instancecomments.php', $optionsyes);
+        $return = new moodle_url('/mod/wiki/comments.php', array('pageid'=>$this->page->id));
+
+        echo $OUTPUT->heading($strdeletecheckfull);
+        print_container_start(false, 'wiki_deletecommentform');
+        echo '<form class="wiki_deletecomment_yes" action="' . $deleteurl . '" method="post" id="deletecomment">';
+        echo '<div><input type="submit" name="confirmdeletecomment" value="' . get_string('yes') . '" /></div>';
+        echo '</form>';
+        echo '<form class="wiki_deletecomment_no" action="' . $return . '" method="post">';
+        echo '<div><input type="submit" name="norestore" value="' . get_string('no') . '" /></div>';
+        echo '</form>';
+        print_container_end();
+    }
+}
+
+/**
  * Class that models the behavior of wiki's
  * save page
  *
index 4abd2e5..a959b32 100644 (file)
@@ -38,7 +38,7 @@ require_once($CFG->dirroot . '/mod/wiki/pagelib.php');
 
 $pageid = required_param('pageid', PARAM_INT);
 $versionid = required_param('versionid', PARAM_INT);
-$confirm = optional_param('confirm', '', PARAM_ALPHA);
+$confirm = optional_param('confirm', 0, PARAM_BOOL);
 
 if (!$page = wiki_get_page($pageid)) {
     print_error('incorrectpageid', 'wiki');
@@ -63,7 +63,9 @@ require_login($course->id, true, $cm);
 add_to_log($course->id, "restore", "restore", "view.php?id=$cm->id", "$wiki->id");
 
 if ($confirm) {
-
+    if (!confirm_sesskey()) {
+        print_error(get_string('invalidsesskey', 'wiki'));
+    }
     $wikipage = new page_wiki_confirmrestore($wiki, $subwiki, $cm);
     $wikipage->set_page($page);
     $wikipage->set_versionid($versionid);
index b76bb8f..18e0391 100644 (file)
     border: thin black solid;
 }
 
-.wiki_restore_yes {
+.wiki_restore_yes, .wiki_deletecomment_yes {
     float: left;
 }
 
-.wiki_restore_no {
+.wiki_restore_no, .wiki_deletecomment_no {
     float: right;
 }
 
-.wiki_restoreform {
+.wiki_restoreform, .wiki_deletecommentform {
     width: 10%;
     margin: auto;
 }
index f6d328d..6812cf9 100644 (file)
@@ -91,9 +91,8 @@ class qtype_multianswer_edit_form extends question_edit_form {
         $mform->addRule('questiontext', null, 'required', null, 'client');
 
         // display the questions from questiontext;
-        if ("" != optional_param('questiontext', '', PARAM_RAW)) {
-            $this->questiondisplay = fullclone(qtype_multianswer_extract_question(
-                    optional_param('questiontext', '', PARAM_RAW)));
+        if ($questiontext = optional_param_array('questiontext', false, PARAM_RAW)) {
+            $this->questiondisplay = fullclone(qtype_multianswer_extract_question($questiontext));
 
         } else {
             if (!$this->reload && !empty($this->savedquestiondisplay->id)) {
index 965d9d8..b6f09a7 100644 (file)
@@ -1317,7 +1317,7 @@ abstract class repository {
             $dir = $CFG->dataroot.'/temp/download/';
         }
         if (empty($filename)) {
-            $filename = uniqid('repo').'_'.time().'.tmp';
+            $filename = uniqid('repo', true).'_'.time().'.tmp';
         }
         if (file_exists($dir.$filename)) {
             $filename = uniqid('m').$filename;
index 8c771c0..a8c5d8f 100644 (file)
@@ -43,6 +43,7 @@
     -webkit-border-radius:6px 6px 0px 0px; /* Safari, Chrome */
     border-radius:6px 6px 0px 0px;         /* CSS3 */
 }
+
 #page-content {
     /* arrotonadamento angolo in basso a sx */
     /* -moz-border-radius:0px 0px 0px 6px;    /* Firefox */
     background-color:[[setting:lblockcolumnbgc]]; /* colore della colonna di sinistra */
     float:none;
 }
+
 #page-content #region-main-box {
     left:[[setting:blockcolumnwidth]];
     background-color:#FFF;
 }
+
 #page-content #region-post-box {
     margin-left:[[setting:minusdoubleblockcolumnwidth]]; /*-2*[[setting:blockcolumnwidth]]*/
     /* arrotonadamento angolo in basso a dx */
     /* border-radius:0px 0px 6px 0px;         /* CSS3 */
     background-color:[[setting:rblockcolumnbgc]]; /* colore della colonna di destra */
 }
+
 #page-content #region-main {
     margin-left:[[setting:doubleblockcolumnwidth]];/*2*[[setting:blockcolumnwidth]]*/
     background-color:white; /* questo serve a togliere la curvatura dagli angoli della zona centrale */
 }
+
 #page-content #region-pre {
     left:[[setting:blockcolumnwidth]]; /*400-[[setting:blockcolumnwidth]]*/
     width:[[setting:blockcolumnwidth]];
     background-color:[[setting:lblockcolumnbgc]]; /* colore della colonna di sx */
 }
+
 #page-content #region-post {
     width:[[setting:blockcolumnwidth]];
     /* arrotonadamento angolo in basso a dx */
     /* border-radius:0px 0px 6px 0px;         /* CSS3 */
     background-color:[[setting:rblockcolumnbgc]]; /* colore del fondo della parte occupata dai contenuti della colonna centrale e della colonna dx */
 }
+
 #page-content .region-content {
     padding:0.6em 8px 0.1em 8px; /* definisco lo spazio sopra e sotto ai blocchi */
 }
 
+.pagelayout-report #page-content .region-content {
+    overflow: auto;
+}
+
 /** Only side pre **/
     .side-pre-only #page-content #region-post-box {margin-left:-[[setting:blockcolumnwidth]];}
     .side-pre-only #page-content #region-main {margin-left:[[setting:blockcolumnwidth]];}
index 55f7a21..264e815 100644 (file)
@@ -31,7 +31,7 @@ defined('MOODLE_INTERNAL') || die();
 
 
 
-$version  = 2011090700.00;              // YYYYMMDD      = weekly release date of this DEV branch
+$version  = 2011090700.01;              // YYYYMMDD      = weekly release date of this DEV branch
                                         //         RR    = release increments - 00 in DEV branches
                                         //           .XX = incremental changes