Merge branch 'MDL-31835_recent_conversations' of git://github.com/andyjdavis/moodle
authorSam Hemelryk <sam@moodle.com>
Mon, 19 Mar 2012 01:10:37 +0000 (14:10 +1300)
committerSam Hemelryk <sam@moodle.com>
Mon, 19 Mar 2012 01:10:37 +0000 (14:10 +1300)
76 files changed:
admin/settings/security.php
backup/moodle2/backup_stepslib.php
backup/moodle2/restore_stepslib.php
calendar/renderer.php
course/edit.php
course/edit_form.php
course/lib.php
course/modedit.php
lang/en/admin.php
lang/en/moodle.php
lib/db/install.xml
lib/db/upgrade.php
mod/assignment/db/access.php
mod/assignment/lang/en/assignment.php
mod/assignment/version.php
mod/chat/db/access.php
mod/chat/lang/en/chat.php
mod/chat/version.php
mod/choice/db/access.php
mod/choice/lang/en/choice.php
mod/choice/version.php
mod/data/db/access.php
mod/data/lang/en/data.php
mod/data/version.php
mod/feedback/db/access.php
mod/feedback/lang/en/feedback.php
mod/feedback/version.php
mod/folder/db/access.php
mod/folder/lang/en/folder.php
mod/folder/version.php
mod/forum/db/access.php
mod/forum/lang/en/forum.php
mod/forum/version.php
mod/glossary/db/access.php
mod/glossary/lang/en/glossary.php
mod/glossary/version.php
mod/imscp/db/access.php
mod/imscp/lang/en/imscp.php
mod/imscp/version.php
mod/label/db/access.php [new file with mode: 0644]
mod/label/lang/en/label.php
mod/label/version.php
mod/lesson/db/access.php
mod/lesson/lang/en/lesson.php
mod/lesson/version.php
mod/lti/db/access.php
mod/lti/lang/en/lti.php
mod/lti/version.php
mod/page/db/access.php
mod/page/lang/en/page.php
mod/page/version.php
mod/quiz/db/access.php
mod/quiz/lang/en/quiz.php
mod/quiz/version.php
mod/resource/db/access.php
mod/resource/lang/en/resource.php
mod/resource/version.php
mod/scorm/db/access.php
mod/scorm/lang/en/scorm.php
mod/scorm/version.php
mod/survey/db/access.php
mod/survey/lang/en/survey.php
mod/survey/version.php
mod/upgrade.txt
mod/url/db/access.php
mod/url/lang/en/url.php
mod/url/version.php
mod/wiki/db/access.php
mod/wiki/lang/en/wiki.php
mod/wiki/version.php
mod/workshop/db/access.php
mod/workshop/lang/en/workshop.php
mod/workshop/version.php
question/engine/questionattempt.php
question/engine/simpletest/testquestionattempt.php
version.php

index 6e499ac..189bf87 100644 (file)
@@ -86,19 +86,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
     $ADMIN->add('security', $temp);
 
 
