Merge branch 'install_master' of https://git.in.moodle.com/amosbot/moodle-install
authorJake Dallimore <jake@moodle.com>
Mon, 10 Dec 2018 00:10:39 +0000 (08:10 +0800)
committerJake Dallimore <jake@moodle.com>
Mon, 10 Dec 2018 00:10:39 +0000 (08:10 +0800)
33 files changed:
backup/converter/imscc1/lib.php
backup/converter/imscc11/lib.php
competency/tests/generator/lib.php
course/renderer.php
lib/db/access.php
lib/db/upgrade.php
lib/db/upgradelib.php
lib/tests/accesslib_test.php
lib/tests/upgradelib_test.php
message/amd/build/message_repository.min.js
message/amd/src/message_repository.js
mod/assign/lib.php
mod/book/lib.php
mod/chat/lib.php
mod/choice/lib.php
mod/data/lib.php
mod/feedback/lib.php
mod/folder/lib.php
mod/forum/lib.php
mod/glossary/lib.php
mod/imscp/lib.php
mod/label/lib.php
mod/lesson/lib.php
mod/lti/lib.php
mod/page/lib.php
mod/quiz/lib.php
mod/resource/lib.php
mod/scorm/lib.php
mod/survey/lib.php
mod/url/lib.php
mod/workshop/lib.php
user/profile/lib.php
version.php

