Merge branch 'MDL-69392-310' of git://github.com/junpataleta/moodle into MOODLE_310_S...
authorVíctor Déniz <victor@moodle.com>
Wed, 21 Oct 2020 15:26:44 +0000 (16:26 +0100)
committerVíctor Déniz <victor@moodle.com>
Wed, 21 Oct 2020 15:26:44 +0000 (16:26 +0100)
17 files changed:
admin/classes/form/testoutgoingmailconf_form.php
admin/settings/server.php
calendar/templates/month_detailed.mustache
course/classes/local/service/content_item_service.php
course/classes/search/customfield.php
lang/en/admin.php
lib/blocklib.php
lib/classes/session/manager.php
lib/db/upgrade.php
lib/moodlelib.php
lib/templates/loginform.mustache
lib/upgrade.txt
mod/assign/styles.css
theme/boost/scss/moodle/calendar.scss
theme/boost/style/moodle.css
theme/classic/style/moodle.css
version.php

index fbf8ac4..f344cfe 100644 (file)
@@ -43,7 +43,7 @@ class testoutgoingmailconf_form extends \moodleform {
         $mform = $this->_form;
 
         // Recipient.
-        $options = ['maxlength' => '100', 'size' => '25'];
+        $options = ['maxlength' => '100', 'size' => '25', 'autocomplete' => 'email'];
         $mform->addElement('text', 'recipient', get_string('testoutgoingmailconf_toemail', 'admin'), $options);
         $mform->setType('recipient', PARAM_EMAIL);
         $mform->addRule('recipient', get_string('required'), 'required');
index cb586b4..11541bb 100644 (file)
@@ -455,6 +455,15 @@ if ($hassiteconfig) {
         new lang_string('divertallemailsexcept_desc', 'admin'),
         '', PARAM_RAW, '50', '4'));
 