-    // "modulesecurity" settingpage
-    $temp = new admin_settingpage('modulesecurity', new lang_string('modulesecurity', 'admin'));
-    $temp->add(new admin_setting_configselect('restrictmodulesfor', new lang_string('restrictmodulesfor', 'admin'), new lang_string('configrestrictmodulesfor', 'admin'), 'none', array('none' => new lang_string('nocourses'),
-                                                                                                                                                                              'all' => new lang_string('fulllistofcourses'),
-                                                                                                                                                                              'requested' => new lang_string('requestedcourses'))));
-    $temp->add(new admin_setting_configcheckbox('restrictbydefault', new lang_string('restrictbydefault', 'admin'), new lang_string('configrestrictbydefault', 'admin'), 0));
-    $temp->add(new admin_setting_configmultiselect_modules('defaultallowedmodules',
-            new lang_string('defaultallowedmodules', 'admin'),
-            new lang_string('configdefaultallowedmodules', 'admin')));
-    $ADMIN->add('security', $temp);
-
-
-
     // "notifications" settingpage
     $temp = new admin_settingpage('notifications', new lang_string('notifications', 'admin'));
     $temp->add(new admin_setting_configselect('displayloginfailures', new lang_string('displayloginfailures', 'admin'), new lang_string('configdisplayloginfailures', 'admin'), '', array('' => new lang_string('nobody'),
index 78d2721..e22ff35 100644 (file)
@@ -403,7 +403,7 @@ class backup_course_structure_step extends backup_structure_step {
             'visible', 'hiddensections', 'groupmode', 'groupmodeforce',
             'defaultgroupingid', 'lang', 'theme',
             'timecreated', 'timemodified',
-            'requested', 'restrictmodules',
+            'requested',
             'enablecompletion', 'completionstartonenrol', 'completionnotify'));
 
         $category = new backup_nested_element('category', array('id'), array(
@@ -414,10 +414,6 @@ class backup_course_structure_step extends backup_structure_step {
         $tag = new backup_nested_element('tag', array('id'), array(
             'name', 'rawname'));
 
-        $allowedmodules = new backup_nested_element('allowed_modules');
-
-        $module = new backup_nested_element('module', array(), array('modulename'));
-
         // attach format plugin structure to $course element, only one allowed
         $this->add_plugin_structure('format', $course, false);
 
@@ -444,9 +440,6 @@ class backup_course_structure_step extends backup_structure_step {
         $course->add_child($tags);
         $tags->add_child($tag);
 
-        $course->add_child($allowedmodules);
-        $allowedmodules->add_child($module);
-
         // Set the sources
 
         $courserec = $DB->get_record('course', array('id' => $this->task->get_courseid()));
@@ -466,11 +459,6 @@ class backup_course_structure_step extends backup_structure_step {
                                      backup_helper::is_sqlparam('course'),
                                      backup::VAR_PARENTID));
 
-        $module->set_source_sql('SELECT m.name AS modulename
-                                   FROM {modules} m
-                                   JOIN {course_allowed_modules} cam ON m.id = cam.module
-                                  WHERE course = ?', array(backup::VAR_COURSEID));
-
         // Some annotations
 
         $course->annotate_ids('grouping', 'defaultgroupingid');
index 58048ec..6dd757e 100644 (file)
@@ -1069,6 +1069,21 @@ class restore_section_structure_step extends restore_structure_step {
  * the course record (never inserting)
  */
 class restore_course_structure_step extends restore_structure_step {
+    /**
+     * @var bool this gets set to true by {@link process_course()} if we are
+     * restoring an old coures that used the legacy 'module security' feature.
+     * If so, we have to do more work in {@link after_execute()}.
+     */
+    protected $legacyrestrictmodules = false;
+
+    /**
+     * @var array Used when {@link $legacyrestrictmodules} is true. This is an
+     * array with array keys the module names ('forum', 'quiz', etc.). These are
+     * the modules that are allowed according to the data in the backup file.
+     * In {@link after_execute()} we then have to prevent adding of all the other
+     * types of activity.
+     */
+    protected $legacyallowedmodules = array();
 
     protected function define_structure() {
 
@@ -1131,8 +1146,9 @@ class restore_course_structure_step extends restore_structure_step {
             $data->hiddensections = 0;
         }
 
-        // Only restrict modules if original course was and target site too for new courses
-        $data->restrictmodules = $data->restrictmodules && !empty($CFG->restrictmodulesfor) && $CFG->restrictmodulesfor == 'all';
+        // Set legacyrestrictmodules to true if the course was resticting modules. If so
+        // then we will need to process restricted modules after execution.
+        $this->legacyrestrictmodules = !empty($data->restrictmodules);
 
         $data->startdate= $this->apply_date_offset($data->startdate);
         if ($data->defaultgroupingid) {
@@ -1187,31 +1203,44 @@ class restore_course_structure_step extends restore_structure_step {
     }
 
     public function process_allowed_module($data) {
-        global $CFG, $DB;
-
         $data = (object)$data;
 
-        // only if enabled by admin setting
-        if (!empty($CFG->restrictmodulesfor) && $CFG->restrictmodulesfor == 'all') {
-            $available = get_plugin_list('mod');
-            $mname = $data->modulename;
-            if (array_key_exists($mname, $available)) {
-                if ($module = $DB->get_record('modules', array('name' => $mname, 'visible' => 1))) {
-                    $rec = new stdclass();
-                    $rec->course = $this->get_courseid();
-                    $rec->module = $module->id;
-                    if (!$DB->record_exists('course_allowed_modules', (array)$rec)) {
-                        $DB->insert_record('course_allowed_modules', $rec);
-                    }
-                }
-            }
+        // Backwards compatiblity support for the data that used to be in the
+        // course_allowed_modules table.
+        if ($this->legacyrestrictmodules) {
+            $this->legacyallowedmodules[$data->modulename] = 1;
         }
     }
 
     protected function after_execute() {
+        global $DB;
+
         // Add course related files, without itemid to match
         $this->add_related_files('course', 'summary', null);
         $this->add_related_files('course', 'legacy', null);
+
+        // Deal with legacy allowed modules.
+        if ($this->legacyrestrictmodules) {
+            $context = context_course::instance($this->get_courseid());
+
+            list($roleids) = get_roles_with_cap_in_context($context, 'moodle/course:manageactivities');
+            list($managerroleids) = get_roles_with_cap_in_context($context, 'moodle/site:config');
+            foreach ($managerroleids as $roleid) {
+                unset($roleids[$roleid]);
+            }
+
+            foreach (get_plugin_list('mod') as $modname => $notused) {
+                if (isset($this->legacyallowedmodules[$modname])) {
+                    // Module is allowed, no worries.
+                    continue;
+                }
+
+                $capability = 'mod/' . $modname . ':addinstance';
+                foreach ($roleids as $roleid) {
+                    assign_capability($capability, CAP_PREVENT, $roleid, $context);
+                }
+            }
+        }
     }
 }
 
index 312c572..ade2f63 100644 (file)
@@ -413,6 +413,8 @@ class core_calendar_renderer extends plugin_renderer_base {
 
         $table = new html_table();
         $table->attributes = array('class'=>'calendarmonth calendartable');
+        $time = make_timestamp($calendar->year, $calendar->month);
+        $table->summary = get_string('calendarheading', 'calendar', userdate($time, get_string('strftimemonthyear')));
         $table->data = array();
 
         $header = new html_table_row();
index 053d8bb..174872c 100644 (file)
@@ -65,18 +65,6 @@ if ($id) { // editing course
 // Prepare course and the editor
 $editoroptions = array('maxfiles' => EDITOR_UNLIMITED_FILES, 'maxbytes'=>$CFG->maxbytes, 'trusttext'=>false, 'noclean'=>true);
 if (!empty($course)) {
-    $allowedmods = array();
-    if ($am = $DB->get_records('course_allowed_modules', array('course'=>$course->id))) {
-        foreach ($am as $m) {
-            $allowedmods[] = $m->module;
-        }
-    } else {
-        // this happens in case we edit course created before enabling module restrictions or somebody disabled everything :-(
-        if (empty($course->restrictmodules) and !empty($CFG->defaultallowedmodules)) {
-            $allowedmods = explode(',', $CFG->defaultallowedmodules);
-        }
-    }
-    $course->allowedmods = $allowedmods;
     //add context for editor
     $editoroptions['context'] = $coursecontext;
     $course = file_prepare_standard_editor($course, 'summary', $editoroptions, $coursecontext, 'course', 'summary', 0);
index d87c9d1..44ed742 100644 (file)
@@ -256,48 +256,6 @@ class course_edit_form extends moodleform {
             $mform->setDefault('completionstartonenrol',0);
         }
 
-//--------------------------------------------------------------------------------
-        if (has_capability('moodle/site:config', $systemcontext)) {
-            if (((!empty($course->requested) && $CFG->restrictmodulesfor == 'requested') || $CFG->restrictmodulesfor == 'all')) {
-                $mform->addElement('header', '', get_string('restrictmodules'));
-
-                $options = array();
-                $options['0'] = get_string('no');
-                $options['1'] = get_string('yes');
-                $mform->addElement('select', 'restrictmodules', get_string('restrictmodules'), $options);
-                if (!empty($CFG->restrictbydefault)) {
-                    $mform->setDefault('restrictmodules', 1);
-                }
-
-                $mods = array(0=>get_string('allownone'));
-                $allmods = $DB->get_records_menu('modules', array('visible' => 1),
-                        'name', 'id, name');
-                foreach ($allmods as $key => $value) {
-                    // Add module to list unless it cannot be added by users anyway
-                    if (plugin_supports('mod', $value, FEATURE_MOD_ARCHETYPE, MOD_ARCHETYPE_OTHER) !==
-                            MOD_ARCHETYPE_SYSTEM) {
-                        $mods[$key] = get_string('pluginname', $value);
-                    }
-                }
-                $mform->addElement('select', 'allowedmods', get_string('to'), $mods, array('multiple'=>'multiple', 'size'=>'10'));
-                $mform->disabledIf('allowedmods', 'restrictmodules', 'eq', 0);
-                // defaults are already in $course
-            } else {
-                // remove any mod restriction
-                $mform->addElement('hidden', 'restrictmodules', 0);
-                $mform->setType('restrictmodules', PARAM_INT);
-            }
-        } else {
-            $mform->addElement('hidden', 'restrictmodules');
-            $mform->setType('restrictmodules', PARAM_INT);
-            if (empty($course->id)) {
-                $mform->setConstant('restrictmodules', (int)($CFG->restrictmodulesfor == 'all'));
-            } else {
-                // keep previous
-                $mform->setConstant('restrictmodules', $course->restrictmodules);
-            }
-        }
-
 /// customizable role names in this course
 //--------------------------------------------------------------------------------
         $mform->addElement('header','rolerenaming', get_string('rolerenaming'));
index 6282112..fd8a1e1 100644 (file)
@@ -3391,58 +3391,37 @@ function course_format_name ($course,$max=100) {
     }
 }
 
-function update_restricted_mods($course, $mods) {
-    global $DB;
-
-/// Delete all the current restricted list
-    $DB->delete_records('course_allowed_modules', array('course'=>$course->id));
-
-    if (empty($course->restrictmodules)) {
-        return;   // We're done
-    }
-
-/// Insert the new list of restricted mods
-    foreach ($mods as $mod) {
-        if ($mod == 0) {
-            continue; // this is the 'allow none' option
-        }
-        $am = new stdClass();
-        $am->course = $course->id;
-        $am->module = $mod;
-        $DB->insert_record('course_allowed_modules',$am);
-    }
-}
-
 /**
- * This function will take an int (module id) or a string (module name)
- * and return true or false, whether it's allowed in the given course (object)
- * $mod is not allowed to be an object, as the field for the module id is inconsistent
- * depending on where in the code it's called from (sometimes $mod->id, sometimes $mod->module)
+ * Is the user allowed to add this type of module to this course?
+ * @param object $course the course settings. Only $course->id is used.
+ * @param string $modname the module name. E.g. 'forum' or 'quiz'.
+ * @return bool whether the current user is allowed to add this type of module to this course.
  */
-
-function course_allowed_module($course,$mod) {
+function course_allowed_module($course, $modname) {
     global $DB;
 
-    if (empty($course->restrictmodules)) {
-        return true;
+    if (is_numeric($modname)) {
+        throw new coding_exception('Function course_allowed_module no longer
+                supports numeric module ids. Please update your code to pass the module name.');
     }
 
-    // Admins and admin-like people who can edit everything can also add anything.
-    // Originally there was a course:update test only, but it did not match the test in course edit form
-    if (has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM))) {
-        return true;
-    }
+    $capability = 'mod/' . $modname . ':addinstance';
+    if (!get_capability_info($capability)) {
+        // Debug warning that the capability does not exist, but no more than once per page.
+        static $warned = array();
+        $archetype = plugin_supports('mod', $modname, FEATURE_MOD_ARCHETYPE, MOD_ARCHETYPE_OTHER);
+        if (!isset($warned[$modname]) && $archetype !== MOD_ARCHETYPE_SYSTEM) {
+            debugging('The module ' . $modname . ' does not define the standard capability ' .
+                    $capability , DEBUG_DEVELOPER);
+            $warned[$modname] = 1;
+        }
 
-    if (is_numeric($mod)) {
-        $modid = $mod;
-    } else if (is_string($mod)) {
-        $modid = $DB->get_field('modules', 'id', array('name'=>$mod));
-    }
-    if (empty($modid)) {
-        return false;
+        // If the capability does not exist, the module can always be added.
+        return true;
     }
 
-    return $DB->record_exists('course_allowed_modules', array('course'=>$course->id, 'module'=>$modid));
+    $coursecontext = context_course::instance($course->id);
+    return has_capability($capability, $coursecontext);
 }
 
 /**
@@ -3910,17 +3889,6 @@ function create_course($data, $editoroptions = NULL) {
 
     fix_course_sortorder();
 
-    // update module restrictions
-    if ($course->restrictmodules) {
-        if (isset($data->allowedmods)) {
-            update_restricted_mods($course, $data->allowedmods);
-        } else {
-            if (!empty($CFG->defaultallowedmodules)) {
-                update_restricted_mods($course, explode(',', $CFG->defaultallowedmodules));
-            }
-        }
-    }
-
     // new context created - better mark it as dirty
     mark_context_dirty($context->path);
 
@@ -3999,11 +3967,6 @@ function update_course($data, $editoroptions = NULL) {
     // Test for and remove blocks which aren't appropriate anymore
     blocks_remove_inappropriate($course);
 
-    // update module restrictions
-    if (isset($data->allowedmods)) {
-        update_restricted_mods($course, $data->allowedmods);
-    }
-
     // Save any custom role names.
     save_local_role_names($course->id, $data);
 
@@ -4316,9 +4279,6 @@ class course_request {
 
         // Set misc settings
         $data->requested = 1;
-        if (!empty($CFG->restrictmodulesfor) && $CFG->restrictmodulesfor != 'none' && !empty($CFG->restrictbydefault)) {
-            $data->restrictmodules = 1;
-        }
 
         // Apply course default settings
         $data->format             = $courseconfig->format;
index 9ed3f5d..63ea832 100644 (file)
@@ -59,7 +59,7 @@ if (!empty($add)) {
 
     $cw = get_course_section($section, $course->id);
 
-    if (!course_allowed_module($course, $module->id)) {
+    if (!course_allowed_module($course, $module->name)) {
         print_error('moduledisable');
     }
 
index 6b6c8df..921dc7d 100644 (file)
@@ -171,7 +171,6 @@ $string['configdebugdisplay'] = 'Set to on, the error reporting will go to the H
 $string['configdebugpageinfo'] = 'Enable if you want page information printed in page footer.';
 $string['configdebugsmtp'] = 'Enable verbose debug information during sending of email messages to SMTP server.';
 $string['configdebugvalidators'] = 'Enable if you want to have links to external validator servers in page footer. You may need to create new user with username <em>w3cvalidator</em>, and enable guest access. These changes may allow unauthorized access to server, do not enable on production sites!';
-$string['configdefaultallowedmodules'] = 'For the courses which fall into the above category, which modules do you want to allow by default <b>when the course is created</b>?';
 $string['configdefaulthomepage'] = 'This determines the home page for logged in users';
 $string['configdefaultrequestcategory'] = 'Courses requested by users will be automatically placed in this category.';
 $string['configdefaultrequestedcategory'] = 'Default category to put courses that were requested into, if they\'re approved.';
@@ -285,8 +284,6 @@ $string['configrequestedstudentsname'] = 'Word for students used in requested co
 $string['configrequestedteachername'] = 'Word for teacher used in requested courses';
 $string['configrequestedteachersname'] = 'Word for teachers used in requested courses';
 $string['configrequiremodintro'] = 'Disable this option if you do not want to force users to enter description of each activity.';
-$string['configrestrictbydefault'] = 'Should new courses that are created that fall into the above category have their modules restricted by default?';
-$string['configrestrictmodulesfor'] = 'Which courses should have <b>the setting</b> for disabling some activity modules?  Note that this setting only applies to teachers, administrators will still be able to add any activity to a course.';
 $string['configrunclamavonupload'] = 'When enabled, clam AV will be used to scan all uploaded files.';
 $string['configrunclamonupload'] = 'Run clam AV on file upload? You will need a correct path in pathtoclam for this to work.  (Clam AV is a free virus scanner that you can get from http://www.clamav.net/)';
 $string['configuserquota'] = 'The maximum number of bytes that a user can store in their own private file area. {$a->bytes} bytes == {$a->displaysize}';
@@ -407,7 +404,6 @@ $string['debugsmtp'] = 'Debug email sending';
 $string['debugstringids'] = 'Show origin of languages strings';
 $string['debugstringids_desc'] = 'This option is designed to help translators. When this option is enabled, if you add the parameter strings=1 to a request URL, it will show the language file and string id beside each string that is output.';
 $string['debugvalidators'] = 'Show validator links';
-$string['defaultallowedmodules'] = 'Default allowed modules';
 $string['defaultcity'] = 'Default city';
 $string['defaultcity_help'] = 'A city entered here will be the default city when creating new user accounts.';
 $string['defaulthomepage'] = 'Default home page for users';
@@ -861,8 +857,6 @@ $string['purgecachesconfirm']= 'Moodle can cache themes, javascript, language st
 $string['purgecachesfinished']= 'All caches were purged.';
 $string['restorernewroleid'] = 'Restorers\' role in courses';
 $string['restorernewroleid_help'] = 'If the user does not already have the permission to manage the newly restored course, the user is automatically assigned this role and enrolled if necessary. Select "None" if you do not want restorers to be able to manage every restored course.';
-$string['restrictbydefault'] = 'Restrict modules by default';
-$string['restrictmodulesfor'] = 'Restrict modules for';
 $string['reverseproxy'] = 'Reverse proxy';
 $string['riskconfig'] = 'Users could change site configuration and behaviour';
 $string['riskconfigshort'] = 'Configuration risk';
index fd18d93..764d5db 100644 (file)
@@ -1385,7 +1385,6 @@ $string['restoreuserinfofailed'] = 'The restore process has stopped because you
 $string['restoreusersprecheck'] = 'Checking user data';
 $string['restoreusersprecheckerror'] = 'Some problems were detected when checking user data';
 $string['restricted'] = 'Restricted';
-$string['restrictmodules'] = 'Restrict activity modules?';
 $string['returningtosite'] = 'Returning to this web site?';
 $string['returntooriginaluser'] = 'Return to {$a}';
 $string['revert'] = 'Revert';
index eeac75d..7f53bb4 100644 (file)
@@ -97,9 +97,8 @@
         <FIELD NAME="theme" TYPE="char" LENGTH="50" NOTNULL="true" SEQUENCE="false" PREVIOUS="lang" NEXT="timecreated"/>
         <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="theme" NEXT="timemodified"/>
         <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="timecreated" NEXT="requested"/>
-        <FIELD NAME="requested" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="timemodified" NEXT="restrictmodules"/>
-        <FIELD NAME="restrictmodules" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="requested" NEXT="enablecompletion"/>
-        <FIELD NAME="enablecompletion" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="1 = allow use of 'completion' progress-tracking on this course. 0 = disable completion tracking on this course." PREVIOUS="restrictmodules" NEXT="completionstartonenrol"/>
+        <FIELD NAME="requested" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="timemodified" NEXT="enablecompletion"/>
+        <FIELD NAME="enablecompletion" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="1 = allow use of 'completion' progress-tracking on this course. 0 = disable completion tracking on this course." PREVIOUS="requested" NEXT="completionstartonenrol"/>
         <FIELD NAME="completionstartonenrol" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="1 = allow use of 'activty completion' progress-tracking on this course. 0 = disable activity completion tracking on this course." PREVIOUS="enablecompletion" NEXT="completionnotify"/>
         <FIELD NAME="completionnotify" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Notify users when they complete this course" PREVIOUS="completionstartonenrol"/>
       </FIELDS>
         <INDEX NAME="course_section" UNIQUE="false" FIELDS="course, section"/>
       </INDEXES>
     </TABLE>
-    <TABLE NAME="course_request" COMMENT="course requests" PREVIOUS="course_sections" NEXT="course_allowed_modules">
+    <TABLE NAME="course_request" COMMENT="course requests" PREVIOUS="course_sections" NEXT="filter_active">
       <FIELDS>
         <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="fullname"/>
         <FIELD NAME="fullname" TYPE="char" LENGTH="254" NOTNULL="true" SEQUENCE="false" PREVIOUS="id" NEXT="shortname"/>
         <INDEX NAME="shortname" UNIQUE="false" FIELDS="shortname"/>
       </INDEXES>
     </TABLE>
-    <TABLE NAME="course_allowed_modules" COMMENT="allowed modules foreach course" PREVIOUS="course_request" NEXT="filter_active">
-      <FIELDS>
-        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="course"/>
-        <FIELD NAME="course" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="id" NEXT="module"/>
-        <FIELD NAME="module" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="course"/>
-      </FIELDS>
-      <KEYS>
-        <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
-      </KEYS>
-      <INDEXES>
-        <INDEX NAME="course" UNIQUE="false" FIELDS="course" NEXT="module"/>
-        <INDEX NAME="module" UNIQUE="false" FIELDS="module" PREVIOUS="course"/>
-      </INDEXES>
-    </TABLE>
-    <TABLE NAME="filter_active" COMMENT="Stores information about which filters are active in which contexts. Also the filter sort order. See get_active_filters in lib/filterlib.php for how this data is used." PREVIOUS="course_allowed_modules" NEXT="filter_config">
+    <TABLE NAME="filter_active" COMMENT="Stores information about which filters are active in which contexts. Also the filter sort order. See get_active_filters in lib/filterlib.php for how this data is used." PREVIOUS="course_request" NEXT="filter_config">
       <FIELDS>
         <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="filter"/>
         <FIELD NAME="filter" TYPE="char" LENGTH="32" NOTNULL="true" SEQUENCE="false" COMMENT="The filter internal name, like 'filter/tex' or 'mod/glossary'." PREVIOUS="id" NEXT="contextid"/>
index c42d27c..dedb1bf 100644 (file)
@@ -212,7 +212,110 @@ function xmldb_main_upgrade($oldversion) {
         upgrade_main_savepoint(true, 2012030900.01);
     }
 
+    if ($oldversion < 2012031500.01) {
+        // Upgrade old course_allowed_modules data to be permission overrides.
+        if ($CFG->restrictmodulesfor = 'all') {
+            $courses = $DB->get_records_menu('course', array(), 'id', 'id, 1');
+        } else if ($CFG->restrictmodulesfor = 'requested') {
+            $courses = $DB->get_records_menu('course', array('retrictmodules' => 1), 'id', 'id, 1');
+        } else {
+            $courses = array();
+        }
+
+        if (!$dbman->table_exists('course_allowed_modules')) {
+            // Upgrade must already have been run on this server. This might happen,
+            // for example, during development of these changes.
+            $courses = array();
+        }
+
+        $modidtoname = $DB->get_records_menu('modules', array(), 'id', 'id, name');
+
+        $coursecount = count($courses);
+        if ($coursecount) {
+            $pbar = new progress_bar('allowedmods', 500, true);
+            $transaction = $DB->start_delegated_transaction();
+        }
+
+        $i = 0;
+        foreach ($courses as $courseid => $notused) {
+            $i += 1;
+            upgrade_set_timeout(60); // 1 minute per course should be fine.
+
+            $allowedmoduleids = $DB->get_records_menu('course_allowed_modules',
+            array('course' => $courseid), 'module', 'module, 1');
+            if (empty($allowedmoduleids)) {
+                // This seems to be the best match for backwards compatibility,
+                // not necessarily with the old code in course_allowed_module function,
+                // but with the code that used to be in the coures settings form.
+                $allowedmoduleids = explode(',', $CFG->defaultallowedmodules);
+                $allowedmoduleids = array_combine($allowedmoduleids, $allowedmoduleids);
+            }
+
+            $context = context_course::instance($courseid);
+
+            list($roleids) = get_roles_with_cap_in_context($context, 'moodle/course:manageactivities');
+            list($managerroleids) = get_roles_with_cap_in_context($context, 'moodle/site:config');
+            foreach ($managerroleids as $roleid) {
+                unset($roleids[$roleid]);
+            }
+
+            foreach ($modidtoname as $modid => $modname) {
+                if (isset($allowedmoduleids[$modid])) {
+                    // Module is allowed, no worries.
+                    continue;
+                }
+
+                $capability = 'mod/' . $modname . ':addinstance';
+                foreach ($roleids as $roleid) {
+                    assign_capability($capability, CAP_PREVENT, $roleid, $context);
+                }
+            }
+
+            $pbar->update($i, $coursecount, "Upgrading legacy course_allowed_modules data - $i/$coursecount.");
+        }
+
+        if ($coursecount) {
+            $transaction->allow_commit();
+        }
+
+        upgrade_main_savepoint(true, 2012031500.01);
+    }
+
+    if ($oldversion < 2012031500.02) {
+
+        // Define field retrictmodules to be dropped from course
+        $table = new xmldb_table('course');
+        $field = new xmldb_field('restrictmodules');
+
+        // Conditionally launch drop field requested
+        if ($dbman->field_exists($table, $field)) {
+            $dbman->drop_field($table, $field);
+        }
+
+        upgrade_main_savepoint(true, 2012031500.02);
+    }
+
+    if ($oldversion < 2012031500.03) {
+
+        // Define table course_allowed_modules to be dropped
+        $table = new xmldb_table('course_allowed_modules');
+
+        // Conditionally launch drop table for course_allowed_modules
+        if ($dbman->table_exists($table)) {
+            $dbman->drop_table($table);
+        }
+
+        upgrade_main_savepoint(true, 2012031500.03);
+    }
+
+    if ($oldversion < 2012031500.04) {
+        // Clean up the old admin settings.
+        unset_config('restrictmodulesfor');
+        unset_config('restrictbydefault');
+        unset_config('defaultallowedmodules');
+
+        upgrade_main_savepoint(true, 2012031500.04);
+    }
 
     return true;
 }
-
index 3c39187..73d3145 100644 (file)
@@ -39,6 +39,18 @@ $capabilities = array(
         )
     ),
 
+    'mod/assignment:addinstance' => array(
+        'riskbitmask' => RISK_XSS,
+
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_COURSE,
+        'archetypes' => array(
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW
+        ),
+        'clonepermissionsfrom' => 'moodle/course:manageactivities'
+    ),
+
     'mod/assignment:submit' => array(
 
         'captype' => 'write',
index bef1da4..725983f 100644 (file)
@@ -32,6 +32,7 @@ $string['allownotes_help'] = 'If enabled, students may enter notes into a text a
 $string['allowresubmit'] = 'Allow resubmitting';
 $string['allowresubmit_help'] = 'If enabled, students will be allowed to resubmit assignments after they have been graded (for them to be re-graded).';
 $string['alreadygraded'] = 'Your assignment has already been graded and resubmission is not allowed.';
+$string['assignment:addinstance'] = 'Add a new assignment';
 $string['assignmentdetails'] = 'Assignment details';
 $string['assignment:exportownsubmission'] = 'Export own submission';
 $string['assignment:exportsubmission'] = 'Export submission';
index 4b787e7..544b8a8 100644 (file)
@@ -25,7 +25,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$module->version   = 2011112900;       // The current module version (Date: YYYYMMDDXX)
-$module->requires  = 2011112900;       // Requires this Moodle version
+$module->version   = 2012030700;       // The current module version (Date: YYYYMMDDXX)
+$module->requires  = 2012030100.04;    // Requires this Moodle version
 $module->component = 'mod_assignment'; // Full name of the plugin (used for diagnostics)
 $module->cron      = 60;
index 2d6e5d0..90e4e01 100644 (file)
@@ -26,6 +26,18 @@ defined('MOODLE_INTERNAL') || die();
 
 $capabilities = array(
 
+    'mod/chat:addinstance' => array(
+        'riskbitmask' => RISK_XSS,
+
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_COURSE,
+        'archetypes' => array(
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW
+        ),
+        'clonepermissionsfrom' => 'moodle/course:manageactivities'
+    ),
+
     'mod/chat:chat' => array(
 
         'riskbitmask' => RISK_SPAM,
@@ -92,5 +104,3 @@ $capabilities = array(
     ),
 
 );
-
-
index 5a02544..34bfc47 100644 (file)
@@ -47,6 +47,7 @@ $string['explaingeneralconfig'] = 'These settings are <strong>always</strong> us
 $string['explainmethoddaemon'] = 'These settings matter <strong>only</strong> if you have selected "Chat server daemon" for chat_method';
 $string['explainmethodnormal'] = 'These settings matter <strong>only</strong> if you have selected "Normal method" for chat_method';
 $string['generalconfig'] = 'General configuration';
+$string['chat:addinstance'] = 'Add a new chat';
 $string['chat:deletelog'] = 'Delete chat logs';
 $string['chat:exportparticipatedsession'] = 'Export chat session which you took part in';
 $string['chat:exportsession'] = 'Export any chat session';
index 48dba99..3342dc6 100644 (file)
@@ -25,7 +25,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$module->version   = 2011112900;       // The current module version (Date: YYYYMMDDXX)
-$module->requires  = 2011112900;       // Requires this Moodle version
+$module->version   = 2012030700;       // The current module version (Date: YYYYMMDDXX)
+$module->requires  = 2012030100.04;    // Requires this Moodle version
 $module->component = 'mod_chat';       // Full name of the plugin (used for diagnostics)
 $module->cron      = 300;
index cf3dfb8..1f5d597 100644 (file)
@@ -26,6 +26,18 @@ defined('MOODLE_INTERNAL') || die();
 
 $capabilities = array(
 
+    'mod/choice:addinstance' => array(
+        'riskbitmask' => RISK_XSS,
+
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_COURSE,
+        'archetypes' => array(
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW
+        ),
+        'clonepermissionsfrom' => 'moodle/course:manageactivities'
+    ),
+
     'mod/choice:choose' => array(
 
         'captype' => 'write',
index c069dc1..c1be25c 100644 (file)
@@ -35,6 +35,7 @@ $string['atleastoneoption'] = 'You need to provide at least one possible answer.
 $string['full'] = '(Full)';
 $string['havetologin'] = 'You have to log in before you can submit your choice';
 $string['choice'] = 'Choice';
+$string['choice:addinstance'] = 'Add a new choice';
 $string['choiceclose'] = 'Until';
 $string['choice:deleteresponses'] = 'Delete responses';
 $string['choice:downloadresponses'] = 'Download responses';
index 672932d..fb9ef04 100644 (file)
@@ -25,7 +25,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$module->version   = 2011112900;       // The current module version (Date: YYYYMMDDXX)
-$module->requires  = 2011112900;       // Requires this Moodle version
+$module->version   = 2012030700;       // The current module version (Date: YYYYMMDDXX)
+$module->requires  = 2012030100.04;    // Requires this Moodle version
 $module->component = 'mod_choice';     // Full name of the plugin (used for diagnostics)
 $module->cron      = 0;
index 87035f3..652c7c4 100644 (file)
@@ -26,6 +26,18 @@ defined('MOODLE_INTERNAL') || die();
 
 $capabilities = array(
 
+    'mod/data:addinstance' => array(
+        'riskbitmask' => RISK_XSS,
+
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_COURSE,
+        'archetypes' => array(
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW
+        ),
+        'clonepermissionsfrom' => 'moodle/course:manageactivities'
+    ),
+
     'mod/data:viewentry' => array(
 
         'captype' => 'read',
index 8abba58..0740288 100644 (file)
@@ -72,6 +72,7 @@ $string['csvfile'] = 'CSV file';
 $string['csvimport'] = 'CSV file import';
 $string['csvimport_help'] = 'Entries may be imported via a plain text file with a list of field names as the first line, then the data, with one record per line.';
 $string['csvwithselecteddelimiter'] = '<acronym title="Comma Separated Values">CSV</acronym> text with selected delimiter:';
+$string['data:addinstance'] = 'Add a new database';
 $string['data:approve'] = 'Approve unapproved entries';
 $string['data:comment'] = 'Write comments';
 $string['data:exportallentries'] = 'Export all database entries';
index 1add7a1..d31fbf0 100644 (file)
@@ -25,7 +25,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$module->version   = 2011112900;       // The current module version (Date: YYYYMMDDXX)
-$module->requires  = 2011112900;       // Requires this Moodle version
+$module->version   = 2012030700;       // The current module version (Date: YYYYMMDDXX)
+$module->requires  = 2012030100.04;    // Requires this Moodle version
 $module->component = 'mod_data';       // Full name of the plugin (used for diagnostics)
 $module->cron      = 60;
index fa628d3..30c309a 100644 (file)
@@ -26,6 +26,18 @@ defined('MOODLE_INTERNAL') || die();
 
 $capabilities = array(
 
+    'mod/feedback:addinstance' => array(
+        'riskbitmask' => RISK_XSS,
+
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_COURSE,
+        'archetypes' => array(
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW
+        ),
+        'clonepermissionsfrom' => 'moodle/course:manageactivities'
+    ),
+
     'mod/feedback:view' => array(
 
         'captype' => 'read',
index a687ed2..57f2490 100644 (file)
@@ -106,6 +106,7 @@ You can view it <a href="{$a->url}">here</a>.';
 $string['entries_saved'] = 'Your answers have been saved. Thank you.';
 $string['export_questions'] = 'Export questions';
 $string['export_to_excel'] = 'Export to Excel';
+$string['feedback:addinstance'] = 'Add a new feedback';
 $string['feedbackclose'] = 'Close the feedback at';
 $string['feedbackcloses'] = 'Feedback closes';
 $string['feedback:complete'] = 'Complete a feedback';
index 542d14a..e301079 100644 (file)
@@ -25,8 +25,8 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$module->version   = 2011112900;       // The current module version (Date: YYYYMMDDXX)
-$module->requires  = 2011112900;       // Requires this Moodle version
+$module->version   = 2012030700;       // The current module version (Date: YYYYMMDDXX)
+$module->requires  = 2012030100.04;    // Requires this Moodle version
 $module->component = 'mod_feedback';   // Full name of the plugin (used for diagnostics)
 $module->cron      = 0;
 
index e6b2c10..3900004 100644 (file)
 defined('MOODLE_INTERNAL') || die();
 
 $capabilities = array(
+
+    'mod/folder:addinstance' => array(
+        'riskbitmask' => RISK_XSS,
+
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_COURSE,
+        'archetypes' => array(
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW
+        ),
+        'clonepermissionsfrom' => 'moodle/course:manageactivities'
+    ),
+
     'mod/folder:view' => array(
         'captype' => 'read',
         'contextlevel' => CONTEXT_MODULE,
index 790d7b5..3a55366 100644 (file)
@@ -25,6 +25,7 @@
  */
 
 $string['contentheader'] = 'Content';
+$string['folder:addinstance'] = 'Add a new folder';
 $string['folder:managefiles'] = 'Manage files in folder module';
 $string['folder:view'] = 'View folder content';
 $string['foldercontent'] = 'Files and subfolders';
index eb10fa2..3be807f 100644 (file)
@@ -25,7 +25,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$module->version   = 2011112900;       // The current module version (Date: YYYYMMDDXX)
-$module->requires  = 2011112900;       // Requires this Moodle version
+$module->version   = 2012030700;       // The current module version (Date: YYYYMMDDXX)
+$module->requires  = 2012030100.04;    // Requires this Moodle version
 $module->component = 'mod_folder';     // Full name of the plugin (used for diagnostics)
 $module->cron      = 0;
index 2c5aa42..a92df57 100644 (file)
@@ -26,6 +26,18 @@ defined('MOODLE_INTERNAL') || die();
 
 $capabilities = array(
 
+    'mod/forum:addinstance' => array(
+        'riskbitmask' => RISK_XSS,
+
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_COURSE,
+        'archetypes' => array(
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW
+        ),
+        'clonepermissionsfrom' => 'moodle/course:manageactivities'
+    ),
+
     'mod/forum:viewdiscussion' => array(
 
         'captype' => 'read',
index 88ab2a8..457ebf0 100644 (file)
@@ -149,6 +149,7 @@ $string['existingsubscribers'] = 'Existing subscribers';
 $string['exportdiscussion'] = 'Export whole discussion';
 $string['forcessubscribe'] = 'This forum forces everyone to be subscribed';
 $string['forum'] = 'Forum';
+$string['forum:addinstance'] = 'Add a new forum';
 $string['forum:addnews'] = 'Add news';
 $string['forum:addquestion'] = 'Add question';
 $string['forumauthorhidden'] = 'Author (hidden)';
index 4f142a7..bce4b6a 100644 (file)
@@ -25,7 +25,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$module->version   = 2011112900;       // The current module version (Date: YYYYMMDDXX)
-$module->requires  = 2011112900;       // Requires this Moodle version
+$module->version   = 2012030700;       // The current module version (Date: YYYYMMDDXX)
+$module->requires  = 2012030100.04;    // Requires this Moodle version
 $module->component = 'mod_forum';      // Full name of the plugin (used for diagnostics)
 $module->cron      = 60;
index 98b67fc..36f27f7 100644 (file)
@@ -26,6 +26,18 @@ defined('MOODLE_INTERNAL') || die();
 
 $capabilities = array(
 
+    'mod/glossary:addinstance' => array(
+        'riskbitmask' => RISK_XSS,
+
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_COURSE,
+        'archetypes' => array(
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW
+        ),
+        'clonepermissionsfrom' => 'moodle/course:manageactivities'
+    ),
+
     'mod/glossary:write' => array(
 
         'riskbitmask' => RISK_SPAM,
index 78d61fa..7112327 100644 (file)
@@ -170,6 +170,7 @@ $string['fillfields'] = 'Concept and definition are mandatory fields.';
 $string['filtername'] = 'Glossary auto-linking';
 $string['fullmatch'] = 'Match whole words only';
 $string['fullmatch_help'] = 'This setting specifies whether only whole words will be linked, for example, a glossary entry named "construct" will not create a link inside the word "constructivism".';
+$string['glossary:addinstance'] = 'Add a new glossary';
 $string['glossary:approve'] = 'Approve unapproved entries';
 $string['glossary:comment'] = 'Create comments';
 $string['glossary:export'] = 'Export entries';
index 1cf903e..f6ed006 100644 (file)
@@ -25,7 +25,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$module->version   = 2012022000;       // The current module version (Date: YYYYMMDDXX)
-$module->requires  = 2011112900;       // Requires this Moodle version
+$module->version   = 2012030700;       // The current module version (Date: YYYYMMDDXX)
+$module->requires  = 2012030100.04;    // Requires this Moodle version
 $module->component = 'mod_glossary';   // Full name of the plugin (used for diagnostics)
 $module->cron      = 0;
index 0b92baf..31c4d09 100644 (file)
@@ -34,6 +34,18 @@ $capabilities = array(
         )
     ),
 
+    'mod/imscp:addinstance' => array(
+        'riskbitmask' => RISK_XSS,
+
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_COURSE,
+        'archetypes' => array(
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW
+        ),
+        'clonepermissionsfrom' => 'moodle/course:manageactivities'
+    ),
+
 /* TODO: review public portfolio API first!
     'mod/imscp:portfolioexport' => array(
 
index d7dd234..278d033 100644 (file)
@@ -30,6 +30,7 @@ $string['contentheader'] = 'Content';
 $string['deploymenterror'] = 'Content package error!';
 $string['keepold'] = 'Archive packages';
 $string['keepoldexplain'] = 'How many packages should be archived?';
+$string['imscp:addinstance'] = 'Add a new IMS content package';
 $string['imscp:view'] = 'View IMS content';
 $string['modulename'] = 'IMS content package';
 $string['modulename_help'] = 'An IMS content package allows for packages created according to the IMS Content Packaging specification to be displayed in the course.';
index 2676022..e0887ef 100644 (file)
@@ -25,7 +25,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$module->version   = 2011112900;       // The current module version (Date: YYYYMMDDXX)
-$module->requires  = 2011112900;       // Requires this Moodle version
+$module->version   = 2012030700;       // The current module version (Date: YYYYMMDDXX)
+$module->requires  = 2012030100.04;    // Requires this Moodle version
 $module->component = 'mod_imscp';      // Full name of the plugin (used for diagnostics)
 $module->cron      = 0;
diff --git a/mod/label/db/access.php b/mod/label/db/access.php
new file mode 100644 (file)
index 0000000..57677e6
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Capability definitions for the label module.
+ *
+ * @package    mod_label
+ * @copyright  2012 The Open University
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or late
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+$capabilities = array(
+
+    'mod/label:addinstance' => array(
+        'riskbitmask' => RISK_XSS,
+
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_COURSE,
+        'archetypes' => array(
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW
+        ),
+        'clonepermissionsfrom' => 'moodle/course:manageactivities'
+    ),
+
+);
index cbcbe73..dcdedb0 100644 (file)
@@ -24,6 +24,7 @@
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
+$string['label:addinstance'] = 'Add a new label';
 $string['labeltext'] = 'Label text';
 $string['modulename'] = 'Label';
 $string['modulename_help'] = 'A label enables text and images to be inserted among the activity links on the course page.';
index 01f4976..6822156 100644 (file)
@@ -25,7 +25,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$module->version   = 2011112900;       // The current module version (Date: YYYYMMDDXX)
-$module->requires  = 2011112900;       // Requires this Moodle version
+$module->version   = 2012030700;       // The current module version (Date: YYYYMMDDXX)
+$module->requires  = 2012030100.04;    // Requires this Moodle version
 $module->component = 'mod_label'; // Full name of the plugin (used for diagnostics)
 $module->cron      = 0;
index d78341c..4da9931 100644 (file)
@@ -28,6 +28,18 @@ defined('MOODLE_INTERNAL') || die();
 
 $capabilities = array(
 
+    'mod/lesson:addinstance' => array(
+        'riskbitmask' => RISK_XSS,
+
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_COURSE,
+        'archetypes' => array(
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW
+        ),
+        'clonepermissionsfrom' => 'moodle/course:manageactivities'
+    ),
+
     'mod/lesson:edit' => array(
 
         'riskbitmask' => RISK_XSS, // we want flash and JS in question pages
index 7898e78..017c10d 100644 (file)
@@ -208,6 +208,7 @@ $string['jumps_help'] = 'Each answer (for questions) or description (for content
 $string['jumpsto'] = 'Jumps to <em>{$a}</em>';
 $string['leftduringtimed'] = 'You have left during a timed lesson.<br />Please click on Continue to restart the lesson.';
 $string['leftduringtimednoretake'] = 'You have left during a timed lesson and you are<br />not allowed to retake or continue the lesson.';
+$string['lesson:addinstance'] = 'Add a new lesson';
 $string['lessonattempted'] = 'Lesson attempted';
 $string['lessonclosed'] = 'This lesson closed on {$a}.';
 $string['lessoncloses'] = 'Lesson closes';
index c65af96..f5ba245 100644 (file)
@@ -25,7 +25,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$module->version   = 2011112900;       // The current module version (Date: YYYYMMDDXX)
-$module->requires  = 2011112900;       // Requires this Moodle version
+$module->version   = 2012030700;       // The current module version (Date: YYYYMMDDXX)
+$module->requires  = 2012030100.04;    // Requires this Moodle version
 $module->component = 'mod_lesson'; // Full name of the plugin (used for diagnostics)
 $module->cron      = 0;
index 5f4edc8..51c676d 100644 (file)
@@ -43,6 +43,18 @@ $capabilities = array(
         )
     ),
 
+    'mod/lti:addinstance' => array(
+        'riskbitmask' => RISK_XSS,
+
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_COURSE,
+        'archetypes' => array(
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW
+        ),
+        'clonepermissionsfrom' => 'moodle/course:manageactivities'
+    ),
+
     'mod/lti:grade' => array(
         'riskbitmask' => RISK_XSS,
 
index 1ad131a..60df1ee 100644 (file)
@@ -219,6 +219,7 @@ real estate to the tool, and others provide a more integrated feel with the Mood
         It is possible that browsers will prevent the new window from opening.';
 $string['launchoptions'] = 'Launch Options';
 $string['lti'] = 'LTI';
+$string['lti:addinstance'] = 'Add a new LTI activity';
 $string['lti:addcoursetool'] = 'Grade LTI activities';
 $string['lti:grade'] = 'Grade LTI activities';
 $string['lti:manage'] = 'Edit LTI activities';
index 16fbb7a..fb6d5ed 100644 (file)
@@ -49,7 +49,7 @@
 
 defined('MOODLE_INTERNAL') || die;
 
-$module->version   = 2011112900;       // The current module version (Date: YYYYMMDDXX)
-$module->requires  = 2011112900;       // Requires this Moodle version
+$module->version   = 2012030700;       // The current module version (Date: YYYYMMDDXX)
+$module->requires  = 2012030100.04;    // Requires this Moodle version
 $module->component = 'mod_lti';        // Full name of the plugin (used for diagnostics)
 $module->cron      = 0;
index 247d014..54b4739 100644 (file)
@@ -34,6 +34,19 @@ $capabilities = array(
         )
     ),
 
+    'mod/page:addinstance' => array(
+        'riskbitmask' => RISK_XSS,
+
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_COURSE,
+        'archetypes' => array(
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW
+        ),
+        'clonepermissionsfrom' => 'moodle/course:manageactivities'
+    ),
+
+
 /* TODO: review public portfolio API first!
     'mod/page:portfolioexport' => array(
 
index e24dd4e..98af5a6 100644 (file)
@@ -38,6 +38,7 @@ $string['modulenameplural'] = 'Pages';
 $string['neverseen'] = 'Never seen';
 $string['optionsheader'] = 'Options';
 $string['page-mod-page-x'] = 'Any page module page';
+$string['page:addinstance'] = 'Add a new page resource';
 $string['page:view'] = 'View page content';
 $string['pluginadministration'] = 'Page module administration';
 $string['pluginname'] = 'Page';
index 5fb8f80..744c4ee 100644 (file)
@@ -25,7 +25,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$module->version   = 2011112900;       // The current module version (Date: YYYYMMDDXX)
-$module->requires  = 2011112900;       // Requires this Moodle version
+$module->version   = 2012030700;       // The current module version (Date: YYYYMMDDXX)
+$module->requires  = 2012030100.04;    // Requires this Moodle version
 $module->component = 'mod_page';       // Full name of the plugin (used for diagnostics)
 $module->cron      = 0;
index ee7bf4a..57f0e7d 100644 (file)
@@ -40,6 +40,19 @@ $capabilities = array(
         )
     ),
 
+    // Ability to add a new quiz to the course.
+    'mod/quiz:addinstance' => array(
+        'riskbitmask' => RISK_XSS,
+
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_COURSE,
+        'archetypes' => array(
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW
+        ),
+        'clonepermissionsfrom' => 'moodle/course:manageactivities'
+    ),
+
     // Ability to do the quiz as a 'student'.
     'mod/quiz:attempt' => array(
         'riskbitmask' => RISK_SPAM,
index c8306db..cdbc997 100644 (file)
@@ -540,6 +540,7 @@ $string['questiontext'] = 'Question text';
 $string['questiontextisempty'] = '[Empty question text]';
 $string['questiontype'] = 'Question type {$a}';
 $string['questiontypesetupoptions'] = 'Setup options for question types:';
+$string['quiz:addinstance'] = 'Add a new quiz';
 $string['quiz:attempt'] = 'Attempt quizzes';
 $string['quizavailable'] = 'The quiz is available until: {$a}';
 $string['quizclose'] = 'Close the quiz';
index 578958f..25dba1a 100644 (file)
@@ -25,7 +25,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$module->version   = 2011120703;       // The current module version (Date: YYYYMMDDXX)
-$module->requires  = 2011112900;       // Requires this Moodle version
+$module->version   = 2012030900;       // The current module version (Date: YYYYMMDDXX)
+$module->requires  = 2012030100.04;    // Requires this Moodle version
 $module->component = 'mod_quiz';       // Full name of the plugin (used for diagnostics)
 $module->cron      = 60;
index 54453da..4f729c6 100644 (file)
@@ -34,6 +34,18 @@ $capabilities = array(
         )
     ),
 
+    'mod/resource:addinstance' => array(
+        'riskbitmask' => RISK_XSS,
+
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_COURSE,
+        'archetypes' => array(
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW
+        ),
+        'clonepermissionsfrom' => 'moodle/course:manageactivities'
+    ),
+
 /* TODO: review public portfolio API first!
     'mod/resource:portfolioexport' => array(
 
index d675cc4..ae0ef79 100644 (file)
@@ -81,6 +81,7 @@ $string['printheading'] = 'Display resource name';
 $string['printheadingexplain'] = 'Display resource name above content? Some display types may not display resource name even if enabled.';
 $string['printintro'] = 'Display resource description';
 $string['printintroexplain'] = 'Display resource description below content? Some display types may not display description even if enabled.';
+$string['resource:addinstance'] = 'Add a new resource';
 $string['resourcecontent'] = 'Files and subfolders';
 $string['resourcedetails_sizetype'] = '{$a->size} {$a->type}';
 $string['resource:exportresource'] = 'Export resource';
index cdb37cb..1f3a9c9 100644 (file)
@@ -25,7 +25,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$module->version   = 2011112900;       // The current module version (Date: YYYYMMDDXX)
-$module->requires  = 2011112900;       // Requires this Moodle version
+$module->version   = 2012030700;       // The current module version (Date: YYYYMMDDXX)
+$module->requires  = 2012030100.04;    // Requires this Moodle version
 $module->component = 'mod_resource'; // Full name of the plugin (used for diagnostics)
 $module->cron      = 0;
index 101da76..8efc9ae 100644 (file)
@@ -26,6 +26,18 @@ defined('MOODLE_INTERNAL') || die();
 
 $capabilities = array(
 
+    'mod/scorm:addinstance' => array(
+        'riskbitmask' => RISK_XSS,
+
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_COURSE,
+        'archetypes' => array(
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW
+        ),
+        'clonepermissionsfrom' => 'moodle/course:manageactivities'
+    ),
+
     'mod/scorm:viewreport' => array(
 
         'captype' => 'read',
index b5ad5d5..9aa0f00 100644 (file)
@@ -253,6 +253,7 @@ $string['review'] = 'Review';
 $string['reviewmode'] = 'Review mode';
 $string['scoes'] = 'Learning objects';
 $string['score'] = 'Score';
+$string['scorm:addinstance'] = 'Add a new SCORM package';
 $string['scormclose'] = 'Until';
 $string['scormcourse'] = 'Learning course';
 $string['scorm:deleteresponses'] = 'Delete SCORM attempts';
index 374b9b4..78b3562 100644 (file)
@@ -25,7 +25,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$module->version   = 2011112901;       // The current module version (Date: YYYYMMDDXX)
-$module->requires  = 2011112900;       // Requires this Moodle version
+$module->version   = 2012030700;       // The current module version (Date: YYYYMMDDXX)
+$module->requires  = 2012030100.04;    // Requires this Moodle version
 $module->component = 'mod_scorm'; // Full name of the plugin (used for diagnostics)
 $module->cron      = 300;
index 212d71c..57e04da 100644 (file)
@@ -26,6 +26,18 @@ defined('MOODLE_INTERNAL') || die();
 
 $capabilities = array(
 
+    'mod/survey:addinstance' => array(
+        'riskbitmask' => RISK_XSS,
+
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_COURSE,
+        'archetypes' => array(
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW
+        ),
+        'clonepermissionsfrom' => 'moodle/course:manageactivities'
+    ),
+
     'mod/survey:participate' => array(
 
         'captype' => 'read',
index 9c61c58..699f5a0 100644 (file)
@@ -234,6 +234,7 @@ $string['scaletimes5'] = 'Almost never,Seldom,Sometimes,Often,Almost always';
 $string['seemoredetail'] = 'Click here to see more detail';
 $string['selectedquestions'] = 'Selected questions from a scale, all students';
 $string['summary'] = 'Summary';
+$string['survey:addinstance'] = 'Add a new survey';
 $string['surveycompleted'] = 'You\'ve completed this survey.  The graph below shows a summary of your results compared to the class averages.';
 $string['survey:download'] = 'Download responses';
 $string['surveygraph'] = 'Survey graph';
index 531e5bb..d1f3c8a 100644 (file)
@@ -25,7 +25,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$module->version   = 2011112900;       // The current module version (Date: YYYYMMDDXX)
-$module->requires  = 2011112900;       // Requires this Moodle version
+$module->version   = 2012030700;       // The current module version (Date: YYYYMMDDXX)
+$module->requires  = 2012030100.04;    // Requires this Moodle version
 $module->component = 'mod_survey';     // Full name of the plugin (used for diagnostics)
 $module->cron      = 0;
index 23e666b..62b3918 100644 (file)
@@ -2,6 +2,13 @@ This files describes API changes in /mod/* - activity modules,
 information provided here is intended especially for developers.
 
 
+=== 2.3 ===
+
+required changes in code:
+* define the capability mod/xxx:addinstance (and the corresponding lang string)
+  (unless your mod is a MOD_ARCHETYPE_SYSTEM).
+
+
 === 2.2 ===
 
 required changes in code:
index c0d4d81..2706365 100644 (file)
@@ -34,6 +34,18 @@ $capabilities = array(
         )
     ),
 
+    'mod/url:addinstance' => array(
+        'riskbitmask' => RISK_XSS,
+
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_COURSE,
+        'archetypes' => array(
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW
+        ),
+        'clonepermissionsfrom' => 'moodle/course:manageactivities'
+    ),
+
 /* TODO: review public portfolio API first!
     'mod/url:portfolioexport' => array(
 
index b152259..dacfb0c 100644 (file)
@@ -67,4 +67,5 @@ $string['printintro'] = 'Display URL description';
 $string['printintroexplain'] = 'Display URL description below content? Some display types may not display description even if enabled.';
 $string['rolesinparams'] = 'Include role names in parameters';
 $string['serverurl'] = 'Server URL';
+$string['url:addinstance'] = 'Add a new URL resource';
 $string['url:view'] = 'View URL';
index 28c0ee4..66357e0 100644 (file)
@@ -25,7 +25,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$module->version   = 2011112900;       // The current module version (Date: YYYYMMDDXX)
-$module->requires  = 2011112900;       // Requires this Moodle version
+$module->version   = 2012030700;       // The current module version (Date: YYYYMMDDXX)
+$module->requires  = 2012030100.04;    // Requires this Moodle version
 $module->component = 'mod_url';        // Full name of the plugin (used for diagnostics)
 $module->cron      = 0;
index 40b0d26..d295aba 100644 (file)
@@ -26,6 +26,18 @@ defined('MOODLE_INTERNAL') || die();
 
 $capabilities = array(
 
+    'mod/wiki:addinstance' => array(
+        'riskbitmask' => RISK_XSS,
+
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_COURSE,
+        'archetypes' => array(
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW
+        ),
+        'clonepermissionsfrom' => 'moodle/course:manageactivities'
+    ),
+
     'mod/wiki:viewpage' => array(
 
         'captype' => 'read',
index 09a6c58..f778f02 100644 (file)
@@ -225,6 +225,7 @@ $string['wikinowikitext'] = 'No wiki text';
 $string['wikiorderedlist'] = 'Ordered list';
 $string['wikisettings'] = 'Wiki settings';
 $string['wikiunorderedlist'] = 'Unordered list';
+$string['wiki:addinstance'] = 'Add a new wiki';
 $string['wiki:createpage'] = 'Create new wiki pages';
 $string['wiki:editcomment'] = 'Add comments to pages';
 $string['wiki:editpage'] = 'Save wiki pages';
index b289545..c17672b 100644 (file)
@@ -33,7 +33,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$module->version   = 2011112900;       // The current module version (Date: YYYYMMDDXX)
-$module->requires  = 2011112900;       // Requires this Moodle version
+$module->version   = 2012030700;       // The current module version (Date: YYYYMMDDXX)
+$module->requires  = 2012030100.04;    // Requires this Moodle version
 $module->component = 'mod_wiki';       // Full name of the plugin (used for diagnostics)
 $module->cron      = 0;
index d1e38e8..59ae764 100644 (file)
@@ -40,6 +40,19 @@ $capabilities = array(
         )
     ),
 
+    // Ability to add a new workshop to the course.
+    'mod/workshop:addinstance' => array(
+        'riskbitmask' => RISK_XSS,
+
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_COURSE,
+        'archetypes' => array(
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW
+        ),
+        'clonepermissionsfrom' => 'moodle/course:manageactivities'
+    ),
+
     // Ability to change the current phase (stage) of the workshop, for example
     // allow submitting, start assessment period, close workshop etc.
     'mod/workshop:switchphase' => array(
index f51361f..844d0c7 100644 (file)
@@ -251,6 +251,7 @@ $string['useselfassessment_help'] = 'If enabled, a user may be allocated their o
 $string['useselfassessment_desc'] = 'Students may assess their own work';
 $string['weightinfo'] = 'Weight: {$a}';
 $string['withoutsubmission'] = 'Reviewer without own submission';
+$string['workshop:addinstance'] = 'Add a new workshop';
 $string['workshop:allocate'] = 'Allocate submissions for review';
 $string['workshop:editdimensions'] = 'Edit assessment forms';
 $string['workshopfeatures'] = 'Workshop features';
index 9fd8a8c..28505d5 100644 (file)
@@ -25,7 +25,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$module->version   = 2011112900;       // The current module version (Date: YYYYMMDDXX)
-$module->requires  = 2011112900;       // Requires this Moodle version
+$module->version   = 2012030700;       // The current module version (Date: YYYYMMDDXX)
+$module->requires  = 2012030100.04;    // Requires this Moodle version
 $module->component = 'mod_workshop';   // Full name of the plugin (used for diagnostics)
 $module->cron      = 0;
index bde5115..4a2253e 100644 (file)
@@ -884,10 +884,10 @@ class question_attempt {
             case self::PARAM_MARK:
                 // Special case to work around PARAM_NUMBER converting '' to 0.
                 $mark = $this->get_submitted_var($name, PARAM_RAW_TRIMMED, $postdata);
-                if ($mark === '') {
+                if ($mark === '' || is_null($mark)) {
                     return $mark;
                 } else {
-                    return $this->get_submitted_var($name, PARAM_NUMBER, $postdata);
+                    return clean_param(str_replace(',', '.', $mark), PARAM_NUMBER);
                 }
 
             case self::PARAM_FILES:
index 84a4d46..b4fe736 100644 (file)
@@ -123,6 +123,16 @@ class question_attempt_test extends UnitTestCase {
                 'name', question_attempt::PARAM_MARK, array('name' => '123')));
     }
 
+    public function test_get_submitted_var_param_mark_number_uk_decimal() {
+        $this->assertIdentical(123.45, $this->qa->get_submitted_var(
+                'name', question_attempt::PARAM_MARK, array('name' => '123.45')));
+    }
+
+    public function test_get_submitted_var_param_mark_number_eu_decimal() {
+        $this->assertIdentical(123.45, $this->qa->get_submitted_var(
+                'name', question_attempt::PARAM_MARK, array('name' => '123,45')));
+    }
+
     public function test_get_submitted_var_param_mark_invalid() {
         $this->assertIdentical(0.0, $this->qa->get_submitted_var(
                 'name', question_attempt::PARAM_MARK, array('name' => 'frog')));
index 892a933..25e2d18 100644 (file)
@@ -30,7 +30,7 @@
 defined('MOODLE_INTERNAL') || die();
 
 
-$version  = 2012031500.00;              // YYYYMMDD      = weekly release date of this DEV branch
+$version  = 2012031500.04;              // YYYYMMDD      = weekly release date of this DEV branch
                                         //         RR    = release increments - 00 in DEV branches
                                         //           .XX = incremental changes