Merge branch 'install_master' of https://git.in.moodle.com/amosbot/moodle-install
authorEloy Lafuente (stronk7) <stronk7@moodle.org>
Thu, 25 Jun 2020 16:05:53 +0000 (18:05 +0200)
committerEloy Lafuente (stronk7) <stronk7@moodle.org>
Thu, 25 Jun 2020 16:05:53 +0000 (18:05 +0200)
32 files changed:
admin/settings/users.php
admin/tool/behat/cli/util_single_run.php
admin/tool/task/renderer.php
admin/tool/task/tests/behat/manage_tasks.feature
contentbank/amd/build/actions.min.js
contentbank/amd/build/actions.min.js.map
contentbank/amd/src/actions.js
contentbank/index.php
contentbank/view.php
course/amd/build/activitychooser.min.js
course/amd/build/activitychooser.min.js.map
course/amd/src/activitychooser.js
course/format/renderer.php
course/renderer.php
course/tests/behat/paged_course_navigation.feature
lang/en/moodle.php
lib/behat/classes/util.php
lib/db/upgrade.php
lib/outputlib.php
lib/questionlib.php
lib/templates/paged_content.mustache
lib/templates/paged_content_paging_bar.mustache
lib/templates/paged_content_paging_bar_item.mustache
lib/tests/behat/behat_hooks.php
lib/yui/build/moodle-core-chooserdialogue/moodle-core-chooserdialogue-debug.js
lib/yui/build/moodle-core-chooserdialogue/moodle-core-chooserdialogue-min.js
lib/yui/build/moodle-core-chooserdialogue/moodle-core-chooserdialogue.js
lib/yui/src/chooserdialogue/js/chooserdialogue.js
theme/boost/scss/moodle/core.scss
theme/boost/style/moodle.css
theme/classic/style/moodle.css
version.php