index 10476d0..ed4d811 100644 (file)
@@ -37,9 +37,10 @@ class imscc1_converter extends base_converter {
      * @return null|string backup::FORMAT_IMSCC1 if the Common Cartridge 1.0 is detected, null otherwise
      */
     public static function detect_format($tempdir) {
-        global $CFG;
-
-        $filepath = $CFG->dataroot . '/temp/backup/' . $tempdir;
+        $filepath = make_backup_temp_directory($tempdir, false);
+        if (!is_dir($filepath)) {
+            throw new convert_helper_exception('tmp_backup_directory_not_found', $filepath);
+        }
         $manifest = cc2moodle::get_manifest($filepath);
         if (!empty($manifest)) {
             // Looks promising, lets load some information.
index 0c1c6d6..56532fa 100644 (file)
@@ -38,9 +38,10 @@ class imscc11_converter extends base_converter {
      * @return null|string backup::FORMAT_IMSCC11 if the Common Cartridge 1.1 is detected, null otherwise
      */
     public static function detect_format($tempdir) {
-        global $CFG;
-
-        $filepath = $CFG->dataroot . '/temp/backup/' . $tempdir;
+        $filepath = make_backup_temp_directory($tempdir, false);
+        if (!is_dir($filepath)) {
+            throw new convert_helper_exception('tmp_backup_directory_not_found', $filepath);
+        }
         $manifest = cc112moodle::get_manifest($filepath);
         if (file_exists($manifest)) {
             // Looks promising, lets load some information.
index 2fb49d6..15a4473 100644 (file)
@@ -95,8 +95,8 @@ class core_competency_generator extends component_generator_base {
      * @return competency
      */
     public function create_competency($record = null) {
-        $this->frameworkcount++;
-        $i = $this->frameworkcount;
+        $this->competencycount++;
+        $i = $this->competencycount;
         $record = (object) $record;
 
         if (!isset($record->competencyframeworkid)) {
index 974414b..ad00ffb 100644 (file)
@@ -457,7 +457,7 @@ class core_course_renderer extends plugin_renderer_base {
             }
         }
         if ($completionicon) {
-            $formattedname = $mod->get_formatted_name();
+            $formattedname = html_entity_decode($mod->get_formatted_name(), ENT_QUOTES, 'UTF-8');
             if ($completiondata->overrideby) {
                 $args = new stdClass();
                 $args->modname = $formattedname;
@@ -498,7 +498,7 @@ class core_course_renderer extends plugin_renderer_base {
                 $output .= html_writer::empty_tag('input', array(
                     'type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()));
                 $output .= html_writer::empty_tag('input', array(
-                    'type' => 'hidden', 'name' => 'modulename', 'value' => $mod->name));
+                    'type' => 'hidden', 'name' => 'modulename', 'value' => $formattedname));
                 $output .= html_writer::empty_tag('input', array(
                     'type' => 'hidden', 'name' => 'completionstate', 'value' => $newstate));
                 $output .= html_writer::tag('button',
index 9ae57a9..0dbb72a 100644 (file)
@@ -412,7 +412,7 @@ $capabilities = array(
     'moodle/site:accessallgroups' => array(
 
         'captype' => 'read',
-        'contextlevel' => CONTEXT_COURSE,
+        'contextlevel' => CONTEXT_MODULE,
         'archetypes' => array(
             'editingteacher' => CAP_ALLOW,
             'manager' => CAP_ALLOW
@@ -422,7 +422,7 @@ $capabilities = array(
     'moodle/site:viewfullnames' => array(
 
         'captype' => 'read',
-        'contextlevel' => CONTEXT_COURSE,
+        'contextlevel' => CONTEXT_MODULE,
         'archetypes' => array(
             'teacher' => CAP_ALLOW,
             'editingteacher' => CAP_ALLOW,
@@ -436,7 +436,7 @@ $capabilities = array(
     'moodle/site:viewuseridentity' => array(
 
         'captype' => 'read',
-        'contextlevel' => CONTEXT_COURSE,
+        'contextlevel' => CONTEXT_MODULE,
         'archetypes' => array(
             'teacher' => CAP_ALLOW,
             'editingteacher' => CAP_ALLOW,
@@ -462,7 +462,7 @@ $capabilities = array(
         'riskbitmask' => RISK_XSS,
 
         'captype' => 'write',
-        'contextlevel' => CONTEXT_COURSE,
+        'contextlevel' => CONTEXT_MODULE,
         'archetypes' => array(
             'editingteacher' => CAP_ALLOW,
             'manager' => CAP_ALLOW
index a89e7a7..35cf1da 100644 (file)
@@ -2884,5 +2884,10 @@ function xmldb_main_upgrade($oldversion) {
         upgrade_main_savepoint(true, 2018120300.02);
     }
 
+    if ($oldversion < 2018120301.02) {
+        upgrade_delete_orphaned_file_records();
+        upgrade_main_savepoint(true, 2018120301.02);
+    }
+
     return true;
 }
index fa7dcf7..e7e162f 100644 (file)
@@ -539,3 +539,30 @@ function upgrade_fix_serialized_objects($serializeddata) {
     }
     return [$updated, $serializeddata];
 }
+
+/**
+ * Deletes file records which have their repository deleted.
+ *
+ */
+function upgrade_delete_orphaned_file_records() {
+    global $DB;
+
+    $sql = "SELECT f.id, f.contextid, f.component, f.filearea, f.itemid, fr.id AS referencefileid
+              FROM {files} f
+              JOIN {files_reference} fr ON f.referencefileid = fr.id
+         LEFT JOIN {repository_instances} ri ON fr.repositoryid = ri.id
+             WHERE ri.id IS NULL";
+
+    $deletedfiles = $DB->get_recordset_sql($sql);
+
+    $deletedfileids = array();
+
+    $fs = get_file_storage();
+    foreach ($deletedfiles as $deletedfile) {
+        $fs->delete_area_files($deletedfile->contextid, $deletedfile->component, $deletedfile->filearea, $deletedfile->itemid);
+        $deletedfileids[] = $deletedfile->referencefileid;
+    }
+    $deletedfiles->close();
+
+    $DB->delete_records_list('files_reference', 'id', $deletedfileids);
+}
index 932b4bb..2541844 100644 (file)
@@ -3389,6 +3389,88 @@ class core_accesslib_testcase extends advanced_testcase {
         $this->assertDebuggingCalled('get_system_context() is deprecated, please use context_system::instance() instead.', DEBUG_DEVELOPER);
     }
 
+    /**
+     * Helper that verifies a list of capabilities, as returned by
+     * $context->get_capabilities() contains certain capabilities.
+     *
+     * @param array $expected a list of capability names
+     * @param array $actual a list of capability info from $context->get_capabilities().
+     */
+    protected function assert_capability_list_contains($expected, $actual) {
+        $actualnames = [];
+        foreach ($actual as $cap) {
+            $actualnames[$cap->name] = $cap->name;
+        }
+        $this->assertArraySubset(array_combine($expected, $expected), $actualnames);
+    }
+
+    /**
+     * Test that context_system::get_capabilities returns capabilities relevant to all modules.
+     */
+    public function test_context_module_caps_returned_by_get_capabilities_in_sys_context() {
+        $actual = context_system::instance()->get_capabilities();
+
+        // Just test a few representative capabilities.
+        $expectedcapabilities = ['moodle/site:accessallgroups', 'moodle/site:viewfullnames',
+                'repository/upload:view', 'atto/recordrtc:recordaudio'];
+
+        $this->assert_capability_list_contains($expectedcapabilities, $actual);
+    }
+
+    /**
+     * Test that context_coursecat::get_capabilities returns capabilities relevant to all modules.
+     */
+    public function test_context_module_caps_returned_by_get_capabilities_in_course_cat_context() {
+        $this->resetAfterTest(true);
+        $generator = $this->getDataGenerator();
+        $cat = $generator->create_category();
+
+        $actual = context_coursecat::instance($cat->id)->get_capabilities();
+
+        // Just test a few representative capabilities.
+        $expectedcapabilities = ['moodle/site:accessallgroups', 'moodle/site:viewfullnames',
+                'repository/upload:view', 'atto/recordrtc:recordaudio'];
+
+        $this->assert_capability_list_contains($expectedcapabilities, $actual);
+    }
+
+    /**
+     * Test that context_course::get_capabilities returns capabilities relevant to all modules.
+     */
+    public function test_context_module_caps_returned_by_get_capabilities_in_course_context() {
+        $this->resetAfterTest(true);
+        $generator = $this->getDataGenerator();
+        $cat = $generator->create_category();
+        $course = $generator->create_course(['category' => $cat->id]);
+
+        $actual = context_course::instance($course->id)->get_capabilities();
+
+        // Just test a few representative capabilities.
+        $expectedcapabilities = ['moodle/site:accessallgroups', 'moodle/site:viewfullnames',
+                'repository/upload:view', 'atto/recordrtc:recordaudio'];
+
+        $this->assert_capability_list_contains($expectedcapabilities, $actual);
+    }
+
+    /**
+     * Test that context_module::get_capabilities returns capabilities relevant to all modules.
+     */
+    public function test_context_module_caps_returned_by_get_capabilities_mod_context() {
+        $this->resetAfterTest(true);
+        $generator = $this->getDataGenerator();
+        $cat = $generator->create_category();
+        $course = $generator->create_course(['category' => $cat->id]);
+        $page = $generator->create_module('page', ['course' => $course->id]);
+
+        $actual = context_module::instance($page->cmid)->get_capabilities();
+
+        // Just test a few representative capabilities.
+        $expectedcapabilities = ['moodle/site:accessallgroups', 'moodle/site:viewfullnames',
+                'repository/upload:view', 'atto/recordrtc:recordaudio'];
+
+        $this->assert_capability_list_contains($expectedcapabilities, $actual);
+    }
+
     /**
      * Test updating of role capabilities during upgrade
      */
index 0dc466e..360bed6 100644 (file)
@@ -920,4 +920,90 @@ class core_upgradelib_testcase extends advanced_testcase {
         $record = $DB->get_record('block_instances', ['id' => $entryid]);
         $this->assertEquals($expected, $record->configdata);
     }
+
+    /**
+     * Check that orphaned files are deleted.
+     */
+    public function test_upgrade_delete_orphaned_file_records() {
+        global $DB, $CFG;
+        require_once($CFG->dirroot . '/repository/lib.php');
+
+        $this->resetAfterTest();
+        // Create user.
+        $generator = $this->getDataGenerator();
+        $user = $generator->create_user();
+        $this->setUser($user);
+        $usercontext = context_user::instance($user->id);
+        $syscontext = context_system::instance();
+
+        $fs = get_file_storage();
+
+        $userrepository = array();
+        $newstoredfile = array();
+        $repositorypluginname = array('user', 'areafiles');
+
+        // Create two repositories with one file in each.
+        foreach ($repositorypluginname as $key => $value) {
+            // Override repository permission.
+            $capability = 'repository/' . $value . ':view';
+            $guestroleid = $DB->get_field('role', 'id', array('shortname' => 'guest'));
+            assign_capability($capability, CAP_ALLOW, $guestroleid, $syscontext->id, true);
+
+            $args = array();
+            $args['type'] = $value;
+            $repos = repository::get_instances($args);
+            $userrepository[$key] = reset($repos);
+
+            $this->assertInstanceOf('repository', $userrepository[$key]);
+
+            $component = 'user';
+            $filearea  = 'private';
+            $itemid    = $key;
+            $filepath  = '/';
+            $filename  = 'userfile.txt';
+
+            $filerecord = array(
+                'contextid' => $usercontext->id,
+                'component' => $component,
+                'filearea'  => $filearea,
+                'itemid'    => $itemid,
+                'filepath'  => $filepath,
+                'filename'  => $filename,
+            );
+
+            $content = 'Test content';
+            $originalfile = $fs->create_file_from_string($filerecord, $content);
+            $this->assertInstanceOf('stored_file', $originalfile);
+
+            $newfilerecord = array(
+                'contextid' => $syscontext->id,
+                'component' => 'core',
+                'filearea'  => 'phpunit',
+                'itemid'    => $key,
+                'filepath'  => $filepath,
+                'filename'  => $filename,
+            );
+            $ref = $fs->pack_reference($filerecord);
+            $newstoredfile[$key] = $fs->create_file_from_reference($newfilerecord, $userrepository[$key]->id, $ref);
+
+            // Look for references by repository ID.
+            $files = $fs->get_external_files($userrepository[$key]->id);
+            $file = reset($files);
+            $this->assertEquals($file, $newstoredfile[$key]);
+        }
+
+        // Make one file orphaned by deleting first repository.
+        $DB->delete_records('repository_instances', array('id' => $userrepository[0]->id));
+        $DB->delete_records('repository_instance_config', array('instanceid' => $userrepository[0]->id));
+
+        upgrade_delete_orphaned_file_records();
+
+        $files = $fs->get_external_files($userrepository[0]->id);
+        $file = reset($files);
+        $this->assertFalse($file);
+
+        $files = $fs->get_external_files($userrepository[1]->id);
+        $file = reset($files);
+        $this->assertEquals($file, $newstoredfile[1]);
+    }
 }
index 222337f..9f480a6 100644 (file)
Binary files a/message/amd/build/message_repository.min.js and b/message/amd/build/message_repository.min.js differ
index b7bb4d6..a7da2f0 100644 (file)
@@ -524,7 +524,7 @@ define(['jquery', 'core/ajax', 'core/notification'], function($, Ajax, Notificat
      * @return {object} jQuery promise
      */
     var deleteMessages = function(userId, messageIds) {
-        return Ajax.call(messageIds.map(function(messageId) {
+        return $.when.apply(null, Ajax.call(messageIds.map(function(messageId) {
             return {
                 methodname: 'core_message_delete_message',
                 args: {
@@ -532,7 +532,7 @@ define(['jquery', 'core/ajax', 'core/notification'], function($, Ajax, Notificat
                     userid: userId
                 }
             };
-        }));
+        })));
     };
 
     /**
index 775374b..718b7b4 100644 (file)
@@ -1295,10 +1295,7 @@ function assign_cron() {
  * @return array Array of capability strings
  */
 function assign_get_extra_capabilities() {
-    return array('gradereport/grader:view',
-                 'moodle/grade:viewall',
-                 'moodle/site:viewfullnames',
-                 'moodle/site:config');
+    return ['gradereport/grader:view', 'moodle/grade:viewall'];
 }
 
 /**
index 5652f49..f5bd20f 100644 (file)
@@ -63,15 +63,6 @@ function book_get_nav_classes() {
     return array ('navtoc', 'navimages', 'navtext');
 }
 
-/**
- * Returns all other caps used in module
- * @return array
- */
-function book_get_extra_capabilities() {
-    // used for group-members-only
-    return array('moodle/site:accessallgroups');
-}
-
 /**
  * Add book instance.
  *
@@ -794,4 +785,4 @@ function mod_book_core_calendar_provide_event_action(calendar_event $event,
         1,
         true
     );
-}
\ No newline at end of file
+}
index 774ebee..fdecbcd 100644 (file)
@@ -1271,16 +1271,6 @@ function chat_reset_userdata($data) {
     return $status;
 }
 
-/**
- * Returns all other caps used in module
- *
- * @return array
- */
-function chat_get_extra_capabilities() {
-    return array('moodle/site:accessallgroups', 'moodle/site:viewfullnames');
-}
-
-
 /**
  * @param string $feature FEATURE_xx constant for requested feature
  * @return mixed True if module supports feature, null if doesn't know
index f15788e..c6704c7 100644 (file)
@@ -822,15 +822,6 @@ function choice_get_response_data($choice, $cm, $groupmode, $onlyactive) {
     return $allresponses;
 }
 
-/**
- * Returns all other caps used in module
- *
- * @return array
- */
-function choice_get_extra_capabilities() {
-    return array('moodle/site:accessallgroups');
-}
-
 /**
  * @uses FEATURE_GROUPS
  * @uses FEATURE_GROUPINGS
index 3bebba3..797b2be 100644 (file)
@@ -3003,7 +3003,8 @@ function data_reset_userdata($data) {
  * @return array
  */
 function data_get_extra_capabilities() {
-    return array('moodle/site:accessallgroups', 'moodle/site:viewfullnames', 'moodle/rating:view', 'moodle/rating:viewany', 'moodle/rating:viewall', 'moodle/rating:rate', 'moodle/comment:view', 'moodle/comment:post', 'moodle/comment:delete');
+    return ['moodle/rating:view', 'moodle/rating:viewany', 'moodle/rating:viewall', 'moodle/rating:rate',
+            'moodle/comment:view', 'moodle/comment:post', 'moodle/comment:delete'];
 }
 
 /**
index bde69f4..f1ec218 100644 (file)
@@ -42,15 +42,6 @@ define('FEEDBACK_DEFAULT_PAGE_COUNT', 20);
 define('FEEDBACK_EVENT_TYPE_OPEN', 'open');
 define('FEEDBACK_EVENT_TYPE_CLOSE', 'close');
 
-/**
- * Returns all other caps used in module.
- *
- * @return array
- */
-function feedback_get_extra_capabilities() {
-    return array('moodle/site:accessallgroups');
-}
-
 /**
  * @uses FEATURE_GROUPS
  * @uses FEATURE_GROUPINGS
index 13d878f..3a54f19 100644 (file)
@@ -51,14 +51,6 @@ function folder_supports($feature) {
     }
 }
 
-/**
- * Returns all other caps used in module
- * @return array
- */
-function folder_get_extra_capabilities() {
-    return array('moodle/site:accessallgroups');
-}
-
 /**
  * This function is used by the reset_course_userdata function in moodlelib.
  * @param $data the data submitted from the reset course.
index e94a720..aaf91fb 100644 (file)
@@ -7426,7 +7426,7 @@ function forum_get_forum_types_all() {
  * @return array
  */
 function forum_get_extra_capabilities() {
-    return array('moodle/site:accessallgroups', 'moodle/site:viewfullnames', 'moodle/site:trustcontent', 'moodle/rating:view', 'moodle/rating:viewany', 'moodle/rating:viewall', 'moodle/rating:rate');
+    return ['moodle/rating:view', 'moodle/rating:viewany', 'moodle/rating:viewall', 'moodle/rating:rate'];
 }
 
 /**
index a2bf130..a5bd709 100644 (file)
@@ -3073,7 +3073,8 @@ function glossary_reset_userdata($data) {
  * @return array
  */
 function glossary_get_extra_capabilities() {
-    return array('moodle/site:accessallgroups', 'moodle/site:viewfullnames', 'moodle/site:trustcontent', 'moodle/rating:view', 'moodle/rating:viewany', 'moodle/rating:viewall', 'moodle/rating:rate', 'moodle/comment:view', 'moodle/comment:post', 'moodle/comment:delete');
+    return ['moodle/rating:view', 'moodle/rating:viewany', 'moodle/rating:viewall', 'moodle/rating:rate',
+            'moodle/comment:view', 'moodle/comment:post', 'moodle/comment:delete'];
 }
 
 /**
index b637862..0599ae6 100644 (file)
@@ -45,14 +45,6 @@ function imscp_supports($feature) {
     }
 }
 
-/**
- * Returns all other caps used in module
- * @return array
- */
-function imscp_get_extra_capabilities() {
-    return array('moodle/site:accessallgroups');
-}
-
 /**
  * This function is used by the reset_course_userdata function in moodlelib.
  *
index 22f51c1..1931f82 100644 (file)
@@ -163,15 +163,6 @@ function label_reset_userdata($data) {
     return array();
 }
 
-/**
- * Returns all other caps used in module
- *
- * @return array
- */
-function label_get_extra_capabilities() {
-    return array('moodle/site:accessallgroups');
-}
-
 /**
  * @uses FEATURE_IDNUMBER
  * @uses FEATURE_GROUPS
index 9e4d91e..5898fc3 100644 (file)
@@ -1133,14 +1133,6 @@ function lesson_reset_userdata($data) {
     return $status;
 }
 
-/**
- * Returns all other caps used in module
- * @return array
- */
-function lesson_get_extra_capabilities() {
-    return array('moodle/site:accessallgroups');
-}
-
 /**
  * @uses FEATURE_GROUPS
  * @uses FEATURE_GROUPINGS
index 96bf055..8865193 100644 (file)
 
 defined('MOODLE_INTERNAL') || die;
 
-/**
- * Returns all other caps used in module.
- *
- * @return array
- */
-function lti_get_extra_capabilities() {
-    return array('moodle/site:accessallgroups');
-}
-
 /**
  * List of features supported in URL module
  * @param string $feature FEATURE_xx constant for requested feature
@@ -659,4 +650,4 @@ function mod_lti_core_calendar_provide_event_action(calendar_event $event,
         1,
         true
     );
-}
\ No newline at end of file
+}
index 3b6f596..c367786 100644 (file)
@@ -44,14 +44,6 @@ function page_supports($feature) {
     }
 }
 
-/**
- * Returns all other caps used in module
- * @return array
- */
-function page_get_extra_capabilities() {
-    return array('moodle/site:accessallgroups');
-}
-
 /**
  * This function is used by the reset_course_userdata function in moodlelib.
  * @param $data the data submitted from the reset course.
index 8f698ee..3ebe2fd 100644 (file)
@@ -1799,9 +1799,7 @@ function quiz_supports($feature) {
 function quiz_get_extra_capabilities() {
     global $CFG;
     require_once($CFG->libdir . '/questionlib.php');
-    $caps = question_get_all_capabilities();
-    $caps[] = 'moodle/site:accessallgroups';
-    return $caps;
+    return question_get_all_capabilities();
 }
 
 /**
index dd55375..a87bbe5 100644 (file)
@@ -44,14 +44,6 @@ function resource_supports($feature) {
     }
 }
 
-/**
- * Returns all other caps used in module
- * @return array
- */
-function resource_get_extra_capabilities() {
-    return array('moodle/site:accessallgroups');
-}
-
 /**
  * This function is used by the reset_course_userdata function in moodlelib.
  * @param $data the data submitted from the reset course.
index f79e724..35db907 100644 (file)
@@ -842,15 +842,6 @@ function scorm_reset_userdata($data) {
     return $status;
 }
 
-/**
- * Returns all other caps used in module
- *
- * @return array
- */
-function scorm_get_extra_capabilities() {
-    return array('moodle/site:accessallgroups');
-}
-
 /**
  * Lists all file areas current user may browse
  *
index 73e0d78..0a6d0e3 100644 (file)
@@ -770,15 +770,6 @@ function survey_reset_userdata($data) {
     return $status;
 }
 
-/**
- * Returns all other caps used in module
- *
- * @return array
- */
-function survey_get_extra_capabilities() {
-    return array('moodle/site:accessallgroups');
-}
-
 /**
  * @uses FEATURE_GROUPS
  * @uses FEATURE_GROUPINGS
index 5aed89d..6a342f3 100644 (file)
@@ -46,14 +46,6 @@ function url_supports($feature) {
     }
 }
 
-/**
- * Returns all other caps used in module
- * @return array
- */
-function url_get_extra_capabilities() {
-    return array('moodle/site:accessallgroups');
-}
-
 /**
  * This function is used by the reset_course_userdata function in moodlelib.
  * @param $data the data submitted from the reset course.
index b4e3a41..ebe39db 100644 (file)
@@ -1154,15 +1154,6 @@ function workshop_scale_used_anywhere($scaleid) {
     return false;
 }
 
-/**
- * Returns all other caps used in the module
- *
- * @return array
- */
-function workshop_get_extra_capabilities() {
-    return array('moodle/site:accessallgroups');
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // Gradebook API                                                              //
 ////////////////////////////////////////////////////////////////////////////////
index f7d0d88..c82551f 100644 (file)
@@ -185,6 +185,10 @@ class profile_field_base {
         $data = new stdClass();
 
         $usernew->{$this->inputname} = $this->edit_save_data_preprocess($usernew->{$this->inputname}, $data);
+        if (!isset($usernew->{$this->inputname})) {
+            // Field cannot be set to null, set the default value.
+            $usernew->{$this->inputname} = $this->field->defaultdata;
+        }
 
         $data->userid  = $usernew->id;
         $data->fieldid = $this->field->id;
index ebd27f0..c8ca564 100644 (file)
@@ -29,7 +29,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$version  = 2018120301.00;              // YYYYMMDD      = weekly release date of this DEV branch.
+$version  = 2018120301.02;              // YYYYMMDD      = weekly release date of this DEV branch.
                                         //         RR    = release increments - 00 in DEV branches.
                                         //           .XX = incremental changes.