+    $noreplyaddress = isset($CFG->noreplyaddress) ? $CFG->noreplyaddress : 'noreply@example.com';
+    $dkimdomain = substr(strrchr($noreplyaddress, "@"), 1);
+    $dkimselector = empty($CFG->emaildkimselector) ? '[selector]' : $CFG->emaildkimselector;
+    $pempath = "\$CFG->dataroot/dkim/{$dkimdomain}/{$dkimselector}.private";
+    $temp->add(new admin_setting_heading('emaildkim', new lang_string('emaildkim', 'admin'),
+        new lang_string('emaildkiminfo', 'admin', ['path' => $pempath, 'docs' => \get_docs_url('Mail_configuration#DKIM')])));
+    $temp->add(new admin_setting_configtext('emaildkimselector', new lang_string('emaildkimselector', 'admin'),
+        new lang_string('configemaildkimselector', 'admin'), '', PARAM_FILE));
+
     $url = new moodle_url('/admin/testoutgoingmailconf.php');
     $link = html_writer::link($url, get_string('testoutgoingmailconf', 'admin'));
     $temp->add(new admin_setting_heading('testoutgoinmailc', new lang_string('testoutgoingmailconf', 'admin'),
index ba01dfe..e815134 100644 (file)
                                                 {{/draggable}}>
 
                                                 <a data-action="view-event" data-event-id="{{id}}" href="{{url}}" title="{{name}}">
-                                                    <span class="badge badge-circle calendar_event_{{normalisedeventtype}}">
+                                                    <span class="calendar-circle calendar_event_{{normalisedeventtype}}">
                                                         &nbsp;
                                                     </span>
                                                     {{> core_calendar/event_icon}}
index ca60efb..832a7eb 100644 (file)
@@ -110,7 +110,12 @@ class content_item_service {
             throw new \coding_exception('The guest user does not exist in the database.');
         }
 
-        $favourites = $this->get_content_favourites(self::RECOMMENDATION_PREFIX, \context_user::instance($CFG->siteguest));
+        // Make sure the guest user context exists.
+        if (!$guestusercontext = \context_user::instance($CFG->siteguest, false)) {
+            throw new \coding_exception('The guest user context does not exist.');
+        }
+
+        $favourites = $this->get_content_favourites(self::RECOMMENDATION_PREFIX, $guestusercontext);
 
         $recommendationcache->set($CFG->siteguest, $favourites);
         return $favourites;
index 1d62aac..19fa1c2 100644 (file)
@@ -66,7 +66,7 @@ class customfield extends \core_search\base {
         if (!$fields) {
             $fields = array();
         }
-        list($fieldsql, $fieldparam) = $DB->get_in_or_equal(array_keys($fields), SQL_PARAMS_NAMED, 'fld', true, true);
+        list($fieldsql, $fieldparam) = $DB->get_in_or_equal(array_keys($fields), SQL_PARAMS_NAMED, 'fld', true, 0);
 
         // Restrict recordset to CONTEXT_COURSE (since we are implementing it to core_course\search).
         $sql = "SELECT d.*
index 455a2cd..4f66c4f 100644 (file)
@@ -231,6 +231,7 @@ $string['configemailchangeconfirmation'] = 'Require an email confirmation step w
 $string['configemailfromvia'] = 'Add via information in the "From" section of outgoing email. This informs the recipient from where this email came from and also helps combat recipients accidentally replying to no-reply email addresses.';
 $string['configemailsubjectprefix'] = 'Text to be prefixed to the subject line of all outgoing mail.';
 $string['configemailheaders'] = 'Raw email headers to be added verbatim to all outgoing email.';
+$string['configemaildkimselector'] = 'The DKIM selector is arbitrary and your DNS record(s) must match this.';
 $string['configenablecalendarexport'] = 'Enable exporting or subscribing to calendars.';
 $string['configenablecomments'] = 'Enable comments';
 $string['configenablecourserequests'] = 'If enabled, users with the capability to request new courses (moodle/course:request) will have the option to request a course. This capability is not allowed for any of the default roles. It may be applied in the system or category context.';
@@ -529,6 +530,9 @@ $string['editorspelling'] = 'Editor spelling';
 $string['editorspellinghelp'] = 'Enable or disable spell-checking. When enabled, <strong>aspell</strong> must be installed on the server.';
 $string['editstrings'] = 'Edit words or phrases';
 $string['emailchangeconfirmation'] = 'Email change confirmation';
+$string['emaildkim'] = 'DKIM email signing';
+$string['emaildkimselector'] = 'DKIM selector';
+$string['emaildkiminfo'] = 'If both the DKIM selector is set and a private certificate file is found which matches the emails "From" address domain in $CFG->dataroot/dkim/[domain]/[selector].private then the email will be signed. In most cases (eg if allowedemaildomains is empty) then only a single certificate is needed in: <code>{$a->path}</code>. For more setup details see <a href="{$a->docs}">{$a->docs}</a>.';
 $string['emailfromvia'] = 'Email via information';
 $string['emailheaders'] = 'Email headers';
 $string['emailsubjectprefix'] = 'Email subject prefix text';
index 0ca4559..849f848 100644 (file)
@@ -1282,8 +1282,10 @@ class block_manager {
         if ($this->page->user_can_edit_blocks() || $block->user_can_edit()) {
             // Edit config icon - always show - needed for positioning UI.
             $str = new lang_string('configureblock', 'block', $blocktitle);
+            $editactionurl = new moodle_url($actionurl, ['bui_editid' => $block->instance->id]);
+            $editactionurl->remove_params(['sesskey']);
             $controls[] = new action_menu_link_secondary(
-                new moodle_url($actionurl, array('bui_editid' => $block->instance->id)),
+                $editactionurl,
                 new pix_icon('t/edit', $str, 'moodle', array('class' => 'iconsmall', 'title' => '')),
                 $str,
                 array('class' => 'editing_edit')
@@ -1346,8 +1348,10 @@ class block_manager {
         if ($this->user_can_delete_block($block)) {
             // Delete icon.
             $str = new lang_string('deleteblock', 'block', $blocktitle);
+            $deleteactionurl = new moodle_url($actionurl, ['bui_deleteid' => $block->instance->id]);
+            $deleteactionurl->remove_params(['sesskey']);
             $controls[] = new action_menu_link_secondary(
-                new moodle_url($actionurl, array('bui_deleteid' => $block->instance->id)),
+                $deleteactionurl,
                 new pix_icon('t/delete', $str, 'moodle', array('class' => 'iconsmall', 'title' => '')),
                 $str,
                 array('class' => 'editing_delete')
@@ -1497,7 +1501,6 @@ class block_manager {
             return false;
         }
 
-        require_sesskey();
         $block = $this->page->blocks->find_instance($blockid);
         if (!$this->user_can_delete_block($block)) {
             throw new moodle_exception('nopermissions', '', $this->page->url->out(), get_string('deleteablock'));
@@ -1563,6 +1566,8 @@ class block_manager {
             // Make sure that nothing else happens after we have displayed this form.
             exit;
         } else {
+            require_sesskey();
+
             blocks_delete_instance($block->instance);
             // bui_deleteid and bui_confirm should not be in the PAGE url.
             $this->page->ensure_param_not_in_url('bui_deleteid');
@@ -1616,7 +1621,6 @@ class block_manager {
             return false;
         }
 
-        require_sesskey();
         require_once($CFG->dirroot . '/blocks/edit_form.php');
 
         $block = $this->find_instance($blockid);
index c3b0baa..8934080 100644 (file)
@@ -1274,6 +1274,10 @@ class manager {
             return;
         }
 
+        if (defined('READ_ONLY_SESSION') && READ_ONLY_SESSION && !empty($CFG->enable_read_only_sessions)) {
+            return;
+        }
+
         $SESSION->recentsessionlocks = self::get_recent_session_locks();
         array_push($SESSION->recentsessionlocks, $sessionlock);
 
index c960663..b10c549 100644 (file)
@@ -2815,5 +2815,41 @@ function xmldb_main_upgrade($oldversion) {
         upgrade_main_savepoint(true, 2020101600.02);
     }
 
+    if ($oldversion < 2020102100.01) {
+        // Get the current guest user which is also set as 'deleted'.
+        $guestuser = $DB->get_record('user', ['id' => $CFG->siteguest, 'deleted' => 1]);
+        // If there is a deleted guest user, reset the user to not be deleted and make sure the related
+        // user context exists.
+        if ($guestuser) {
+            $guestuser->deleted = 0;
+            $DB->update_record('user', $guestuser);
+
+            // Get the guest user context.
+            $guestusercontext = $DB->get_record('context',
+                ['contextlevel' => CONTEXT_USER, 'instanceid' => $guestuser->id]);
+
+            // If the guest user context does not exist, create it.
+            if (!$guestusercontext) {
+                $record = new stdClass();
+                $record->contextlevel = CONTEXT_USER;
+                $record->instanceid = $guestuser->id;
+                $record->depth = 0;
+                // The path is not known before insert.
+                $record->path = null;
+                $record->locked = 0;
+
+                $record->id = $DB->insert_record('context', $record);
+
+                // Update the path.
+                $record->path = '/' . SYSCONTEXTID . '/' . $record->id;
+                $record->depth = substr_count($record->path, '/');
+                $DB->update_record('context', $record);
+            }
+        }
+
+        // Main savepoint reached.
+        upgrade_main_savepoint(true, 2020102100.01);
+    }
+
     return true;
 }
index b571bb7..4f543ea 100644 (file)
@@ -6384,6 +6384,19 @@ function email_to_user($user, $from, $subject, $messagetext, $messagehtml = '',
         $mail->addReplyTo($values[0], $values[1]);
     }
 
+    if (!empty($CFG->emaildkimselector)) {
+        $domain = substr(strrchr($mail->From, "@"), 1);
+        $pempath = "{$CFG->dataroot}/dkim/{$domain}/{$CFG->emaildkimselector}.private";
+        if (file_exists($pempath)) {
+            $mail->DKIM_domain      = $domain;
+            $mail->DKIM_private     = $pempath;
+            $mail->DKIM_selector    = $CFG->emaildkimselector;
+            $mail->DKIM_identity    = $mail->From;
+        } else {
+            debugging("Email DKIM selector chosen due to {$mail->From} but no certificate found at $pempath", DEBUG_DEVELOPER);
+        }
+    }
+
     if ($mail->send()) {
         set_send_count($user);
         if (!empty($mail->SMTPDebug)) {
index d41a055..c2419fd 100644 (file)
                     {{/canloginasguest}}
 
                 {{#hasidentityproviders}}
-                    <h6 class="mt-2">{{#str}} potentialidps, auth {{/str}}</h6>
+                    <h3 class="h6 mt-2">{{#str}} potentialidps, auth {{/str}}</h3>
                     <div class="potentialidplist mt-3">
                         {{#identityproviders}}
                             <div class="potentialidp">
index 40aa910..438b770 100644 (file)
@@ -58,6 +58,7 @@ information provided here is intended especially for developers.
 * Function redirect() now emits a line of backtrace into the X-Redirect-By header when debugging is on
 * New DML function $DB->delete_records_subquery() to delete records based on a subquery in a way
   that will work across databases.
+* Add support for email DKIM signatures via $CFG->emaildkimselector
 
 === 3.9 ===
 * Following function has been deprecated, please use \core\task\manager::run_from_cli().
index f936282..5be6098 100644 (file)
     background-color: white;
 }
 
-.path-mod-assign .gradingtable .c0 div.selectall {
-    margin-left: 7px;
-}
-
 .path-mod-assign .gradingtable .yui3-menu ul {
     margin: 0;
 }
index 9419789..5d00eaf 100644 (file)
@@ -159,41 +159,40 @@ $calendarEventColor: #0d5ca1 !default;
                         vertical-align: initial;
                     }
 
-                    .badge {
-                        &.badge-circle {
-                            width: 12px;
-                            height: 12px;
-                            border-radius: 6px;
-                            vertical-align: middle;
-
-                            &.calendar_event_category {
-                                background-color: $calendarEventCategoryColor;
-                                border: $calendarEventCategoryBorder;
-                            }
-                            &.calendar_event_course {
-                                background-color: $calendarEventCourseColor;
-                                border: $calendarEventCourseBorder;
-                            }
+                    .calendar-circle {
+                        width: 12px;
+                        height: 12px;
+                        border-radius: 6px;
+                        vertical-align: middle;
+                        display: inline-block;
 
-                            &.calendar_event_site {
-                                background-color: $calendarEventGlobalColor;
-                                border: $calendarEventGlobalBorder;
-                            }
+                        &.calendar_event_category {
+                            background-color: $calendarEventCategoryColor;
+                            border: $calendarEventCategoryBorder;
+                        }
+                        &.calendar_event_course {
+                            background-color: $calendarEventCourseColor;
+                            border: $calendarEventCourseBorder;
+                        }
 
-                            &.calendar_event_group {
-                                background-color: $calendarEventGroupColor;
-                                border: $calendarEventGroupBorder;
-                            }
+                        &.calendar_event_site {
+                            background-color: $calendarEventGlobalColor;
+                            border: $calendarEventGlobalBorder;
+                        }
 
-                            &.calendar_event_user {
-                                background-color: $calendarEventUserColor;
-                                border: $calendarEventUserBorder;
-                            }
+                        &.calendar_event_group {
+                            background-color: $calendarEventGroupColor;
+                            border: $calendarEventGroupBorder;
+                        }
 
-                            &.calendar_event_other {
-                                background-color: $calendarEventOtherColor;
-                                border: $calendarEventOtherBorder;
-                            }
+                        &.calendar_event_user {
+                            background-color: $calendarEventUserColor;
+                            border: $calendarEventUserBorder;
+                        }
+
+                        &.calendar_event_other {
+                            background-color: $calendarEventOtherColor;
+                            border: $calendarEventOtherBorder;
                         }
                     }
                 }
index 436ff18..198e064 100644 (file)
@@ -12856,27 +12856,28 @@ input[disabled] {
           margin-left: 0.25em;
           margin-right: 0.25em;
           vertical-align: initial; }
-        .path-calendar .maincalendar .calendarmonth ul li .badge.badge-circle {
+        .path-calendar .maincalendar .calendarmonth ul li .calendar-circle {
           width: 12px;
           height: 12px;
           border-radius: 6px;
-          vertical-align: middle; }
-          .path-calendar .maincalendar .calendarmonth ul li .badge.badge-circle.calendar_event_category {
+          vertical-align: middle;
+          display: inline-block; }
+          .path-calendar .maincalendar .calendarmonth ul li .calendar-circle.calendar_event_category {
             background-color: #e0cbe0;
             border: 2px solid #9e619f; }
-          .path-calendar .maincalendar .calendarmonth ul li .badge.badge-circle.calendar_event_course {
+          .path-calendar .maincalendar .calendarmonth ul li .calendar-circle.calendar_event_course {
             background-color: #ffd3bd;
             border: 2px solid #d34600; }
-          .path-calendar .maincalendar .calendarmonth ul li .badge.badge-circle.calendar_event_site {
+          .path-calendar .maincalendar .calendarmonth ul li .calendar-circle.calendar_event_site {
             background-color: #d6f8cd;
             border: 2px solid #2b8713; }
-          .path-calendar .maincalendar .calendarmonth ul li .badge.badge-circle.calendar_event_group {
+          .path-calendar .maincalendar .calendarmonth ul li .calendar-circle.calendar_event_group {
             background-color: #fee7ae;
             border: 2px solid #9a6e02; }
-          .path-calendar .maincalendar .calendarmonth ul li .badge.badge-circle.calendar_event_user {
+          .path-calendar .maincalendar .calendarmonth ul li .calendar-circle.calendar_event_user {
             background-color: #dce7ec;
             border: 2px solid #4e7c91; }
-          .path-calendar .maincalendar .calendarmonth ul li .badge.badge-circle.calendar_event_other {
+          .path-calendar .maincalendar .calendarmonth ul li .calendar-circle.calendar_event_other {
             background-color: #ced4da;
             border: 2px solid #687889; }
     .path-calendar .maincalendar .calendarmonth td {
index 9b4e42e..4c25504 100644 (file)
@@ -13070,27 +13070,28 @@ input[disabled] {
           margin-left: 0.25em;
           margin-right: 0.25em;
           vertical-align: initial; }
-        .path-calendar .maincalendar .calendarmonth ul li .badge.badge-circle {
+        .path-calendar .maincalendar .calendarmonth ul li .calendar-circle {
           width: 12px;
           height: 12px;
           border-radius: 6px;
-          vertical-align: middle; }
-          .path-calendar .maincalendar .calendarmonth ul li .badge.badge-circle.calendar_event_category {
+          vertical-align: middle;
+          display: inline-block; }
+          .path-calendar .maincalendar .calendarmonth ul li .calendar-circle.calendar_event_category {
             background-color: #e0cbe0;
             border: 2px solid #9e619f; }
-          .path-calendar .maincalendar .calendarmonth ul li .badge.badge-circle.calendar_event_course {
+          .path-calendar .maincalendar .calendarmonth ul li .calendar-circle.calendar_event_course {
             background-color: #ffd3bd;
             border: 2px solid #d34600; }
-          .path-calendar .maincalendar .calendarmonth ul li .badge.badge-circle.calendar_event_site {
+          .path-calendar .maincalendar .calendarmonth ul li .calendar-circle.calendar_event_site {
             background-color: #d6f8cd;
             border: 2px solid #2b8713; }
-          .path-calendar .maincalendar .calendarmonth ul li .badge.badge-circle.calendar_event_group {
+          .path-calendar .maincalendar .calendarmonth ul li .calendar-circle.calendar_event_group {
             background-color: #fee7ae;
             border: 2px solid #9a6e02; }
-          .path-calendar .maincalendar .calendarmonth ul li .badge.badge-circle.calendar_event_user {
+          .path-calendar .maincalendar .calendarmonth ul li .calendar-circle.calendar_event_user {
             background-color: #dce7ec;
             border: 2px solid #4e7c91; }
-          .path-calendar .maincalendar .calendarmonth ul li .badge.badge-circle.calendar_event_other {
+          .path-calendar .maincalendar .calendarmonth ul li .calendar-circle.calendar_event_other {
             background-color: #ced4da;
             border: 2px solid #687889; }
     .path-calendar .maincalendar .calendarmonth td {
index 2acf8a5..bb7681d 100644 (file)
@@ -29,7 +29,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$version  = 2020102100.00;              // YYYYMMDD      = weekly release date of this DEV branch.
+$version  = 2020102100.01;              // YYYYMMDD      = weekly release date of this DEV branch.
                                         //         RR    = release increments - 00 in DEV branches.
                                         //           .XX = incremental changes.
 $release  = '3.10dev+ (Build: 20201021)';// Human-friendly version name