Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 54a393ab62 | |||
| debff7fe73 | |||
| 7ab7bd886d | |||
| d4ece04082 | |||
| d463c79ec2 | |||
| 6cfcfff118 | |||
| 7a142305cf | |||
| aa45fcf78e | |||
| 799f198aa1 | |||
| 13ba557a2b | |||
| b25797ced3 | |||
| 008248c5b1 | |||
| b34eca2f9e | |||
| 1f2a60e458 | |||
| 7f54185c69 | |||
| 54b3003c92 | |||
| 43235c6236 | |||
| 3bb94d6919 |
@@ -1870,4 +1870,180 @@
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="3.3" requires="2.7">
|
||||
<UNICODE level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unicoderequired" />
|
||||
</FEEDBACK>
|
||||
</UNICODE>
|
||||
<DATABASE level="required">
|
||||
<VENDOR name="mariadb" version="5.5.31" />
|
||||
<VENDOR name="mysql" version="5.5.31" />
|
||||
<VENDOR name="postgres" version="9.3" />
|
||||
<VENDOR name="mssql" version="10.0" />
|
||||
<VENDOR name="oracle" version="10.2" />
|
||||
</DATABASE>
|
||||
<PHP version="5.6.5" level="required">
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="pcreunicodewarning" />
|
||||
</FEEDBACK>
|
||||
</PCREUNICODE>
|
||||
<PHP_EXTENSIONS>
|
||||
<PHP_EXTENSION name="iconv" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="iconvrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="mbstring" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="mbstringrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="curl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="curlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="openssl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="opensslrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="tokenizer" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="tokenizerrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xmlrpc" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="xmlrpcrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="soap" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="soaprecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="ctype" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ctyperequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zip" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ziprequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zlib" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="gd" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="gdrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="simplexml" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="simplexmlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="spl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="splrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="pcre" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="dom" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xml" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xmlreader" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="intl" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="intlrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="json" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="hash" level="required"/>
|
||||
<PHP_EXTENSION name="fileinfo" level="required"/>
|
||||
</PHP_EXTENSIONS>
|
||||
<PHP_SETTINGS>
|
||||
<PHP_SETTING name="memory_limit" value="96M" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="settingmemorylimit" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
<PHP_SETTING name="file_uploads" value="1" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="settingfileuploads" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
<PHP_SETTING name="opcache.enable" value="1" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="opcacherecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
</PHP_SETTINGS>
|
||||
<CUSTOM_CHECKS>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_storage_engine" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbstorageengine" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="question/engine/upgrade/upgradelib.php" function="quiz_attempts_upgraded" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="quizattemptsupgradedmessage" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="slashargumentswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="unsupporteddbtablerowformat" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_unoconv_version" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="unoconvwarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_libcurl_version" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="libcurlwarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_format" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbfileformat" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_per_table" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbfilepertable" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_large_prefix" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddblargeprefix" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_is_https" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="ishttpswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_incomplete_unicode_support" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="incompleteunicodesupport" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
</COMPATIBILITY_MATRIX>
|
||||
|
||||
@@ -64,7 +64,7 @@ class block_course_overview extends block_base {
|
||||
$content = array();
|
||||
|
||||
$updatemynumber = optional_param('mynumber', -1, PARAM_INT);
|
||||
if ($updatemynumber >= 0) {
|
||||
if ($updatemynumber >= 0 && optional_param('sesskey', '', PARAM_RAW) && confirm_sesskey()) {
|
||||
block_course_overview_update_mynumber($updatemynumber);
|
||||
}
|
||||
|
||||
@@ -125,4 +125,4 @@ class block_course_overview extends block_base {
|
||||
$config = get_config('block_course_overview');
|
||||
return !empty($config->showwelcomearea);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ function block_course_overview_get_myorder() {
|
||||
// If preference was not found, look in the old location and convert if found.
|
||||
$order = array();
|
||||
if ($value = get_user_preferences('course_overview_course_order')) {
|
||||
$order = unserialize($value);
|
||||
$order = unserialize_array($value);
|
||||
block_course_overview_update_myorder($order);
|
||||
unset_user_preference('course_overview_course_order');
|
||||
}
|
||||
|
||||
@@ -191,7 +191,7 @@ class block_course_overview_renderer extends plugin_renderer_base {
|
||||
for ($i = 1; $i <= $max; $i++) {
|
||||
$options[$i] = $i;
|
||||
}
|
||||
$url = new moodle_url('/my/index.php');
|
||||
$url = new moodle_url('/my/index.php', ['sesskey' => sesskey()]);
|
||||
$select = new single_select($url, 'mynumber', $options, block_course_overview_get_max_user_courses(), array());
|
||||
$select->set_label(get_string('numtodisplay', 'block_course_overview'));
|
||||
$output .= $this->output->render($select);
|
||||
|
||||
@@ -52,11 +52,11 @@ $action = (empty($id)) ? 'add' : 'edit';
|
||||
|
||||
$external = new stdClass();
|
||||
|
||||
// Check that this id exists
|
||||
if (!empty($id) && !$DB->record_exists('blog_external', array('id' => $id))) {
|
||||
print_error('wrongexternalid', 'blog');
|
||||
} elseif (!empty($id)) {
|
||||
$external = $DB->get_record('blog_external', array('id' => $id));
|
||||
// Retrieve the external blog record.
|
||||
if (!empty($id)) {
|
||||
if (!$external = $DB->get_record('blog_external', array('id' => $id, 'userid' => $USER->id))) {
|
||||
print_error('wrongexternalid', 'blog');
|
||||
}
|
||||
}
|
||||
|
||||
$strformheading = ($action == 'edit') ? get_string('editexternalblog', 'blog') : get_string('addnewexternalblog', 'blog');
|
||||
|
||||
+1
-1
@@ -891,7 +891,7 @@ function blog_get_headers($courseid=null, $groupid=null, $userid=null, $tagid=nu
|
||||
}
|
||||
|
||||
// Append Search info
|
||||
if (!empty($search)) {
|
||||
if (!empty($search) && has_capability('moodle/blog:search', $sitecontext)) {
|
||||
$headers['filters']['search'] = $search;
|
||||
$blogurl->param('search', $search);
|
||||
$PAGE->navbar->add(get_string('searchterm', 'blog', $search), $blogurl->out());
|
||||
|
||||
@@ -1605,7 +1605,7 @@ class grade_report_grader extends grade_report {
|
||||
|
||||
// Try looking for old location of user setting that used to store all courses in one serialized user preference.
|
||||
if (($oldcollapsedpref = get_user_preferences('grade_report_grader_collapsed_categories')) !== null) {
|
||||
if ($collapsedall = @unserialize($oldcollapsedpref)) {
|
||||
if ($collapsedall = unserialize_array($oldcollapsedpref)) {
|
||||
// We found the old-style preference, filter out only categories that belong to this course and update the prefs.
|
||||
$collapsed = static::filter_collapsed_categories($courseid, $collapsedall);
|
||||
if (!empty($collapsed['aggregatesonly']) || !empty($collapsed['gradesonly'])) {
|
||||
|
||||
@@ -762,6 +762,7 @@ $string['numberofmissingstrings'] = 'Number of missing strings: {$a}';
|
||||
$string['numberofstrings'] = 'Total number of strings: {$a->strings}<br />Missing: {$a->missing} ({$a->missingpercent} %)';
|
||||
$string['opcacherecommended'] = 'PHP opcode caching improves performance and lowers memory requirements, OPcache extension is recommended and fully supported.';
|
||||
$string['opensslrecommended'] = 'Installing the optional OpenSSL library is highly recommended -- it enables Moodle Networking functionality.';
|
||||
$string['opensslrequired'] = 'The OpenSSL PHP extension is now required by Moodle to provide stronger cryptographic services.';
|
||||
$string['opentogoogle'] = 'Open to Google';
|
||||
$string['optionalmaintenancemessage'] = 'Optional maintenance message';
|
||||
$string['order1'] = 'First';
|
||||
|
||||
@@ -180,6 +180,7 @@ $string['viewmyentriesaboutcourse'] = 'View my entries about this course';
|
||||
$string['viewsiteentries'] = 'View all entries';
|
||||
$string['viewuserentries'] = 'View all entries by {$a}';
|
||||
$string['worldblogs'] = 'The world can read entries set to be world-accessible';
|
||||
$string['wrongexternalid'] = 'Wrong external blog id';
|
||||
$string['wrongpostid'] = 'Wrong blog post id';
|
||||
$string['page-blog-edit'] = 'Blog editing pages';
|
||||
$string['page-blog-index'] = 'Blog listing pages';
|
||||
|
||||
@@ -9670,6 +9670,58 @@ function get_course_display_name_for_list($course) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Safe analogue of unserialize() that can only parse arrays
|
||||
*
|
||||
* Arrays may contain only integers or strings as both keys and values. Nested arrays are allowed.
|
||||
* Note: If any string (key or value) has semicolon (;) as part of the string parsing will fail.
|
||||
* This is a simple method to substitute unnecessary unserialize() in code and not intended to cover all possible cases.
|
||||
*
|
||||
* @param string $expression
|
||||
* @return array|bool either parsed array or false if parsing was impossible.
|
||||
*/
|
||||
function unserialize_array($expression) {
|
||||
$subs = [];
|
||||
// Find nested arrays, parse them and store in $subs , substitute with special string.
|
||||
while (preg_match('/([\^;\}])(a:\d+:\{[^\{\}]*\})/', $expression, $matches) && strlen($matches[2]) < strlen($expression)) {
|
||||
$key = '--SUB' . count($subs) . '--';
|
||||
$subs[$key] = unserialize_array($matches[2]);
|
||||
if ($subs[$key] === false) {
|
||||
return false;
|
||||
}
|
||||
$expression = str_replace($matches[2], $key . ';', $expression);
|
||||
}
|
||||
|
||||
// Check the expression is an array.
|
||||
if (!preg_match('/^a:(\d+):\{([^\}]*)\}$/', $expression, $matches1)) {
|
||||
return false;
|
||||
}
|
||||
// Get the size and elements of an array (key;value;key;value;....).
|
||||
$parts = explode(';', $matches1[2]);
|
||||
$size = intval($matches1[1]);
|
||||
if (count($parts) < $size * 2 + 1) {
|
||||
return false;
|
||||
}
|
||||
// Analyze each part and make sure it is an integer or string or a substitute.
|
||||
$value = [];
|
||||
for ($i = 0; $i < $size * 2; $i++) {
|
||||
if (preg_match('/^i:(\d+)$/', $parts[$i], $matches2)) {
|
||||
$parts[$i] = (int)$matches2[1];
|
||||
} else if (preg_match('/^s:(\d+):"(.*)"$/', $parts[$i], $matches3) && strlen($matches3[2]) == (int)$matches3[1]) {
|
||||
$parts[$i] = $matches3[2];
|
||||
} else if (preg_match('/^--SUB\d+--$/', $parts[$i])) {
|
||||
$parts[$i] = $subs[$parts[$i]];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Combine keys and values.
|
||||
for ($i = 0; $i < $size * 2; $i += 2) {
|
||||
$value[$parts[$i]] = $parts[$i+1];
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The lang_string class
|
||||
*
|
||||
|
||||
@@ -2972,4 +2972,34 @@ class core_moodlelib_testcase extends advanced_testcase {
|
||||
$CFG->mailprefix = 'mdl-';
|
||||
$this->assertEquals(1, validate_email(generate_email_processing_address(23, $modargs)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test safe method unserialize_array().
|
||||
*/
|
||||
public function test_unserialize_array() {
|
||||
$a = [1, 2, 3];
|
||||
$this->assertEquals($a, unserialize_array(serialize($a)));
|
||||
$this->assertEquals($a, unserialize_array(serialize($a)));
|
||||
$a = ['a' => 1, 2 => 2, 'b' => 'cde'];
|
||||
$this->assertEquals($a, unserialize_array(serialize($a)));
|
||||
$this->assertEquals($a, unserialize_array(serialize($a)));
|
||||
$a = ['a' => 1, 2 => 2, 'b' => 'c"d"e'];
|
||||
$this->assertEquals($a, unserialize_array(serialize($a)));
|
||||
$a = ['a' => 1, 2 => ['c' => 'd', 'e' => 'f'], 'b' => 'cde'];
|
||||
$this->assertEquals($a, unserialize_array(serialize($a)));
|
||||
|
||||
// Can not unserialize if any string contains semicolons.
|
||||
$a = ['a' => 1, 2 => 2, 'b' => 'c"d";e'];
|
||||
$this->assertEquals(false, unserialize_array(serialize($a)));
|
||||
|
||||
// Can not unserialize if there are any objects.
|
||||
$a = (object)['a' => 1, 2 => 2, 'b' => 'cde'];
|
||||
$this->assertEquals(false, unserialize_array(serialize($a)));
|
||||
$a = ['a' => 1, 2 => 2, 'b' => (object)['a' => 'cde']];
|
||||
$this->assertEquals(false, unserialize_array(serialize($a)));
|
||||
|
||||
// Array used in the grader report.
|
||||
$a = array('aggregatesonly' => [51, 34], 'gradesonly' => [21, 45, 78]);
|
||||
$this->assertEquals($a, unserialize_array(serialize($a)));
|
||||
}
|
||||
}
|
||||
|
||||
+2330
-2270
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -4516,7 +4516,7 @@ function forum_update_post($newpost, $mform, &$message) {
|
||||
|
||||
// Last post modified tracking.
|
||||
$discussion->timemodified = $post->modified;
|
||||
$discussion->usermodified = $USER->id;
|
||||
$discussion->usermodified = $post->userid;
|
||||
|
||||
if (!$post->parent) { // Post is a discussion starter - update discussion title and times too
|
||||
$discussion->name = $post->subject;
|
||||
@@ -4531,7 +4531,7 @@ function forum_update_post($newpost, $mform, &$message) {
|
||||
forum_add_attachment($post, $forum, $cm, $mform, $message);
|
||||
|
||||
if (forum_tp_can_track_forums($forum) && forum_tp_is_tracked($forum)) {
|
||||
forum_tp_mark_post_read($USER->id, $post, $post->forum);
|
||||
forum_tp_mark_post_read($USER->id, $post, $forum->id);
|
||||
}
|
||||
|
||||
// Let Moodle know that assessable content is uploaded (eg for plagiarism detection)
|
||||
|
||||
@@ -940,4 +940,56 @@ class mod_forum_lib_testcase extends advanced_testcase {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that {@link forum_update_post()} keeps correct forum_discussions usermodified.
|
||||
*/
|
||||
public function test_forum_update_post_keeps_discussions_usermodified() {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Let there be light.
|
||||
$teacher = self::getDataGenerator()->create_user();
|
||||
$student = self::getDataGenerator()->create_user();
|
||||
$course = self::getDataGenerator()->create_course();
|
||||
|
||||
$forum = self::getDataGenerator()->create_module('forum', (object)[
|
||||
'course' => $course->id,
|
||||
]);
|
||||
|
||||
$generator = self::getDataGenerator()->get_plugin_generator('mod_forum');
|
||||
|
||||
// Let the teacher start a discussion.
|
||||
$discussion = $generator->create_discussion((object)[
|
||||
'course' => $course->id,
|
||||
'userid' => $teacher->id,
|
||||
'forum' => $forum->id,
|
||||
]);
|
||||
|
||||
// On this freshly created discussion, the teacher is the author of the last post.
|
||||
$this->assertEquals($teacher->id, $DB->get_field('forum_discussions', 'usermodified', ['id' => $discussion->id]));
|
||||
|
||||
// Let the student reply to the teacher's post.
|
||||
$reply = $generator->create_post((object)[
|
||||
'course' => $course->id,
|
||||
'userid' => $student->id,
|
||||
'forum' => $forum->id,
|
||||
'discussion' => $discussion->id,
|
||||
'parent' => $discussion->firstpost,
|
||||
]);
|
||||
// The student should now be the last post's author.
|
||||
$this->assertEquals($student->id, $DB->get_field('forum_discussions', 'usermodified', ['id' => $discussion->id]));
|
||||
|
||||
// Let the teacher edit the student's reply.
|
||||
$this->setUser($teacher->id);
|
||||
$newpost = (object)[
|
||||
'id' => $reply->id,
|
||||
'itemid' => 0,
|
||||
'subject' => 'Amended subject',
|
||||
];
|
||||
forum_update_post($newpost, null, $message);
|
||||
|
||||
// The student should be still the last post's author.
|
||||
$this->assertEquals($student->id, $DB->get_field('forum_discussions', 'usermodified', ['id' => $discussion->id]));
|
||||
}
|
||||
}
|
||||
|
||||
+32
-2
@@ -203,8 +203,9 @@ class core_user_external extends external_api {
|
||||
|
||||
// Preferences.
|
||||
if (!empty($user['preferences'])) {
|
||||
$userobject = (object)$user;
|
||||
foreach ($user['preferences'] as $preference) {
|
||||
set_user_preference($preference['type'], $preference['value'], $user['id']);
|
||||
self::set_user_preference($preference['type'], $preference['value'], $userobject);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -433,7 +434,7 @@ class core_user_external extends external_api {
|
||||
// Preferences.
|
||||
if (!empty($user['preferences'])) {
|
||||
foreach ($user['preferences'] as $preference) {
|
||||
set_user_preference($preference['type'], $preference['value'], $user['id']);
|
||||
self::set_user_preference($preference['type'], $preference['value'], $existinguser);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1176,6 +1177,35 @@ class core_user_external extends external_api {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates preference value and updates the user preference
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @param stdClass $user
|
||||
*/
|
||||
protected static function set_user_preference($name, $value, $user) {
|
||||
$preferences = array(
|
||||
'auth_forcepasswordchange' => PARAM_BOOL,
|
||||
'htmleditor' => PARAM_COMPONENT,
|
||||
'usemodchooser' => PARAM_BOOL,
|
||||
'badgeprivacysetting' => PARAM_BOOL,
|
||||
'blogpagesize' => PARAM_INT,
|
||||
'forum_markasreadonnotification' => PARAM_INT,
|
||||
'calendar_timeformat' => PARAM_NOTAGS,
|
||||
'calendar_startwday' => PARAM_INT,
|
||||
'calendar_maxevents' => PARAM_INT,
|
||||
'calendar_lookahead' => PARAM_INT,
|
||||
'calendar_persistflt' => PARAM_INT
|
||||
);
|
||||
if (isset($preferences[$name])) {
|
||||
$value = clean_param($value, $preferences[$name]);
|
||||
if ($preferences[$name] == PARAM_BOOL) {
|
||||
$value = (int)$value;
|
||||
}
|
||||
set_user_preference($name, $value, $user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -478,7 +478,14 @@ class core_user_externallib_testcase extends externallib_advanced_testcase {
|
||||
'email' => 'usertest1@example.com',
|
||||
'description' => 'This is a description for user 1',
|
||||
'city' => 'Perth',
|
||||
'country' => 'au'
|
||||
'country' => 'au',
|
||||
'preferences' => [[
|
||||
'type' => 'htmleditor',
|
||||
'value' => 'atto'
|
||||
], [
|
||||
'type' => 'invalidpreference',
|
||||
'value' => 'abcd'
|
||||
]]
|
||||
);
|
||||
|
||||
$context = context_system::instance();
|
||||
@@ -503,6 +510,8 @@ class core_user_externallib_testcase extends externallib_advanced_testcase {
|
||||
$this->assertEquals($dbuser->description, $user1['description']);
|
||||
$this->assertEquals($dbuser->city, $user1['city']);
|
||||
$this->assertEquals($dbuser->country, $user1['country']);
|
||||
$this->assertEquals('atto', get_user_preferences('htmleditor', null, $dbuser));
|
||||
$this->assertEquals(null, get_user_preferences('invalidpreference', null, $dbuser));
|
||||
}
|
||||
|
||||
// Call without required capability
|
||||
@@ -657,7 +666,14 @@ class core_user_externallib_testcase extends externallib_advanced_testcase {
|
||||
'email' => 'usertest1@example.com',
|
||||
'description' => 'This is a description for user 1',
|
||||
'city' => 'Perth',
|
||||
'country' => 'au'
|
||||
'country' => 'au',
|
||||
'preferences' => [[
|
||||
'type' => 'htmleditor',
|
||||
'value' => 'atto'
|
||||
], [
|
||||
'type' => 'invalidpreference',
|
||||
'value' => 'abcd'
|
||||
]]
|
||||
);
|
||||
|
||||
$context = context_system::instance();
|
||||
@@ -693,6 +709,8 @@ class core_user_externallib_testcase extends externallib_advanced_testcase {
|
||||
$this->assertEquals($dbuser->description, $user1['description']);
|
||||
$this->assertEquals($dbuser->city, $user1['city']);
|
||||
$this->assertEquals($dbuser->country, $user1['country']);
|
||||
$this->assertEquals('atto', get_user_preferences('htmleditor', null, $dbuser));
|
||||
$this->assertEquals(null, get_user_preferences('invalidpreference', null, $dbuser));
|
||||
|
||||
// Call without required capability.
|
||||
$this->unassignUserCapability('moodle/user:update', $context->id, $roleid);
|
||||
|
||||
+2
-2
@@ -29,11 +29,11 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$version = 2014051218.00; // 20140512 = branching date YYYYMMDD - do not modify!
|
||||
$version = 2014051220.00; // 20140512 = branching date YYYYMMDD - do not modify!
|
||||
// RR = release increments - 00 in DEV branches.
|
||||
// .XX = incremental changes.
|
||||
|
||||
$release = '2.7.18 (Build: 20170109)'; // Human-friendly version name
|
||||
$release = '2.7.20 (Build: 20170508)'; // Human-friendly version name
|
||||
|
||||
$branch = '27'; // This version's branch.
|
||||
$maturity = MATURITY_STABLE; // This version's maturity level.
|
||||
|
||||
Reference in New Issue
Block a user