index 0b7c4a4..c54a169 100644 (file)
@@ -261,10 +261,28 @@ if ($hassiteconfig) {
     $temp->add($setting);
 
     // See {@link https://gdpr-info.eu/art-8-gdpr/}.
+    // See {@link https://www.betterinternetforkids.eu/web/portal/practice/awareness/detail?articleId=3017751}.
     $ageofdigitalconsentmap = implode(PHP_EOL, [
         '*, 16',
         'AT, 14',
+        'BE, 13',
+        'BG, 14',
+        'CY, 14',
+        'CZ, 15',
+        'DK, 13',
+        'EE, 13',
         'ES, 14',
+        'FI, 13',
+        'FR, 15',
+        'GB, 13',
+        'GR, 15',
+        'IT, 14',
+        'LT, 14',
+        'LV, 13',
+        'MT, 13',
+        'NO, 13',
+        'PT, 13',
+        'SE, 13',
         'US, 13'
     ]);
     $setting = new admin_setting_agedigitalconsentmap('agedigitalconsentmap',
index 967fde3..f0a3650 100644 (file)
@@ -164,6 +164,8 @@ if ($options['install']) {
         mtrace("Acceptance tests site installed");
     }
 
+    // Note: Do not build the themes here. This is done during the 'enable' stage.
+
 } else if ($options['drop']) {
     // Ensure no tests are running.
     test_lock::acquire('behat');
@@ -182,6 +184,10 @@ if ($options['install']) {
     // Enable test mode.
     behat_util::start_test_mode($options['add-core-features-to-theme'], $options['optimize-runs'], $parallel, $run);
 
+    // Themes are only built in the 'enable' command.
+    behat_util::build_themes();
+    mtrace("Testing environment themes built");
+
     // This is only displayed once for parallel install.
     if (empty($run)) {
         // Notify user that 2.5 profile has been converted to 3.5.
index a003eab..ec0bb0c 100644 (file)
@@ -48,6 +48,7 @@ class tool_task_renderer extends plugin_renderer_base {
         $showloglink = \core\task\logmanager::has_log_report();
 
         $table = new html_table();
+        $table->caption = get_string('scheduledtasks', 'tool_task');
         $table->head = [
             get_string('name'),
             get_string('component', 'tool_task'),
@@ -180,7 +181,7 @@ class tool_task_renderer extends plugin_renderer_base {
         $plugininfo->init_display_name();
 
         $componentname = $plugininfo->displayname;
-        if (!$plugininfo->is_enabled()) {
+        if ($plugininfo->is_enabled() === false) {
             $componentname .= ' ' . html_writer::span(
                             get_string('disabled', 'tool_task'), 'badge badge-secondary');
         }
index 160451d..dd27d85 100644 (file)
@@ -65,3 +65,9 @@ Feature: Manage scheduled tasks
       | Name               | Component    | Minute | Hour | Day | Day of week | Month |
       | Log table cleanup  | Standard log | */5    | 1    | 2   | 4           | 3     |
     And I should see "Log table cleanup" in the "tr.table-primary" "css_element"
+
+  Scenario: Disabled plugin's tasks are labelled as disabled too
+    When "CAS users sync job \auth_cas\task\sync_task" row "Next run" column of "Scheduled tasks" table should contain "Plugin disabled"
+    Then "CAS users sync job \auth_cas\task\sync_task" row "Component" column of "Scheduled tasks" table should contain "Disabled"
+    And "Background processing for scheduled allocation \workshopallocation_scheduled\task\cron_task" row "Next run" column of "Scheduled tasks" table should not contain "Plugin disabled"
+    And "Background processing for scheduled allocation \workshopallocation_scheduled\task\cron_task" row "Component" column of "Scheduled tasks" table should not contain "Disabled"
index 4d78f53..237c664 100644 (file)
Binary files a/contentbank/amd/build/actions.min.js and b/contentbank/amd/build/actions.min.js differ
index 6e5344e..79956ea 100644 (file)
Binary files a/contentbank/amd/build/actions.min.js.map and b/contentbank/amd/build/actions.min.js.map differ
index 561cb99..1776292 100644 (file)
@@ -176,10 +176,10 @@ function($, Ajax, Notification, Str, Templates, Url, ModalFactory, ModalEvents)
         var requestType = 'success';
         Ajax.call([request])[0].then(function(data) {
             if (data.result) {
-                return Str.get_string('contentdeleted', 'core_contentbank');
+                return 'contentdeleted';
             }
             requestType = 'error';
-            return Str.get_string('contentnotdeleted', 'core_contentbank');
+            return 'contentnotdeleted';
 
         }).done(function(message) {
             var params = {
@@ -212,10 +212,10 @@ function($, Ajax, Notification, Str, Templates, Url, ModalFactory, ModalEvents)
         var requestType = 'success';
         Ajax.call([request])[0].then(function(data) {
             if (data) {
-                return Str.get_string('contentrenamed', 'core_contentbank');
+                return 'contentrenamed';
             }
             requestType = 'error';
-            return Str.get_string('contentnotrenamed', 'core_contentbank');
+            return 'contentnotrenamed';
 
         }).then(function(message) {
             var params = null;
index bf8de2b..33eff29 100644 (file)
@@ -32,8 +32,8 @@ $context = context::instance_by_id($contextid, MUST_EXIST);
 
 require_capability('moodle/contentbank:access', $context);
 
-$statusmsg = optional_param('statusmsg', '', PARAM_RAW);
-$errormsg = optional_param('errormsg', '', PARAM_RAW);
+$statusmsg = optional_param('statusmsg', '', PARAM_ALPHANUMEXT);
+$errormsg = optional_param('errormsg', '', PARAM_ALPHANUMEXT);
 
 $title = get_string('contentbank');
 \core_contentbank\helper::get_page_ready($context, $title);
@@ -98,9 +98,11 @@ echo $OUTPUT->header();
 echo $OUTPUT->box_start('generalbox');
 
 // If needed, display notifications.
-if ($errormsg !== '') {
+if ($errormsg !== '' && get_string_manager()->string_exists($errormsg, 'core_contentbank')) {
+    $errormsg = get_string($errormsg, 'core_contentbank');
     echo $OUTPUT->notification($errormsg);
-} else if ($statusmsg !== '') {
+} else if ($statusmsg !== '' && get_string_manager()->string_exists($statusmsg, 'core_contentbank')) {
+    $statusmsg = get_string($statusmsg, 'core_contentbank');
     echo $OUTPUT->notification($statusmsg, 'notifysuccess');
 }
 
index 9f2a8d1..5fd66d1 100644 (file)
@@ -35,8 +35,8 @@ $record = $DB->get_record('contentbank_content', ['id' => $id], '*', MUST_EXIST)
 $context = context::instance_by_id($record->contextid, MUST_EXIST);
 require_capability('moodle/contentbank:access', $context);
 
-$statusmsg = optional_param('statusmsg', '', PARAM_RAW);
-$errormsg = optional_param('errormsg', '', PARAM_RAW);
+$statusmsg = optional_param('statusmsg', '', PARAM_ALPHANUMEXT);
+$errormsg = optional_param('errormsg', '', PARAM_ALPHANUMEXT);
 
 $returnurl = new \moodle_url('/contentbank/index.php', ['contextid' => $context->id]);
 $plugin = core_plugin_manager::instance()->get_plugin_info($record->contenttype);
@@ -111,9 +111,11 @@ $PAGE->add_header_action(html_writer::div(
 echo $OUTPUT->header();
 
 // If needed, display notifications.
-if ($errormsg !== '') {
+if ($errormsg !== '' && get_string_manager()->string_exists($errormsg, 'core_contentbank')) {
+    $errormsg = get_string($errormsg, 'core_contentbank');
     echo $OUTPUT->notification($errormsg);
-} else if ($statusmsg !== '') {
+} else if ($statusmsg !== '' && get_string_manager()->string_exists($statusmsg, 'core_contentbank')) {
+    $statusmsg = get_string($statusmsg, 'core_contentbank');
     echo $OUTPUT->notification($statusmsg, 'notifysuccess');
 }
 if ($contenttype->can_access()) {
index 27aebcf..b49f3dc 100644 (file)
Binary files a/course/amd/build/activitychooser.min.js and b/course/amd/build/activitychooser.min.js differ
index 055d5ac..a409f76 100644 (file)
Binary files a/course/amd/build/activitychooser.min.js.map and b/course/amd/build/activitychooser.min.js.map differ
index 176ed99..5de0576 100644 (file)
@@ -136,7 +136,7 @@ const registerListenerEvents = (courseId, chooserConfig) => {
                 const data = await fetchModuleData();
 
                 // Apply the section id to all the module instance links.
-                const builtModuleData = sectionIdMapper(data, caller.dataset.sectionid);
+                const builtModuleData = sectionIdMapper(data, caller.dataset.sectionid, caller.dataset.sectionreturnid);
 
                 ChooserDialogue.displayChooser(
                     sectionModal,
@@ -161,13 +161,14 @@ const registerListenerEvents = (courseId, chooserConfig) => {
  * @method sectionIdMapper
  * @param {Object} webServiceData Our original data from the Web service call
  * @param {Number} id The ID of the section we need to append to the links
+ * @param {Number|null} sectionreturnid The ID of the section return we need to append to the links
  * @return {Array} [modules] with URL's built
  */
-const sectionIdMapper = (webServiceData, id) => {
+const sectionIdMapper = (webServiceData, id, sectionreturnid) => {
     // We need to take a fresh deep copy of the original data as an object is a reference type.
     const newData = JSON.parse(JSON.stringify(webServiceData));
     newData.content_items.forEach((module) => {
-        module.link += '&section=' + id;
+        module.link += '&section=' + id + '&sr=' + (sectionreturnid ?? 0);
     });
     return newData.content_items;
 };
index 6fbe141..b5884c3 100644 (file)
@@ -203,7 +203,8 @@ abstract class format_section_renderer_base extends plugin_renderer_base {
             'class' => 'section main clearfix'.$sectionstyle,
             'role' => 'region',
             'aria-labelledby' => "sectionid-{$section->id}-title",
-            'data-sectionid' => $section->section
+            'data-sectionid' => $section->section,
+            'data-sectionreturnid' => $sectionreturn
         ]);
 
         $leftcontent = $this->section_left_content($section, $course, $onsectionpage);
index bb7b3b9..da82415 100644 (file)
@@ -376,6 +376,7 @@ class core_course_renderer extends plugin_renderer_base {
                     'class' => 'section-modchooser-link btn btn-link',
                     'data-action' => 'open-chooser',
                     'data-sectionid' => $section,
+                    'data-sectionreturnid' => $sectionreturn,
                 ]
             );
             $ajaxcontrol .= html_writer::end_tag('div');
index 92fd475..04b7b15 100644 (file)
@@ -38,6 +38,29 @@ Feature: Course paged mode
       | topics | "Topic 1" | "Topic 2" | "Topic 3" | "Topic 0" | "Topic 4" |
       | weeks | "1 January - 7 January" | "8 January - 14 January" | "15 January - 21 January" | "25 December - 31 December" | "22 January - 28 January" |
 
+  @javascript
+  Scenario Outline: Paged section redirect after creating an activity
+    Given the following "courses" exist:
+      | fullname | shortname | category | format | coursedisplay | numsections | startdate |
+      | Course 1 | C1        | 0        | <courseformat> | 1     | 3           | 0         |
+    And I log in as "admin"
+    And I am on "Course 1" course homepage with editing mode on
+    And I click on <section1> "link" in the <section1> "section"
+    And I should see <section1> in the "div.single-section" "css_element"
+    And I should see <section2> in the ".single-section span.mdl-right" "css_element"
+    And I should not see <prevunexistingsection> in the ".single-section" "css_element"
+    When I add a "Chat" to section "1" and I fill the form with:
+      | Name of this chat room | Chat room |
+      | Description | Chat description |
+    Then I should see <section1> in the "div.single-section" "css_element"
+    And I should see <section2> in the ".single-section span.mdl-right" "css_element"
+    And I should not see <prevunexistingsection> in the ".single-section" "css_element"
+
+    Examples:
+      | courseformat | section1 | section2 | prevunexistingsection |
+      | topics       | "Topic 1" | "Topic 2" | "Topic 0"          |
+      | weeks        | "1 January - 7 January" | "8 January - 14 January" | "25 December - 31 December" |
+
   Scenario Outline: Weekly and topics course formats with Javascript disabled
     Given the following "courses" exist:
       | fullname | shortname | category | format | coursedisplay | numsections | startdate |
index 7672db6..24d2c03 100644 (file)
@@ -854,6 +854,7 @@ $string['first'] = 'First';
 $string['firstaccess'] = 'First access';
 $string['firstname'] = 'First name';
 $string['firstnamephonetic'] = 'First name - phonetic';
+$string['firstpage'] = 'First page';
 $string['firstsiteaccess'] = 'First access to site';
 $string['firsttime'] = 'Is this your first time here?';
 $string['folder'] = 'Folder';
@@ -1133,6 +1134,7 @@ $string['lastlogin'] = 'Last login';
 $string['lastmodified'] = 'Last modified';
 $string['lastname'] = 'Surname';
 $string['lastnamephonetic'] = 'Surname - phonetic';
+$string['lastpage'] = 'Last page';
 $string['lastsiteaccess'] = 'Last access to site';
 $string['lastyear'] = 'Last year';
 $string['latestlanguagepack'] = 'Check for latest language pack on moodle.org';
@@ -1417,6 +1419,7 @@ Cheers from the \'{$a->sitename}\' administrator,
 $string['newusers'] = 'New users';
 $string['newwindow'] = 'New window';
 $string['next'] = 'Next';
+$string['nextpage'] = 'Next page';
 $string['nextsection'] = 'Next section';
 $string['no'] = 'No';
 $string['noblockstoaddhere'] = 'There are no blocks that you can add to this page.';
@@ -1600,6 +1603,7 @@ $string['preview'] = 'Preview';
 $string['previeworchoose'] = 'Preview or choose a theme';
 $string['previous'] = 'Previous';
 $string['previouslyselectedusers'] = 'Previously selected users not matching \'{$a}\'';
+$string['previouspage'] = 'Previous page';
 $string['previoussection'] = 'Previous section';
 $string['primaryadminsetup'] = 'Setup administrator account';
 $string['privacy:metadata:config_log'] = 'The log of configuration changes.';
index 267406b..b24ea48 100644 (file)
@@ -32,6 +32,7 @@ require_once(__DIR__ . '/behat_config_manager.php');
 
 require_once(__DIR__ . '/../../filelib.php');
 require_once(__DIR__ . '/../../clilib.php');
+require_once(__DIR__ . '/../../csslib.php');
 
 use Behat\Mink\Session;
 use Behat\Mink\Exception\ExpectationException;
@@ -131,6 +132,35 @@ class behat_util extends testing_util {
         self::store_database_state();
     }
 
+    /**
+     * Build theme CSS.
+     */
+    public static function build_themes() {
+        global $CFG;
+        require_once("{$CFG->libdir}/outputlib.php");
+
+        $themenames = array_keys(\core_component::get_plugin_list('theme'));
+
+        // Load the theme configs.
+        $themeconfigs = array_map(function($themename) {
+            return \theme_config::load($themename);
+        }, $themenames);
+
+        // Build the list of themes and cache them in local cache.
+        $themes = theme_build_css_for_themes($themeconfigs, ['ltr'], true);
+
+        $framework = self::get_framework();
+        $storageroot = self::get_dataroot() . "/{$framework}/themedata";
+
+        foreach ($themes as $themename => $themedata) {
+            $dirname = "{$storageroot}/{$themename}";
+            check_dir_exists($dirname);
+            foreach ($themedata as $direction => $css) {
+                file_put_contents("{$dirname}/{$direction}.css", $css);
+            }
+        }
+    }
+
     /**
      * Drops dataroot and remove test database tables
      * @throws coding_exception
@@ -397,6 +427,37 @@ class behat_util extends testing_util {
         initialise_cfg();
     }
 
+    /**
+     * Restore theme CSS stored during behat setup.
+     */
+    public static function restore_saved_themes(): void {
+        global $CFG;
+
+        $themerev = theme_get_revision();
+
+        $framework = self::get_framework();
+        $storageroot = self::get_dataroot() . "/{$framework}/themedata";
+        $themenames = array_keys(\core_component::get_plugin_list('theme'));
+        $directions = ['ltr', 'rtl'];
+
+        $themeconfigs = array_map(function($themename) {
+            return \theme_config::load($themename);
+        }, $themenames);
+
+        foreach ($themeconfigs as $themeconfig) {
+            $themename = $themeconfig->name;
+            $themesubrev = theme_get_sub_revision_for_theme($themename);
+
+            $dirname = "{$storageroot}/{$themename}";
+            foreach ($directions as $direction) {
+                $cssfile = "{$dirname}/{$direction}.css";
+                if (file_exists($cssfile)) {
+                    $themeconfig->set_css_content_cache(file_get_contents($cssfile));
+                }
+            }
+        }
+    }
+
     /**
      * Pause execution immediately.
      *
index 53fa76a..dcc2f48 100644 (file)
@@ -2443,6 +2443,48 @@ function xmldb_main_upgrade($oldversion) {
 
     // Automatically generated Moodle v3.9.0 release upgrade line.
     // Put any upgrade step following this.
+    if ($oldversion < 2020061500.02) {
+        // Update default digital age consent map according to the current legislation on each country.
+
+        // The default age of digital consent map for 38 and below.
+        $oldageofdigitalconsentmap = implode(PHP_EOL, [
+            '*, 16',
+            'AT, 14',
+            'ES, 14',
+            'US, 13'
+        ]);
+
+        // Check if the current age of digital consent map matches the old one.
+        if (get_config('moodle', 'agedigitalconsentmap') === $oldageofdigitalconsentmap) {
+            // If the site is still using the old defaults, upgrade to the new default.
+            $ageofdigitalconsentmap = implode(PHP_EOL, [
+                '*, 16',
+                'AT, 14',
+                'BE, 13',
+                'BG, 14',
+                'CY, 14',
+                'CZ, 15',
+                'DK, 13',
+                'EE, 13',
+                'ES, 14',
+                'FI, 13',
+                'FR, 15',
+                'GB, 13',
+                'GR, 15',
+                'IT, 14',
+                'LT, 14',
+                'LV, 13',
+                'MT, 13',
+                'NO, 13',
+                'PT, 13',
+                'SE, 13',
+                'US, 13'
+            ]);
+            set_config('agedigitalconsentmap', $ageofdigitalconsentmap);
+        }
+
+        upgrade_main_savepoint(true, 2020061500.02);
+    }
 
     return true;
 }
index e7cb41e..fb4a29c 100644 (file)
@@ -179,12 +179,13 @@ function theme_get_css_filename($themename, $globalrevision, $themerevision, $di
  * @param theme_config[] $themeconfigs An array of theme_config instances.
  * @param array          $directions   Must be a subset of ['rtl', 'ltr'].
  * @param bool           $cache        Should the generated files be stored in local cache.
+ * @return array         The built theme content in a multi-dimensional array of name => direction => content
  */
-function theme_build_css_for_themes($themeconfigs = [], $directions = ['rtl', 'ltr'], $cache = true) {
+function theme_build_css_for_themes($themeconfigs = [], $directions = ['rtl', 'ltr'], $cache = true): array {
     global $CFG;
 
     if (empty($themeconfigs)) {
-        return;
+        return [];
     }
 
     require_once("{$CFG->libdir}/csslib.php");
@@ -212,7 +213,7 @@ function theme_build_css_for_themes($themeconfigs = [], $directions = ['rtl', 'l
                 css_store_css($themeconfig, $filename, $themecss[$direction]);
             }
         }
-        $themescss[] = $themecss;
+        $themescss[$themeconfig->name] = $themecss;
 
         if ($cache) {
             // Only update the theme revision after we've successfully created the
index 470b3be..8c89e04 100644 (file)
@@ -1813,6 +1813,8 @@ function question_get_question_capabilities() {
         'moodle/question:useall',
         'moodle/question:movemine',
         'moodle/question:moveall',
+        'moodle/question:tagmine',
+        'moodle/question:tagall',
     );
 }
 
index c1b7202..4111ea8 100644 (file)
     Example context (json):
     {
         "pagingbar": {
-            "itemsperpage": 1,
+            "showitemsperpageselector": true,
+            "itemsperpage": [
+                { "value": 5, "active": false },
+                { "value": 10, "active": true },
+                { "value": 15, "active": false }
+            ],
             "previous": true,
             "next": true,
             "first": true,
             "last": true,
+            "barsize": 5,
             "pages": [
                 {
                     "page": "1",
                 {
                     "url": "#",
                     "page": "2"
+                },
+                {
+                    "url": "#",
+                    "page": "3"
+                },
+                {
+                    "url": "#",
+                    "page": "4"
+                },
+                {
+                    "url": "#",
+                    "page": "5"
+                },
+                {
+                    "url": "#",
+                    "page": "6"
+                },
+                {
+                    "url": "#",
+                    "page": "7"
                 }
             ]
         },
             {
                 "page": 2,
                 "content": "<p>Some page 2 content</p>"
+            },
+            {
+                "page": 3,
+                "content": "<p>Some page 3 content</p>"
+            },
+            {
+                "page": 4,
+                "content": "<p>Some page 4 content</p>"
+            },
+            {
+                "page": 5,
+                "content": "<p>Some page 5 content</p>"
+            },
+            {
+                "page": 6,
+                "content": "<p>Some page 6 content</p>"
+            },
+            {
+                "page": 7,
+                "content": "<p>Some page 7 content</p>"
             }
         ]
     }
index b0b84f1..f8af357 100644 (file)
 
     Example context (json):
     {
-        "itemsperpage": 2,
+        "showitemsperpageselector": true,
+        "itemsperpage": [
+            { "value": 5, "active": false },
+            { "value": 10, "active": true },
+            { "value": 15, "active": false }
+        ],
         "previous": true,
         "next": true,
         "first": true,
@@ -89,7 +94,8 @@
                         <a
                             class="dropdown-item {{#active}}active{{/active}}"
                             href="#"
-                            data-limit={{value}}
+                            data-limit="{{value}}"
+                            role="menuitem"
                             {{#active}}aria-current="true"{{/active}}
                         >
                             {{#value}}{{.}}{{/value}}
         <ul class="pagination mb-0">
             {{#previous}}
                 {{< core/paged_content_paging_bar_item }}
+                    {{$linkattributes}}aria-label="{{#str}}previouspage{{/str}}"{{/linkattributes}}
                     {{$item-content}}
                         <span class="icon-no-margin dir-rtl-hide" aria-hidden="true">{{#pix}} i/previous, core {{/pix}}</span>
                         <span class="icon-no-margin dir-ltr-hide" aria-hidden="true">{{#pix}} i/next, core {{/pix}}</span>
             {{/previous}}
             {{#first}}
                 {{< core/paged_content_paging_bar_item }}
+                    {{$linkattributes}}aria-label="{{#str}}firstpage{{/str}}"{{/linkattributes}}
                     {{$item-content}}
-                        <span aria-hidden="true">{{#str}}first{{/str}}</span>
+                        {{#str}}first{{/str}}
                     {{/item-content}}
                     {{$attributes}}data-control="first"{{/attributes}}
                 {{/ core/paged_content_paging_bar_item }}
             {{/first}}
             {{#barsize}}
                 {{< core/paged_content_paging_bar_item }}
+                    {{$linkattributes}}aria-hidden="true"{{/linkattributes}}
                     {{$item-content}}
-                        <span aria-hidden="true">&hellip;</span>
+                        &hellip;
                     {{/item-content}}
                     {{$attributes}}data-dots="beginning"{{/attributes}}
                 {{/ core/paged_content_paging_bar_item }}
             {{/pages}}
             {{#barsize}}
                 {{< core/paged_content_paging_bar_item }}
+                    {{$linkattributes}}aria-hidden="true"{{/linkattributes}}
                     {{$item-content}}
-                        <span aria-hidden="true">&hellip;</span>
+                        &hellip;
                     {{/item-content}}
                     {{$attributes}}data-dots="ending"{{/attributes}}
                 {{/ core/paged_content_paging_bar_item }}
             {{/barsize}}
             {{#last}}
                 {{< core/paged_content_paging_bar_item }}
+                    {{$linkattributes}}aria-label="{{#str}}lastpage{{/str}}"{{/linkattributes}}
                     {{$item-content}}
-                        <span aria-hidden="true">{{#str}}last{{/str}}</span>
+                        {{#str}}last{{/str}}
                     {{/item-content}}
                     {{$attributes}}data-control="last"{{/attributes}}
                 {{/ core/paged_content_paging_bar_item }}
             {{/last}}
             {{#next}}
                 {{< core/paged_content_paging_bar_item }}
+                    {{$linkattributes}}aria-label="{{#str}}nextpage{{/str}}"{{/linkattributes}}
                     {{$item-content}}
                         <span class="icon-no-margin dir-rtl-hide" aria-hidden="true">{{#pix}} i/next, core {{/pix}}</span>
                         <span class="icon-no-margin dir-ltr-hide" aria-hidden="true">{{#pix}} i/previous, core {{/pix}}</span>
index e3ef1a2..ed50b10 100644 (file)
@@ -33,7 +33,7 @@
 
     <a href="{{#url}}{{.}}{{/url}}{{^url}}#{{/url}}"
        class="page-link"
-       data-region="page-link">
+       data-region="page-link" {{$linkattributes}}aria-label="{{#str}}pagea, moodle, {{page}}{{/str}}"{{/linkattributes}}>
         {{$item-content}}
             {{{page}}}
         {{/item-content}}
index c7b53df..115765a 100644 (file)
@@ -367,6 +367,16 @@ class behat_hooks extends behat_base {
         behat_util::reset_all_data();
         error_reporting($errorlevel);
 
+        if ($this->running_javascript()) {
+            // Fetch the user agent.
+            // This isused to choose between the SVG/Non-SVG versions of themes.
+            $useragent = $this->getSession()->evaluateScript('return navigator.userAgent;');
+            \core_useragent::instance(true, $useragent);
+
+            // Restore the saved themes.
+            behat_util::restore_saved_themes();
+        }
+
         // Assign valid data to admin user (some generator-related code needs a valid user).
         $user = $DB->get_record('user', array('username' => 'admin'));
         \core\session\manager::set_user($user);
index 4ccb899..9d72b87 100644 (file)
Binary files a/lib/yui/build/moodle-core-chooserdialogue/moodle-core-chooserdialogue-debug.js and b/lib/yui/build/moodle-core-chooserdialogue/moodle-core-chooserdialogue-debug.js differ
index 90a6b75..9af91ef 100644 (file)
Binary files a/lib/yui/build/moodle-core-chooserdialogue/moodle-core-chooserdialogue-min.js and b/lib/yui/build/moodle-core-chooserdialogue/moodle-core-chooserdialogue-min.js differ
index 4ccb899..9d72b87 100644 (file)
Binary files a/lib/yui/build/moodle-core-chooserdialogue/moodle-core-chooserdialogue.js and b/lib/yui/build/moodle-core-chooserdialogue/moodle-core-chooserdialogue.js differ
index a2df1f7..ddefaa5 100644 (file)
@@ -214,7 +214,9 @@ Y.extend(CHOOSERDIALOGUE, Y.Base, {
             newheight, totalheight;
 
         if (this.panel.shouldResizeFullscreen()) {
-            // No custom sizing required for a fullscreen dialog.
+            dialogue.setStyle('maxHeight', '100%');
+            dialogue.setStyle('height', 'auto');
+            this.panel.makeResponsive();
             return;
         }
 
index ac58e81..4f10a37 100644 (file)
@@ -2603,6 +2603,9 @@ $picker-emojis-per-row: 7 !default;
         color: darken(theme-color-level($color, $alert-color-level), 10%);
     }
 }
+.alert a {
+    font-weight: $font-weight-bold;
+}
 
 @include media-breakpoint-down(sm) {
     #page-navbar {
index c9fc671..588a0de 100644 (file)
@@ -11746,6 +11746,9 @@ body.h5p-embed .h5pmessages {
 .alert-dark a {
   color: #040505; }
 
+.alert a {
+  font-weight: 700; }
+
 @media (max-width: 767.98px) {
   #page-navbar {
     width: 100%; }
index 7be6184..e9b5b03 100644 (file)
@@ -11960,6 +11960,9 @@ body.h5p-embed .h5pmessages {
 .alert-dark a {
   color: #040505; }
 
+.alert a {
+  font-weight: 700; }
+
 @media (max-width: 767.98px) {
   #page-navbar {
     width: 100%; }
index 54a463e..d0e7604 100644 (file)
@@ -29,7 +29,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$version  = 2020061500.01;              // YYYYMMDD      = weekly release date of this DEV branch.
+$version  = 2020061500.02;              // YYYYMMDD      = weekly release date of this DEV branch.
                                         //         RR    = release increments - 00 in DEV branches.
                                         //           .XX = incremental changes.
 $release  = '4.0dev (Build: 20200618)'; // Human-friendly version name