diff --git a/.grunt/babel-plugin-add-module-to-define.js b/.grunt/babel-plugin-add-module-to-define.js
index 2e76d31c3187c..804bb80fd2222 100644
--- a/.grunt/babel-plugin-add-module-to-define.js
+++ b/.grunt/babel-plugin-add-module-to-define.js
@@ -111,8 +111,22 @@ module.exports = ({template, types}) => {
if (!this.seenDefine && path.get('callee').isIdentifier({name: 'define'})) {
// We only want to modify the first instance of define that we find.
this.seenDefine = true;
+
// Get the Moodle component for the file being processed.
var moduleName = getModuleNameFromFileName(this.file.opts.filename);
+
+ // The function signature of `define()` is:
+ // define = function (name, deps, callback) {...}
+ // Ensure that if the moduel supplied its own name that it is replaced.
+ if (path.node.arguments.length > 0) {
+ // Ensure that there is only one name.
+ if (path.node.arguments[0].type === 'StringLiteral') {
+ // eslint-disable-next-line
+ console.log(`Replacing module name '${path.node.arguments[0].extra.rawValue}' with ${moduleName}`);
+ path.node.arguments.shift();
+ }
+ }
+
// Add the module name as the first argument to the define function.
path.node.arguments.unshift(types.stringLiteral(moduleName));
// Add a space after the define function in the built file so that previous versions
diff --git a/admin/purgecaches.php b/admin/purgecaches.php
index b43aa7777a2d6..c9658bde8504b 100644
--- a/admin/purgecaches.php
+++ b/admin/purgecaches.php
@@ -38,12 +38,11 @@
if ($data = $form->get_data()) {
// Valid request. Purge, and redirect the user back to where they came from.
- $selected = $data->purgeselectedoptions;
- purge_caches($selected);
-
if (isset($data->all)) {
+ purge_caches();
$message = get_string('purgecachesfinished', 'admin');
} else {
+ purge_caches($data->purgeselectedoptions);
$message = get_string('purgeselectedcachesfinished', 'admin');
}
diff --git a/admin/repository.php b/admin/repository.php
index 97c54efcc85e4..cf8143480e680 100644
--- a/admin/repository.php
+++ b/admin/repository.php
@@ -142,6 +142,8 @@ function repository_action_url($repository) {
$success = true;
if (!$repoid = $type->create()) {
$success = false;
+ } else {
+ add_to_config_log('repository_visibility', '', (int)$visible, $plugin);
}
$data = data_submitted();
}
@@ -184,14 +186,14 @@ function repository_action_url($repository) {
print_error('confirmsesskeybad', '', $baseurl);
}
$class = \core_plugin_manager::resolve_plugininfo_class('repository');
- $class::enable_plugin($repository, true);
+ $class::enable_plugin($repository, 1);
$return = true;
} else if ($action == 'hide') {
if (!confirm_sesskey()) {
print_error('confirmsesskeybad', '', $baseurl);
}
$class = \core_plugin_manager::resolve_plugininfo_class('repository');
- $class::enable_plugin($repository, false);
+ $class::enable_plugin($repository, 0);
$return = true;
} else if ($action == 'delete') {
$repositorytype = repository::get_type_by_typename($repository);
@@ -202,6 +204,8 @@ function repository_action_url($repository) {
}
if ($repositorytype->delete($downloadcontents)) {
+ // Include this information into config changes table.
+ add_to_config_log('repository_visibility', $repositorytype->get_visible(), '', $repository);
core_plugin_manager::reset_caches();
redirect($baseurl);
} else {
diff --git a/admin/search.php b/admin/search.php
index 88c2b35011e58..1bcf3c38c17cc 100644
--- a/admin/search.php
+++ b/admin/search.php
@@ -60,7 +60,6 @@
}
$PAGE->has_secondary_navigation_setter(false);
-$PAGE->set_primary_active_tab('siteadminnode');
// and finally, if we get here, then there are matching settings and we have to print a form
// to modify them
diff --git a/admin/templates/setting_configcolourpicker.mustache b/admin/templates/setting_configcolourpicker.mustache
index 50b7da1011b52..7b52846f9b4e7 100644
--- a/admin/templates/setting_configcolourpicker.mustache
+++ b/admin/templates/setting_configcolourpicker.mustache
@@ -48,6 +48,6 @@
{{#haspreviewconfig}}
-
+
{{/haspreviewconfig}}
diff --git a/admin/tool/behat/tests/behat/i_am_on_page.feature b/admin/tool/behat/tests/behat/i_am_on_page.feature
index 9c60a8b3da929..8f4abc23ac4a8 100644
--- a/admin/tool/behat/tests/behat/i_am_on_page.feature
+++ b/admin/tool/behat/tests/behat/i_am_on_page.feature
@@ -71,9 +71,9 @@ Feature: Use core page resolvers for the I am on the page steps
Then I should see ""
Examples:
- | description | identifier | shouldsee |
- | Admin page | "Admin notifications" | Check for available updates |
- | Home page | Homepage | Course overview |
+ | description | identifier | shouldsee |
+ | Admin page | "Admin notifications" | Check for available updates |
+ | Home page | Homepage | Calendar |
Scenario Outline: When I am on a named page logged in as
When I am on the page logged in as admin
@@ -82,4 +82,4 @@ Feature: Use core page resolvers for the I am on the page steps
Examples:
| description | identifier | shouldsee |
| Admin page | "Admin notifications" | Check for available updates |
- | Home page | Homepage | Course overview |
+ | Home page | Homepage | Calendar |
diff --git a/admin/tool/dataprivacy/tests/behat/dataexport.feature b/admin/tool/dataprivacy/tests/behat/dataexport.feature
index ce458a7df87d7..ff4f0f1354516 100644
--- a/admin/tool/dataprivacy/tests/behat/dataexport.feature
+++ b/admin/tool/dataprivacy/tests/behat/dataexport.feature
@@ -54,7 +54,7 @@ Feature: Data export from the privacy API
And I reload the page
And I should see "Download ready" in the "Victim User 1" "table_row"
And I open the action menu in "Victim User 1" "table_row"
- And following "Download" should download between "1" and "146000" bytes
+ And following "Download" should download between "1" and "150000" bytes
And the following config values are set as admin:
| privacyrequestexpiry | 1 | tool_dataprivacy |
And I wait "1" seconds
@@ -89,7 +89,7 @@ Feature: Data export from the privacy API
And I reload the page
And I should see "Download ready" in the "Export all of my personal data" "table_row"
And I open the action menu in "Victim User 1" "table_row"
- And following "Download" should download between "1" and "146000" bytes
+ And following "Download" should download between "1" and "150000" bytes
And the following config values are set as admin:
| privacyrequestexpiry | 1 | tool_dataprivacy |
@@ -126,7 +126,7 @@ Feature: Data export from the privacy API
And I reload the page
And I should see "Download ready" in the "Victim User 1" "table_row"
And I open the action menu in "Victim User 1" "table_row"
- And following "Download" should download between "1" and "146000" bytes
+ And following "Download" should download between "1" and "150000" bytes
And the following config values are set as admin:
| privacyrequestexpiry | 1 | tool_dataprivacy |
diff --git a/admin/tool/policy/templates/page_agreedocs.mustache b/admin/tool/policy/templates/page_agreedocs.mustache
index 60efaa6838e28..046eb8338adf6 100644
--- a/admin/tool/policy/templates/page_agreedocs.mustache
+++ b/admin/tool/policy/templates/page_agreedocs.mustache
@@ -134,9 +134,9 @@
{{# str }}somefieldsrequired, form, {{/ str }}
-
+
{{#cancancel}}
-
+
{{/cancancel}}
diff --git a/admin/tool/policy/tests/behat/acceptances.feature b/admin/tool/policy/tests/behat/acceptances.feature
index 85df22dbaa9a5..998049ca794c3 100644
--- a/admin/tool/policy/tests/behat/acceptances.feature
+++ b/admin/tool/policy/tests/behat/acceptances.feature
@@ -36,7 +36,7 @@ Feature: Viewing acceptances reports and accepting on behalf of other users
And I press "Next"
And I set the field "I agree to the This site policy" to "1"
And I press "Next"
- And I should see "Course overview"
+ And I should see "Calendar"
And I log out
And I log in as "manager"
And I press "Next"
@@ -82,7 +82,7 @@ Feature: Viewing acceptances reports and accepting on behalf of other users
And I press "Next"
And I set the field "I agree to the This site policy" to "1"
And I press "Next"
- And I should see "Course overview"
+ And I should see "Calendar"
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
And I click on "1 of 4 (25%)" "link" in the "This site policy" "table_row"
And I click on "Accept This site policy" "link" in the "User One" "table_row"
@@ -111,7 +111,7 @@ Feature: Viewing acceptances reports and accepting on behalf of other users
And I set the field "I agree to the This site policy" to "1"
And I set the field "I agree to the This privacy policy" to "1"
And I press "Next"
- And I should see "Course overview"
+ And I should see "Calendar"
And I log out
And I log in as "manager"
And I press "Next"
@@ -300,7 +300,7 @@ Feature: Viewing acceptances reports and accepting on behalf of other users
And I press "Next"
And I set the field "I agree to the This site policy" to "1"
And I press "Next"
- And I should see "Course overview"
+ And I should see "Calendar"
And I log out
And I log in as "admin"
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
@@ -311,4 +311,4 @@ Feature: Viewing acceptances reports and accepting on behalf of other users
And I press "Continue"
And I log out
When I log in as "user1"
- Then I should see "Course overview"
+ Then I should see "Calendar"
diff --git a/admin/tool/usertours/tests/behat/create_tour.feature b/admin/tool/usertours/tests/behat/create_tour.feature
index 92b676f3e6e96..b1e1b3edaac8f 100644
--- a/admin/tool/usertours/tests/behat/create_tour.feature
+++ b/admin/tool/usertours/tests/behat/create_tour.feature
@@ -20,7 +20,7 @@ Feature: Add a new user tour
| Display in middle of page | Welcome | Welcome to your personal learning space. We'd like to give you a quick tour to show you some of the areas you may find helpful |
And I add steps to the "First tour" tour:
| targettype | targetvalue_block | Title | Content |
- | Block | Course overview | Course overview | This area shows you what's happening in some of your courses |
+ | Block | Timeline | Timeline | This is the Timeline. All of your upcoming activities can be found here |
| Block | Calendar | Calendar | This is the Calendar. All of your assignments and due dates can be found here |
And I add steps to the "First tour" tour:
| targettype | targetvalue_selector | Title | Content |
@@ -28,7 +28,7 @@ Feature: Add a new user tour
When I am on homepage
Then I should see "Welcome to your personal learning space. We'd like to give you a quick tour to show you some of the areas you may find helpful"
And I click on "Next" "button" in the "[data-role='flexitour-step']" "css_element"
- And I should see "This area shows you what's happening in some of your courses"
+ And I should see "This is the Timeline. All of your upcoming activities can be found here"
And I should not see "This is the Calendar. All of your assignments and due dates can be found here"
And I click on "Next" "button" in the "[data-role='flexitour-step']" "css_element"
And I should see "This is the Calendar. All of your assignments and due dates can be found here"
@@ -95,7 +95,7 @@ Feature: Add a new user tour
| Display in middle of page | Welcome | First step of the Tour |
And I add steps to the "Steps tour" tour:
| targettype | targetvalue_block | Title | Content |
- | Block | Course overview | Course overview | Second step of the Tour |
+ | Block | Timeline | Timeline | Second step of the Tour |
| Block | Calendar | Calendar | Third step of the Tour |
When I am on homepage
Then I should see "First step of the Tour"
@@ -129,7 +129,7 @@ Feature: Add a new user tour
| Display in middle of page | Welcome | First step of the Tour |
And I add steps to the "Steps tour" tour:
| targettype | targetvalue_block | Title | Content |
- | Block | Course overview | Course overview | Second step of the Tour |
+ | Block | Timeline | Timeline | Second step of the Tour |
| Block | Calendar | Calendar | Third step of the Tour |
When I am on homepage
Then I should see "First step of the Tour"
diff --git a/admin/tool/usertours/tests/behat/tour_accessibility.feature b/admin/tool/usertours/tests/behat/tour_accessibility.feature
index 6dc9d81b8ec67..dbb567d90b785 100644
--- a/admin/tool/usertours/tests/behat/tour_accessibility.feature
+++ b/admin/tool/usertours/tests/behat/tour_accessibility.feature
@@ -14,7 +14,7 @@ Feature: Apply accessibility to a tour
And I add steps to the tour:
| targettype | targetvalue_selector | Title | Content |
| Selector | .usermenu | User menu | Next page |
- | Selector | input,button | Page 2 | Next page |
+ | Selector | .navbar-brand | Page 2 | Next page |
And I add steps to the tour:
| targettype | Title | Content |
| Display in middle of page | Page 3 | Final page. |
@@ -66,11 +66,11 @@ Feature: Apply accessibility to a tour
And I am on site homepage
When I click on "Next" "button"
And I click on "Next" "button"
- Then "input[aria-describedby^='tour-step-tool_usertours'],button[aria-describedby^='tour-step-tool_usertours']" "css_element" should exist
- And "input[tabindex],button[tabindex]" "css_element" should exist
+ Then ".navbar-brand[aria-describedby^='tour-step-tool_usertours']" "css_element" should exist
+ And ".navbar-brand[tabindex]" "css_element" should exist
When I click on "Next" "button"
- Then "input[aria-describedby^='tour-step-tool_usertours'],button[aria-describedby^='tour-step-tool_usertours']" "css_element" should not exist
- And "input[tabindex]:not([tabindex='-1']),button[tabindex]:not([tabindex='-1'])" "css_element" should not exist
+ Then ".navbar-brand[aria-describedby^='tour-step-tool_usertours']" "css_element" should not exist
+ And ".navbar-brand[tabindex]:not([tabindex='-1'])" "css_element" should not exist
When I click on "End tour" "button"
- Then "input[aria-describedby^='tour-step-tool_usertours'],button[aria-describedby^='tour-step-tool_usertours']" "css_element" should not exist
- And "input[tabindex]:not([tabindex='0']),button[tabindex]:not([tabindex='0'])" "css_element" should not exist
+ Then ".navbar-brand[aria-describedby^='tour-step-tool_usertours']" "css_element" should not exist
+ And ".navbar-brand[tabindex]:not([tabindex='0'])" "css_element" should not exist
diff --git a/admin/tool/usertours/tests/behat/tour_navigation.feature b/admin/tool/usertours/tests/behat/tour_navigation.feature
index 5e577d10c4002..12123d2322669 100644
--- a/admin/tool/usertours/tests/behat/tour_navigation.feature
+++ b/admin/tool/usertours/tests/behat/tour_navigation.feature
@@ -53,14 +53,14 @@ Feature: Steps can be navigated within a tour
| Display in middle of page | Welcome | Welcome to your personal learning space. We'd like to give you a quick tour to show you some of the areas you may find helpful |
And I add steps to the "First tour" tour:
| targettype | targetvalue_block | Title | Content |
- | Block | Course overview | Course overview | This area shows you what's happening in some of your courses |
+ | Block | Timeline | Timeline | This is the Timeline. All of your upcoming activities can be found here |
| Block | Calendar | Calendar | This is the Calendar. All of your assignments and due dates can be found here |
When I am on homepage
Then I should see "Skip tour"
And I should see "Next (1/3)"
And I click on "Next (1/3)" "button" in the "Welcome" "dialogue"
And I should see "Skip tour"
- And I click on "Next (2/3)" "button" in the "Course overview" "dialogue"
+ And I click on "Next (2/3)" "button" in the "Timeline" "dialogue"
And I should see "End tour"
@javascript
diff --git a/badges/renderer.php b/badges/renderer.php
index 36929f6a7656e..cc79994797dea 100644
--- a/badges/renderer.php
+++ b/badges/renderer.php
@@ -59,7 +59,8 @@ public function print_badges_list($badges, $userid, $profile = false, $external
$name = html_writer::tag('span', $bname, array('class' => 'badge-name'));
- $image = html_writer::empty_tag('img', ['src' => $imageurl, 'class' => 'badge-image', 'alt' => $badge->imagecaption]);
+ $imagecaption = $badge->imagecaption ?? '';
+ $image = html_writer::empty_tag('img', ['src' => $imageurl, 'class' => 'badge-image', 'alt' => $imagecaption]);
if (!empty($badge->dateexpire) && $badge->dateexpire < time()) {
$image .= $this->output->pix_icon('i/expired',
get_string('expireddate', 'badges', userdate($badge->dateexpire)),
diff --git a/blocks/calendar_month/block_calendar_month.php b/blocks/calendar_month/block_calendar_month.php
index 336e5953e58a3..fe3b998a6c8e2 100644
--- a/blocks/calendar_month/block_calendar_month.php
+++ b/blocks/calendar_month/block_calendar_month.php
@@ -59,10 +59,6 @@ public function get_content() {
$renderer = $this->page->get_renderer('core_calendar');
$this->content->text .= $renderer->render_from_template($template, $data);
- if ($this->page->course->id != SITEID) {
- $this->content->text .= $renderer->event_filter();
- }
-
$options = [
'showfullcalendarlink' => true
];
diff --git a/blocks/calendar_month/tests/behat/block_calendar_month.feature b/blocks/calendar_month/tests/behat/block_calendar_month.feature
index 246044a95bbf1..33ba9904dfa60 100644
--- a/blocks/calendar_month/tests/behat/block_calendar_month.feature
+++ b/blocks/calendar_month/tests/behat/block_calendar_month.feature
@@ -38,25 +38,6 @@ Feature: Enable the calendar block in a course and test it's functionality
And I hover over today in the mini-calendar block
Then I should see "Site Event"
- @javascript
- Scenario: Filter site events in the calendar block
- Given I log in as "admin"
- And I create a calendar event with form data:
- | id_eventtype | Site |
- | id_name | Site Event |
- And I log out
- When I log in as "teacher1"
- And I am on "Course 1" course homepage with editing mode on
- And I add the "Calendar" block
- And I create a calendar event with form data:
- | id_eventtype | Course |
- | id_name | Course Event |
- And I am on "Course 1" course homepage
- And I follow "Hide site events"
- Then I should not see "Site Event"
- And I hover over today in the mini-calendar block
- And I should see "Course Event"
-
@javascript
Scenario: View a course event in the calendar block
Given I log in as "teacher1"
@@ -69,24 +50,6 @@ Feature: Enable the calendar block in a course and test it's functionality
And I hover over today in the mini-calendar block
Then I should see "Course Event"
- @javascript
- Scenario: Filter course events in the calendar block
- Given I log in as "teacher1"
- And I am on "Course 1" course homepage with editing mode on
- And I add the "Calendar" block
- And I create a calendar event with form data:
- | id_eventtype | Course |
- | id_name | Course Event |
- And I am on "Course 1" course homepage
- And I create a calendar event with form data:
- | id_eventtype | User |
- | id_name | User Event |
- And I am on "Course 1" course homepage
- And I follow "Hide course events"
- Then I should not see "Course Event"
- And I hover over today in the mini-calendar block
- And I should see "User Event"
-
@javascript
Scenario: View a user event in the calendar block
Given I log in as "teacher1"
@@ -99,24 +62,6 @@ Feature: Enable the calendar block in a course and test it's functionality
And I hover over today in the mini-calendar block
Then I should see "User Event"
- @javascript
- Scenario: Filter user events in the calendar block
- Given I log in as "teacher1"
- And I am on "Course 1" course homepage with editing mode on
- And I add the "Calendar" block
- And I create a calendar event with form data:
- | id_eventtype | Course |
- | id_name | Course Event |
- And I am on "Course 1" course homepage
- And I create a calendar event with form data:
- | id_eventtype | User |
- | id_name | User Event |
- When I am on "Course 1" course homepage
- And I follow "Hide user events"
- Then I should not see "User Event"
- And I hover over today in the mini-calendar block
- And I should see "Course Event"
-
@javascript
Scenario: View a group event in the calendar block
Given the following "groups" exist:
@@ -153,42 +98,3 @@ Feature: Enable the calendar block in a course and test it's functionality
And I log in as "student2"
And I am on "Course 1" course homepage
And I should not see "Group Event"
-
- @javascript
- Scenario: Filter group events in the calendar block
- Given the following "groups" exist:
- | name | course | idnumber |
- | Group 1 | C1 | G1 |
- | Group 2 | C1 | G2 |
- And the following "group members" exist:
- | user | group |
- | student1 | G1 |
- | student2 | G2 |
- When I log in as "teacher1"
- And I am on "Course 1" course homepage
- And I navigate to "Settings" in current page administration
- And I set the following fields to these values:
- | id_groupmode | Separate groups |
- | id_groupmodeforce | Yes |
- And I press "Save and display"
- And I turn editing mode on
- And I add the "Calendar" block
- And I create a calendar event with form data:
- | id_eventtype | Course |
- | id_name | Course Event 1 |
- And I am on "Course 1" course homepage
- And I click on "Full calendar" "link"
- And I click on "New event" "button"
- And I set the following fields to these values:
- | id_eventtype | Group |
- | id_name | Group Event 1 |
- And I set the following fields to these values:
- | Group | Group 1 |
- And I press "Save"
- And I log out
- Then I log in as "student1"
- And I am on "Course 1" course homepage
- And I follow "Hide group events"
- And I should not see "Group Event 1"
- And I hover over today in the mini-calendar block
- And I should see "Course Event 1"
diff --git a/blocks/moodleblock.class.php b/blocks/moodleblock.class.php
index 76de67eef6af5..d50478fecb70b 100644
--- a/blocks/moodleblock.class.php
+++ b/blocks/moodleblock.class.php
@@ -249,7 +249,7 @@ public function get_content_for_output($output) {
$this->arialabel = $bc->arialabel;
}
- if ($this->page->user_is_editing()) {
+ if ($this->page->user_is_editing() && $this->instance_can_be_edited()) {
$bc->controls = $this->page->blocks->edit_controls($this);
} else {
// we must not use is_empty on hidden blocks
@@ -692,6 +692,15 @@ public function instance_can_be_collapsed() {
return true;
}
+ /**
+ * If overridden and set to false by the block it will not be editable.
+ *
+ * @return bool
+ */
+ public function instance_can_be_edited() {
+ return true;
+ }
+
/** @callback callback functions for comments api */
public static function comment_template($options) {
$ret = << $configs,
];
}
+
+ /**
+ * Disable block editing on the my courses page.
+ *
+ * @return boolean
+ */
+ public function instance_can_be_edited() {
+ if ($this->page->blocks->is_known_region(BLOCK_POS_LEFT) || $this->page->blocks->is_known_region(BLOCK_POS_RIGHT)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
}
diff --git a/blocks/myoverview/db/upgrade.php b/blocks/myoverview/db/upgrade.php
index 823981818bf99..47160e4684773 100644
--- a/blocks/myoverview/db/upgrade.php
+++ b/blocks/myoverview/db/upgrade.php
@@ -25,6 +25,8 @@
defined('MOODLE_INTERNAL') || die();
+require_once($CFG->dirroot . '/my/lib.php');
+
/**
* Upgrade code for the MyOverview block.
*
@@ -81,5 +83,77 @@ function xmldb_block_myoverview_upgrade($oldversion) {
// Automatically generated Moodle v3.9.0 release upgrade line.
// Put any upgrade step following this.
+ if ($oldversion < 2021052504) {
+ /**
+ * Small helper function for this version upgrade to delete instances of this block.
+ *
+ * @param stdClass $instance DB record of a block that we need to delete within Moodle.
+ */
+ function delete_block_instance(stdClass $instance) {
+ global $DB;
+ if ($instance) {
+ list($sql, $params) = $DB->get_in_or_equal($instance->id, SQL_PARAMS_NAMED);
+ $params['contextlevel'] = CONTEXT_BLOCK;
+ $DB->delete_records_select('context', "contextlevel=:contextlevel AND instanceid " . $sql, $params);
+ $DB->delete_records('block_positions', ['blockinstanceid' => $instance->id]);
+ $DB->delete_records('block_instances', ['id' => $instance->id]);
+ $DB->delete_records_list('user_preferences', 'name',
+ ['block' . $instance->id . 'hidden', 'docked_block_instance_' . $instance->id]);
+ }
+ }
+
+ // Delete the default indexsys version of the block.
+ $mysubpagepattern = $DB->get_record(
+ 'my_pages',
+ ['userid' => null, 'name' => MY_PAGE_DEFAULT, 'private' => MY_PAGE_PRIVATE],
+ 'id',
+ IGNORE_MULTIPLE
+ )->id;
+ $instances = $DB->get_records('block_instances', ['blockname' => 'myoverview',
+ 'pagetypepattern' => 'my-index', 'subpagepattern' => $mysubpagepattern]);
+ foreach ($instances as $instance) {
+ delete_block_instance($instance);
+ }
+
+ // Begin looking for any and all instances of course overview in customised /my pages.
+ $pageselect = 'name = :name and private = :private and userid IS NOT NULL';
+ $pageparams['name'] = MY_PAGE_DEFAULT;
+ $pageparams['private'] = MY_PAGE_PRIVATE;
+
+ $pages = $DB->get_recordset_select('my_pages', $pageselect, $pageparams);
+ foreach ($pages as $page) {
+ $blocksql = 'blockname = :blockname and pagetypepattern = :pagetypepattern and subpagepattern = :subpagepattern';
+ $blockparams['blockname'] = 'myoverview';
+ $blockparams['pagetypepattern'] = 'my-index';
+ $blockparams['subpagepattern'] = $page->id;
+ $instances = $DB->get_records_select('block_instances', $blocksql, $blockparams);
+ foreach ($instances as $instance) {
+ delete_block_instance($instance);
+ }
+ }
+ $pages->close();
+
+ // Add new instance to the /my/courses.php page.
+ $subpagepattern = $DB->get_record(
+ 'my_pages',
+ ['userid' => null, 'name' => MY_PAGE_COURSES, 'private' => MY_PAGE_PUBLIC],
+ 'id',
+ IGNORE_MULTIPLE
+ )->id;
+
+ // See if this block already somehow exists, it should not but who knows.
+ if (!$DB->get_record('block_instances', ['blockname' => 'myoverview',
+ 'pagetypepattern' => 'my-index', 'subpagepattern' => $subpagepattern])) {
+ $page = new moodle_page();
+ $systemcontext = context_system::instance();
+ $page->set_context($systemcontext);
+ // Add the block to the default /my/courses.
+ $page->blocks->add_region('content');
+ $page->blocks->add_block('myoverview', 'content', 0, false, 'my-index', $subpagepattern);
+ }
+
+ upgrade_block_savepoint(true, 2021052504, 'myoverview', false);
+ }
+
return true;
}
diff --git a/blocks/myoverview/lib.php b/blocks/myoverview/lib.php
index 7080d73f4b63a..8352f63ab05a5 100644
--- a/blocks/myoverview/lib.php
+++ b/blocks/myoverview/lib.php
@@ -101,7 +101,7 @@ function block_myoverview_user_preferences() {
$preferences['block_myoverview_user_sort_preference'] = array(
'null' => NULL_NOT_ALLOWED,
- 'default' => BLOCK_MYOVERVIEW_SORTING_TITLE,
+ 'default' => BLOCK_MYOVERVIEW_SORTING_LASTACCESSED,
'type' => PARAM_ALPHA,
'choices' => array(
BLOCK_MYOVERVIEW_SORTING_TITLE,
diff --git a/blocks/myoverview/tests/behat/block_myoverview_adminsettings.feature b/blocks/myoverview/tests/behat/block_myoverview_adminsettings.feature
index e9356fabd5bdf..92a51af321bd9 100644
--- a/blocks/myoverview/tests/behat/block_myoverview_adminsettings.feature
+++ b/blocks/myoverview/tests/behat/block_myoverview_adminsettings.feature
@@ -32,7 +32,7 @@ Feature: The my overview block allows admins to easily configure the students' c
And I set the field "All" to "1"
And I press "Save"
And I log out
- Then I log in as "student1"
+ Then I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
# We have to check for the data attribute instead of the list element text as we would get false positives from the "All (except removed from view)" element otherwise
Then "[data-value='allincludinghidden']" "css_element" should exist in the ".block_myoverview .dropdown-menu" "css_element"
@@ -43,7 +43,7 @@ Feature: The my overview block allows admins to easily configure the students' c
And I set the field "All" to "0"
And I press "Save"
And I log out
- Then I log in as "student1"
+ Then I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
# We have to check for the data attribute instead of the list element text as we would get false negatives "All (except removed from view)" element otherwise
Then "[data-value='allincludinghidden']" "css_element" should not exist in the ".block_myoverview .dropdown-menu" "css_element"
@@ -54,7 +54,7 @@ Feature: The my overview block allows admins to easily configure the students' c
And I set the field "All (except removed from view)" to "1"
And I press "Save"
And I log out
- Then I log in as "student1"
+ Then I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
Then "All (except removed from view)" "list_item" should exist in the ".block_myoverview .dropdown-menu" "css_element"
@@ -64,7 +64,7 @@ Feature: The my overview block allows admins to easily configure the students' c
And I set the field "All (except removed from view)" to "0"
And I press "Save"
And I log out
- Then I log in as "student1"
+ Then I am on the "My courses" page logged in as "student1"
# 'All (except removed from view)' option has been disabled, so the button is falling back to the 'In progress' option which is the next enabled option.
And I click on "In progress" "button" in the "Course overview" "block"
Then "All (except removed from view)" "list_item" should not exist in the ".block_myoverview .dropdown-menu" "css_element"
@@ -75,7 +75,7 @@ Feature: The my overview block allows admins to easily configure the students' c
And I set the field "In progress" to "1"
And I press "Save"
And I log out
- Then I log in as "student1"
+ Then I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
Then "In progress" "list_item" should exist in the ".block_myoverview .dropdown-menu" "css_element"
@@ -85,7 +85,7 @@ Feature: The my overview block allows admins to easily configure the students' c
And I set the field "In progress" to "0"
And I press "Save"
And I log out
- Then I log in as "student1"
+ Then I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
Then "In progress" "list_item" should not exist in the ".block_myoverview .dropdown-menu" "css_element"
@@ -95,7 +95,7 @@ Feature: The my overview block allows admins to easily configure the students' c
And I set the field "Future" to "1"
And I press "Save"
And I log out
- Then I log in as "student1"
+ Then I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
Then "Future" "list_item" should exist in the ".block_myoverview .dropdown-menu" "css_element"
@@ -105,7 +105,7 @@ Feature: The my overview block allows admins to easily configure the students' c
And I set the field "Future" to "0"
And I press "Save"
And I log out
- Then I log in as "student1"
+ Then I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
Then "Future" "list_item" should not exist in the ".block_myoverview .dropdown-menu" "css_element"
@@ -115,7 +115,7 @@ Feature: The my overview block allows admins to easily configure the students' c
And I set the field "Past" to "1"
And I press "Save"
And I log out
- Then I log in as "student1"
+ Then I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
Then "Past" "list_item" should exist in the ".block_myoverview .dropdown-menu" "css_element"
@@ -125,7 +125,7 @@ Feature: The my overview block allows admins to easily configure the students' c
And I set the field "Past" to "0"
And I press "Save"
And I log out
- Then I log in as "student1"
+ Then I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
Then "Past" "list_item" should not exist in the ".block_myoverview .dropdown-menu" "css_element"
@@ -135,7 +135,7 @@ Feature: The my overview block allows admins to easily configure the students' c
And I set the field "Starred" to "1"
And I press "Save"
And I log out
- Then I log in as "student1"
+ Then I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
Then "Starred" "list_item" should exist in the ".block_myoverview .dropdown-menu" "css_element"
@@ -145,7 +145,7 @@ Feature: The my overview block allows admins to easily configure the students' c
And I set the field "Starred" to "0"
And I press "Save"
And I log out
- Then I log in as "student1"
+ Then I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
Then "Starred" "list_item" should not exist in the ".block_myoverview .dropdown-menu" "css_element"
@@ -155,7 +155,7 @@ Feature: The my overview block allows admins to easily configure the students' c
And I set the field "Removed from view" to "1"
And I press "Save"
And I log out
- Then I log in as "student1"
+ Then I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
Then "Removed from view" "list_item" should exist in the ".block_myoverview .dropdown-menu" "css_element"
@@ -165,7 +165,7 @@ Feature: The my overview block allows admins to easily configure the students' c
And I set the field "Removed from view" to "0"
And I press "Save"
And I log out
- Then I log in as "student1"
+ Then I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
Then "Removed from view" "list_item" should not exist in the ".block_myoverview .dropdown-menu" "css_element"
@@ -181,7 +181,7 @@ Feature: The my overview block allows admins to easily configure the students' c
And I set the field "Removed from view" to "0"
And I press "Save"
And I log out
- And I log in as "student1"
+ And I am on the "My courses" page logged in as "student1"
Then "button#groupingdropdown" "css_element" should not exist in the ".block_myoverview" "css_element"
And I should see "Course 1" in the "Course overview" "block"
And I should see "Course 2" in the "Course overview" "block"
@@ -201,7 +201,7 @@ Feature: The my overview block allows admins to easily configure the students' c
And I set the field "Removed from view" to "0"
And I press "Save"
And I log out
- And I log in as "student1"
+ And I am on the "My courses" page logged in as "student1"
Then "button#groupingdropdown" "css_element" should not exist in the ".block_myoverview" "css_element"
And I should see "Course 2" in the "Course overview" "block"
And I should see "Course 3" in the "Course overview" "block"
diff --git a/blocks/myoverview/tests/behat/block_myoverview_customfield.feature b/blocks/myoverview/tests/behat/block_myoverview_customfield.feature
index c866d5d0c227a..096b136895e65 100644
--- a/blocks/myoverview/tests/behat/block_myoverview_customfield.feature
+++ b/blocks/myoverview/tests/behat/block_myoverview_customfield.feature
@@ -35,7 +35,7 @@ Feature: The my overview block allows users to group courses by custom fields
Given the following config values are set as admin:
| displaygroupingcustomfield | 1 | block_myoverview |
| customfiltergrouping | checkboxfield | block_myoverview |
- And I log in as "student1"
+ And I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "Checkbox field: Yes" "link" in the "Course overview" "block"
Then I should see "Course 1" in the "Course overview" "block"
@@ -48,7 +48,7 @@ Feature: The my overview block allows users to group courses by custom fields
Given the following config values are set as admin:
| displaygroupingcustomfield | 1 | block_myoverview |
| customfiltergrouping | checkboxfield | block_myoverview |
- And I log in as "student1"
+ And I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "Checkbox field: No" "link" in the "Course overview" "block"
Then I should not see "Course 1" in the "Course overview" "block"
@@ -61,7 +61,7 @@ Feature: The my overview block allows users to group courses by custom fields
Given the following config values are set as admin:
| displaygroupingcustomfield | 1 | block_myoverview |
| customfiltergrouping | datefield | block_myoverview |
- And I log in as "student1"
+ And I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "1 February 2001" "link" in the "Course overview" "block"
Then I should see "Course 1" in the "Course overview" "block"
@@ -74,7 +74,7 @@ Feature: The my overview block allows users to group courses by custom fields
Given the following config values are set as admin:
| displaygroupingcustomfield | 1 | block_myoverview |
| customfiltergrouping | datefield | block_myoverview |
- And I log in as "student1"
+ And I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "6 August 1980" "link" in the "Course overview" "block"
Then I should not see "Course 1" in the "Course overview" "block"
@@ -87,7 +87,7 @@ Feature: The my overview block allows users to group courses by custom fields
Given the following config values are set as admin:
| displaygroupingcustomfield | 1 | block_myoverview |
| customfiltergrouping | datefield | block_myoverview |
- And I log in as "student1"
+ And I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "No Date field" "link" in the "Course overview" "block"
Then I should not see "Course 1" in the "Course overview" "block"
@@ -100,7 +100,7 @@ Feature: The my overview block allows users to group courses by custom fields
Given the following config values are set as admin:
| displaygroupingcustomfield | 1 | block_myoverview |
| customfiltergrouping | selectfield | block_myoverview |
- And I log in as "student1"
+ And I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
And I should not see "Option 4" in the "Course overview" "block"
When I click on "Option 1" "link" in the "Course overview" "block"
@@ -114,7 +114,7 @@ Feature: The my overview block allows users to group courses by custom fields
Given the following config values are set as admin:
| displaygroupingcustomfield | 1 | block_myoverview |
| customfiltergrouping | selectfield | block_myoverview |
- And I log in as "student1"
+ And I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "Option 2" "link" in the "Course overview" "block"
Then I should not see "Course 1" in the "Course overview" "block"
@@ -127,7 +127,7 @@ Feature: The my overview block allows users to group courses by custom fields
Given the following config values are set as admin:
| displaygroupingcustomfield | 1 | block_myoverview |
| customfiltergrouping | selectfield | block_myoverview |
- And I log in as "student1"
+ And I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "No Select field" "link" in the "Course overview" "block"
Then I should not see "Course 1" in the "Course overview" "block"
@@ -140,7 +140,7 @@ Feature: The my overview block allows users to group courses by custom fields
Given the following config values are set as admin:
| displaygroupingcustomfield | 1 | block_myoverview |
| customfiltergrouping | textfield | block_myoverview |
- And I log in as "student1"
+ And I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "fish" "link" in the "Course overview" "block"
Then I should see "Course 1" in the "Course overview" "block"
@@ -153,7 +153,7 @@ Feature: The my overview block allows users to group courses by custom fields
Given the following config values are set as admin:
| displaygroupingcustomfield | 1 | block_myoverview |
| customfiltergrouping | textfield | block_myoverview |
- And I log in as "student1"
+ And I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "dog" "link" in the "Course overview" "block"
Then I should not see "Course 1" in the "Course overview" "block"
@@ -166,7 +166,7 @@ Feature: The my overview block allows users to group courses by custom fields
Given the following config values are set as admin:
| displaygroupingcustomfield | 1 | block_myoverview |
| customfiltergrouping | textfield | block_myoverview |
- And I log in as "student1"
+ And I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "No Text field" "link" in the "Course overview" "block"
Then I should not see "Course 1" in the "Course overview" "block"
@@ -191,7 +191,7 @@ Feature: The my overview block allows users to group courses by custom fields
And I set the field "Visible to" to "Nobody"
And I press "Save changes"
And I log out
- When I log in as "student1"
+ When I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
Then I should not see "penguin" in the "Course overview" "block"
Then I should not see "No text field" in the "Course overview" "block"
diff --git a/blocks/myoverview/tests/behat/block_myoverview_dashboard.feature b/blocks/myoverview/tests/behat/block_myoverview_dashboard.feature
index b1dcc7bd0b231..ce381bcb1c1a8 100644
--- a/blocks/myoverview/tests/behat/block_myoverview_dashboard.feature
+++ b/blocks/myoverview/tests/behat/block_myoverview_dashboard.feature
@@ -27,7 +27,7 @@ Feature: The my overview block allows users to easily access their courses
| student1 | C5 | student |
Scenario: View past courses
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "Past" "link" in the "Course overview" "block"
Then I should see "Course 1" in the "Course overview" "block"
@@ -37,7 +37,7 @@ Feature: The my overview block allows users to easily access their courses
And I should not see "Course 5" in the "Course overview" "block"
Scenario: View future courses
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "Future" "link" in the "Course overview" "block"
Then I should see "Course 5" in the "Course overview" "block"
@@ -47,7 +47,7 @@ Feature: The my overview block allows users to easily access their courses
And I should not see "Course 4" in the "Course overview" "block"
Scenario: View inprogress courses
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "In progress" "link" in the "Course overview" "block"
Then I should see "Course 2" in the "Course overview" "block"
@@ -57,7 +57,7 @@ Feature: The my overview block allows users to easily access their courses
And I should not see "Course 5" in the "Course overview" "block"
Scenario: View all (except removed) courses
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "All (except removed from view)" "link" in the "Course overview" "block"
Then I should see "Course 1" in the "Course overview" "block"
@@ -70,7 +70,7 @@ Feature: The my overview block allows users to easily access their courses
Given the following config values are set as admin:
| config | value | plugin |
| displaygroupingallincludinghidden | 1 | block_myoverview |
- And I log in as "student1"
+ And I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
# We have to click on the data attribute instead of the button element text as we might risk to click on the false positive "All (except removed from view)" element instead
When I click on "[data-value='allincludinghidden']" "css_element" in the "Course overview" "block"
@@ -81,7 +81,7 @@ Feature: The my overview block allows users to easily access their courses
Then I should see "Course 5" in the "Course overview" "block"
Scenario: View inprogress courses - test persistence
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
And I click on "In progress" "link" in the "Course overview" "block"
And I reload the page
@@ -93,7 +93,7 @@ Feature: The my overview block allows users to easily access their courses
And I should not see "Course 5" in the "Course overview" "block"
Scenario: View all (except removed) courses - w/ persistence
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "All (except removed from view)" "link" in the "Course overview" "block"
And I reload the page
@@ -105,7 +105,7 @@ Feature: The my overview block allows users to easily access their courses
Then I should see "Course 5" in the "Course overview" "block"
Scenario: View past courses - w/ persistence
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "Past" "link" in the "Course overview" "block"
And I reload the page
@@ -117,7 +117,7 @@ Feature: The my overview block allows users to easily access their courses
And I should not see "Course 5" in the "Course overview" "block"
Scenario: View future courses - w/ persistence
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "Future" "link" in the "Course overview" "block"
And I reload the page
@@ -129,7 +129,7 @@ Feature: The my overview block allows users to easily access their courses
And I should not see "Course 4" in the "Course overview" "block"
Scenario: View favourite courses - w/ persistence
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I click on "Star this course" "link" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
@@ -143,7 +143,7 @@ Feature: The my overview block allows users to easily access their courses
And I should not see "Course 5" in the "Course overview" "block"
Scenario: List display persistence
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I click on "Display drop-down menu" "button" in the "Course overview" "block"
And I click on "List" "link" in the "Course overview" "block"
And I reload the page
@@ -151,7 +151,7 @@ Feature: The my overview block allows users to easily access their courses
And "[data-display='list']" "css_element" in the "Course overview" "block" should be visible
Scenario: Cards display persistence
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I click on "Display drop-down menu" "button" in the "Course overview" "block"
And I click on "Card" "link" in the "Course overview" "block"
And I reload the page
@@ -159,7 +159,7 @@ Feature: The my overview block allows users to easily access their courses
And "[data-display='card']" "css_element" in the "Course overview" "block" should be visible
Scenario: Summary display persistence
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I click on "Display drop-down menu" "button" in the "Course overview" "block"
And I click on "Summary" "link" in the "Course overview" "block"
And I reload the page
@@ -167,7 +167,7 @@ Feature: The my overview block allows users to easily access their courses
And "[data-display='summary']" "css_element" in the "Course overview" "block" should be visible
Scenario: Course name sort persistence
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I click on "sortingdropdown" "button" in the "Course overview" "block"
And I click on "Course name" "link" in the "Course overview" "block"
And I reload the page
@@ -175,7 +175,7 @@ Feature: The my overview block allows users to easily access their courses
And "[data-sort='fullname']" "css_element" in the "Course overview" "block" should be visible
Scenario: Last accessed sort persistence
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I click on "sortingdropdown" "button" in the "Course overview" "block"
And I click on "Last accessed" "link" in the "Course overview" "block"
And I reload the page
@@ -183,7 +183,7 @@ Feature: The my overview block allows users to easily access their courses
And "[data-sort='ul.timeaccess desc']" "css_element" in the "Course overview" "block" should be visible
Scenario: Short name sort persistence
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
When I click on "sortingdropdown" "button" in the "Course overview" "block"
Then I should not see "Short name" in the "Course overview" "block"
When the following config values are set as admin:
@@ -197,7 +197,7 @@ Feature: The my overview block allows users to easily access their courses
And "[data-sort='shortname']" "css_element" in the "Course overview" "block" should be visible
Scenario: View inprogress courses with hide persistent functionality
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "In progress" "link" in the "Course overview" "block"
And I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
@@ -210,7 +210,7 @@ Feature: The my overview block allows users to easily access their courses
And I should not see "Course 5" in the "Course overview" "block"
Scenario: View past courses with hide persistent functionality
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "Past" "link" in the "Course overview" "block"
And I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 1')]" "xpath_element"
@@ -223,7 +223,7 @@ Feature: The my overview block allows users to easily access their courses
And I should not see "Course 5" in the "Course overview" "block"
Scenario: View future courses with hide persistent functionality
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "Future" "link" in the "Course overview" "block"
And I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 5')]" "xpath_element"
@@ -236,7 +236,7 @@ Feature: The my overview block allows users to easily access their courses
And I should not see "Course 4" in the "Course overview" "block"
Scenario: View all (except hidden) courses with hide persistent functionality
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "All (except removed from view)" "link" in the "Course overview" "block"
And I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 5')]" "xpath_element"
@@ -252,7 +252,7 @@ Feature: The my overview block allows users to easily access their courses
Given the following config values are set as admin:
| config | value | plugin |
| displaygroupingallincludinghidden | 1 | block_myoverview |
- And I log in as "student1"
+ And I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
# We have to click on the data attribute instead of the button element text as we might risk to click on the false positive "All (except removed from view)" element instead
When I click on "[data-value='allincludinghidden']" "css_element" in the "Course overview" "block"
@@ -268,7 +268,7 @@ Feature: The my overview block allows users to easily access their courses
Scenario: Show course category in cards display
Given the following config values are set as admin:
| displaycategories | 1 | block_myoverview |
- And I log in as "student1"
+ And I am on the "My courses" page logged in as "student1"
And I click on "Display drop-down menu" "button" in the "Course overview" "block"
When I click on "Card" "link" in the "Course overview" "block"
Then I should see "Category 1" in the "Course overview" "block"
@@ -276,7 +276,7 @@ Feature: The my overview block allows users to easily access their courses
Scenario: Show course category in list display
Given the following config values are set as admin:
| displaycategories | 1 | block_myoverview |
- And I log in as "student1"
+ And I am on the "My courses" page logged in as "student1"
And I click on "Display drop-down menu" "button" in the "Course overview" "block"
When I click on "List" "link" in the "Course overview" "block"
Then I should see "Category 1" in the "Course overview" "block"
@@ -284,7 +284,7 @@ Feature: The my overview block allows users to easily access their courses
Scenario: Show course category in summary display
Given the following config values are set as admin:
| displaycategories | 1 | block_myoverview |
- And I log in as "student1"
+ And I am on the "My courses" page logged in as "student1"
And I click on "Display drop-down menu" "button" in the "Course overview" "block"
When I click on "Summary" "link" in the "Course overview" "block"
Then I should see "Category 1" in the "Course overview" "block"
@@ -292,7 +292,7 @@ Feature: The my overview block allows users to easily access their courses
Scenario: Hide course category in cards display
Given the following config values are set as admin:
| displaycategories | 0 | block_myoverview |
- And I log in as "student1"
+ And I am on the "My courses" page logged in as "student1"
And I click on "Display drop-down menu" "button" in the "Course overview" "block"
When I click on "Card" "link" in the "Course overview" "block"
Then I should not see "Category 1" in the "Course overview" "block"
@@ -300,7 +300,7 @@ Feature: The my overview block allows users to easily access their courses
Scenario: Hide course category in list display
Given the following config values are set as admin:
| displaycategories | 0 | block_myoverview |
- And I log in as "student1"
+ And I am on the "My courses" page logged in as "student1"
And I click on "Display drop-down menu" "button" in the "Course overview" "block"
When I click on "List" "link" in the "Course overview" "block"
Then I should not see "Category 1" in the "Course overview" "block"
@@ -308,12 +308,12 @@ Feature: The my overview block allows users to easily access their courses
Scenario: Show course category in summary display
Given the following config values are set as admin:
| displaycategories | 0 | block_myoverview |
- And I log in as "student1"
+ And I am on the "My courses" page logged in as "student1"
And I click on "Display drop-down menu" "button" in the "Course overview" "block"
When I click on "Summary" "link" in the "Course overview" "block"
Then I should not see "Category 1" in the "Course overview" "block"
@accessibility
Scenario: The dashboard page must have sufficient colour contrast
- When I log in as "student1"
+ When I am on the "My courses" page logged in as "student1"
Then the page should meet "wcag143" accessibility standards
diff --git a/blocks/myoverview/tests/behat/block_myoverview_favourite.feature b/blocks/myoverview/tests/behat/block_myoverview_favourite.feature
index fbf575663c275..71d140ea4ca61 100644
--- a/blocks/myoverview/tests/behat/block_myoverview_favourite.feature
+++ b/blocks/myoverview/tests/behat/block_myoverview_favourite.feature
@@ -24,7 +24,7 @@ Feature: The my overview block allows users to favourite their courses
| student1 | C5 | student |
Scenario: Favourite a course on a course card
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
When I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I click on "Star this course" "link" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I reload the page
@@ -34,7 +34,7 @@ Feature: The my overview block allows users to favourite their courses
And "//div[@class='card dashboard-card' and contains(.,'Course 3')]//span[@data-region='is-favourite' and @aria-hidden='true']" "xpath_element" should exist
Scenario: Star a course and switch display to list
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
When I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 5')]" "xpath_element"
And I click on "Star this course" "link" in the "//div[@class='card dashboard-card' and contains(.,'Course 5')]" "xpath_element"
And I reload the page
@@ -47,7 +47,7 @@ Feature: The my overview block allows users to favourite their courses
And "//li[contains(concat(' ', normalize-space(@class), ' '), 'list-group-item') and contains(.,'Course 3')]//span[@data-region='is-favourite' and @aria-hidden='true']" "xpath_element" should exist
Scenario: Star a course and switch display to summary
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
When I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 5')]" "xpath_element"
And I click on "Star this course" "link" in the "//div[@class='card dashboard-card' and contains(.,'Course 5')]" "xpath_element"
And I reload the page
diff --git a/blocks/myoverview/tests/behat/block_myoverview_hidden.feature b/blocks/myoverview/tests/behat/block_myoverview_hidden.feature
index 3c4a12de23b7e..e82f34bdf0d84 100644
--- a/blocks/myoverview/tests/behat/block_myoverview_hidden.feature
+++ b/blocks/myoverview/tests/behat/block_myoverview_hidden.feature
@@ -24,7 +24,7 @@ Feature: The my overview block allows users to hide their courses
| student1 | C5 | student |
Scenario: Test hide toggle functionality
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "All (except removed from view)" "link" in the "Course overview" "block"
And I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
@@ -33,7 +33,7 @@ Feature: The my overview block allows users to hide their courses
Then I should not see "Course 2" in the "Course overview" "block"
Scenario: Test hide toggle functionality w/ favorites
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "All (except removed from view)" "link" in the "Course overview" "block"
And I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
@@ -50,7 +50,7 @@ Feature: The my overview block allows users to hide their courses
Then I should see "Course 2" in the "Course overview" "block"
Scenario: Test show toggle functionality
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "All (except removed from view)" "link" in the "Course overview" "block"
And I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
@@ -65,7 +65,7 @@ Feature: The my overview block allows users to hide their courses
Then I should see "Course 2" in the "Course overview" "block"
Scenario: Test show toggle functionality w/ favorites
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "All (except removed from view)" "link" in the "Course overview" "block"
And I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
@@ -87,7 +87,7 @@ Feature: The my overview block allows users to hide their courses
Then I should see "Course 2" in the "Course overview" "block"
Scenario: Test a course is hidden directly with "All (except removed from view)" courses
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "All (except removed from view)" "link" in the "Course overview" "block"
And I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
@@ -98,7 +98,7 @@ Feature: The my overview block allows users to hide their courses
Given the following config values are set as admin:
| config | value | plugin |
| displaygroupingallincludinghidden | 1 | block_myoverview |
- And I log in as "student1"
+ And I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
# We have to click on the data attribute instead of the button element text as we might risk to click on the false positive "All (except hidden)" element instead
When I click on "[data-value='allincludinghidden']" "css_element" in the "Course overview" "block"
diff --git a/blocks/myoverview/tests/behat/block_myoverview_pagelimit_persistence.feature b/blocks/myoverview/tests/behat/block_myoverview_pagelimit_persistence.feature
index fef9a8b936184..1822a2d7ab9cc 100644
--- a/blocks/myoverview/tests/behat/block_myoverview_pagelimit_persistence.feature
+++ b/blocks/myoverview/tests/behat/block_myoverview_pagelimit_persistence.feature
@@ -37,7 +37,7 @@ Feature: The my overview block allows users to persistence of their page limits
| student1 | C13 | student |
Scenario: Toggle the page limit between page reloads
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
When I click on "[data-action='limit-toggle']" "css_element" in the "Course overview" "block"
And I click on "All" "link" in the ".dropdown-menu.show" "css_element"
Then I should see "Course 13"
@@ -46,7 +46,7 @@ Feature: The my overview block allows users to persistence of their page limits
And I should see "All" in the "[data-action='limit-toggle']" "css_element"
Scenario: Toggle the page limit between grouping changes
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
When I click on "[data-action='limit-toggle']" "css_element" in the "Course overview" "block"
And I click on "All" "link" in the ".dropdown-menu.show" "css_element"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
diff --git a/blocks/myoverview/tests/behat/block_myoverview_pagination.feature b/blocks/myoverview/tests/behat/block_myoverview_pagination.feature
index b3a6b514f478e..05f5ea63fe4c4 100644
--- a/blocks/myoverview/tests/behat/block_myoverview_pagination.feature
+++ b/blocks/myoverview/tests/behat/block_myoverview_pagination.feature
@@ -34,7 +34,7 @@ Feature: My overview block pagination
| Course 25 | C25 | 0 |
Scenario: The pagination controls should be hidden if I am not enrolled in any courses
- When I log in as "student1"
+ When I am on the "My courses" page logged in as "student1"
Then I should see "No courses" in the "Course overview" "block"
And I should not see "Show" in the "Course overview" "block"
And ".block_myoverview .dropdown-menu.show" "css_element" should not be visible
@@ -57,7 +57,7 @@ Feature: My overview block pagination
| student1 | C10 | student |
| student1 | C11 | student |
| student1 | C12 | student |
- When I log in as "student1"
+ When I am on the "My courses" page logged in as "student1"
Then I should not see "Show" in the "Course overview" "block"
And ".block_myoverview .dropdown-menu.show" "css_element" should not be visible
And ".block_myoverview [data-control='next']" "css_element" should not be visible
@@ -80,7 +80,7 @@ Feature: My overview block pagination
| student1 | C11 | student |
| student1 | C12 | student |
| student1 | C13 | student |
- When I log in as "student1"
+ When I am on the "My courses" page logged in as "student1"
Then I should see "12" in the "[data-action='limit-toggle']" "css_element"
And I log out
@@ -100,7 +100,7 @@ Feature: My overview block pagination
| student1 | C11 | student |
| student1 | C12 | student |
| student1 | C13 | student |
- And I log in as "student1"
+ And I am on the "My courses" page logged in as "student1"
When I click on "[data-action='limit-toggle']" "css_element" in the "Course overview" "block"
Then I should see "All" in the ".dropdown-menu.show" "css_element"
And I should see "12" in the ".dropdown-menu.show" "css_element"
@@ -125,7 +125,7 @@ Feature: My overview block pagination
| student1 | C11 | student |
| student1 | C12 | student |
| student1 | C13 | student |
- When I log in as "student1"
+ When I am on the "My courses" page logged in as "student1"
Then the "class" attribute of ".block_myoverview [data-control='previous']" "css_element" should contain "disabled"
And I log out
@@ -145,7 +145,7 @@ Feature: My overview block pagination
| student1 | C11 | student |
| student1 | C12 | student |
| student1 | C13 | student |
- When I log in as "student1"
+ When I am on the "My courses" page logged in as "student1"
And I click on "[data-control='next']" "css_element" in the "Course overview" "block"
Then the "class" attribute of ".block_myoverview [data-control='next']" "css_element" should contain "disabled"
And I log out
@@ -178,7 +178,8 @@ Feature: My overview block pagination
| student1 | C23 | student |
| student1 | C24 | student |
| student1 | C25 | student |
- When I log in as "student1"
+ When I am on the "My courses" page logged in as "student1"
+ And I wait until ".block_myoverview [data-control='next']" "css_element" exists
And I click on "[data-control='next']" "css_element" in the "Course overview" "block"
Then the "class" attribute of ".block_myoverview [data-control='next']" "css_element" should not contain "disabled"
And the "class" attribute of ".block_myoverview [data-control='previous']" "css_element" should not contain "disabled"
diff --git a/blocks/myoverview/tests/behat/block_myoverview_progress.feature b/blocks/myoverview/tests/behat/block_myoverview_progress.feature
index 30f133477d110..3d503a2ba07aa 100644
--- a/blocks/myoverview/tests/behat/block_myoverview_progress.feature
+++ b/blocks/myoverview/tests/behat/block_myoverview_progress.feature
@@ -21,7 +21,7 @@ Feature: Course overview block show users their progress on courses
| student1 | C1 | student |
Scenario: Course progress percentage should not be displayed if completion is not enabled
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
When I click on "All (except removed from view)" "link" in the "Course overview" "block"
Then I should not see "0%" in the "Course overview" "block"
@@ -34,12 +34,11 @@ Feature: Course overview block show users their progress on courses
| id_completionview | 1 |
And I press "Save and return to course"
And I log out
- When I log in as "student1"
+ When I am on the "My courses" page logged in as "student1"
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
Then I should see "Course 1" in the "Course overview" "block"
And I should see "0%" in the "Course overview" "block"
-
And I am on the "Test choice 1" "choice activity" page
- And I follow "Dashboard" in the user menu
+ And I am on the "My courses" page
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
And I should see "100%" in the "Course overview" "block"
diff --git a/blocks/myoverview/tests/behat/block_myoverview_search.feature b/blocks/myoverview/tests/behat/block_myoverview_search.feature
index 0878b639f4d0f..6f6214678d485 100644
--- a/blocks/myoverview/tests/behat/block_myoverview_search.feature
+++ b/blocks/myoverview/tests/behat/block_myoverview_search.feature
@@ -39,21 +39,21 @@ Feature: My overview block searching
| student1 | C13 | student |
Scenario: The search should return no courses if I am not enrolled in any
- When I log in as "student2"
+ When I am on the "My courses" page logged in as "student2"
Then I should see "No courses" in the "Course overview" "block"
And I set the field "Search courses" to "Fake example"
And I should see "No courses" in the "Course overview" "block"
And I log out
Scenario: Single page search
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I set the field "Search courses" to "Course 0"
Then I should see "Course 01" in the "Course overview" "block"
And I should not see "Course 13" in the "Course overview" "block"
And I log out
Scenario: Paginated search
- Given I log in as "student1"
+ Given I am on the "My courses" page logged in as "student1"
And I set the field "Search courses" to "Course"
And I should see "Course 01" in the "Course overview" "block"
And I should not see "Course 13" in the "Course overview" "block"
diff --git a/blocks/myoverview/tests/myoverview_test.php b/blocks/myoverview/tests/myoverview_test.php
index eba4b29bc4adf..13f130cfc6f46 100644
--- a/blocks/myoverview/tests/myoverview_test.php
+++ b/blocks/myoverview/tests/myoverview_test.php
@@ -66,15 +66,15 @@ public function test_get_block_config_for_external() {
$this->setUser($user);
$context = context_user::instance($user->id);
- if (!$currentpage = my_get_page($user->id, MY_PAGE_PRIVATE)) {
+ if (!$currentpage = my_get_page($user->id, MY_PAGE_PUBLIC, MY_PAGE_COURSES)) {
throw new moodle_exception('mymoodlesetup');
}
- $PAGE->set_url('/my/index.php'); // Need this because some internal API calls require the $PAGE url to be set.
+ $PAGE->set_url('/my/courses.php'); // Need this because some internal API calls require the $PAGE url to be set.
$PAGE->set_context($context);
$PAGE->set_pagelayout('mydashboard');
$PAGE->set_pagetype('my-index');
- $PAGE->blocks->add_region('content'); // Need to add this special regition to retrieve the central blocks.
+ $PAGE->blocks->add_region('content'); // Need to add this special region to retrieve the central blocks.
$PAGE->set_subpage($currentpage->id);
// Load the block instances for all the regions.
diff --git a/blocks/myoverview/version.php b/blocks/myoverview/version.php
index 988fee790f497..b8ed58d669a26 100644
--- a/blocks/myoverview/version.php
+++ b/blocks/myoverview/version.php
@@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2021052503; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->version = 2021052504; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2021052500; // Requires this Moodle version.
$plugin->component = 'block_myoverview'; // Full name of the plugin (used for diagnostics).
diff --git a/blocks/tests/behat/configure_block_throughout_site.feature b/blocks/tests/behat/configure_block_throughout_site.feature
index f633c84d57018..f6cfc09be4af1 100644
--- a/blocks/tests/behat/configure_block_throughout_site.feature
+++ b/blocks/tests/behat/configure_block_throughout_site.feature
@@ -70,4 +70,4 @@ Feature: Add and configure blocks throughout the site
| Text block title | Foo " onload="document.getElementsByTagName('body')[0].remove()" alt=" |
| Content | Example |
When I press "Save changes"
- Then I should see "Course overview"
+ Then I should see "Example"
diff --git a/blocks/tests/externallib_test.php b/blocks/tests/externallib_test.php
index 937b640a71b45..26904bceba7d3 100644
--- a/blocks/tests/externallib_test.php
+++ b/blocks/tests/externallib_test.php
@@ -327,9 +327,14 @@ public function test_get_dashboard_blocks_default_dashboard() {
// Force a setting change to check the returned blocks settings.
set_config('displaycategories', 0, 'block_myoverview');
+ $systempage = $DB->get_record('my_pages', array('userid' => null, 'name' => MY_PAGE_DEFAULT, 'private' => true));
// Get the expected default blocks.
- $alldefaultblocksordered = $DB->get_records_menu('block_instances',
- array('pagetypepattern' => 'my-index'), 'defaultregion, defaultweight ASC', 'id, blockname');
+ $alldefaultblocksordered = $DB->get_records_menu(
+ 'block_instances',
+ array('pagetypepattern' => 'my-index', 'subpagepattern' => $systempage->id),
+ 'defaultregion, defaultweight ASC',
+ 'id, blockname'
+ );
$this->setUser($user);
@@ -368,8 +373,13 @@ public function test_get_dashboard_blocks_default_dashboard_including_sticky_blo
$user = $this->getDataGenerator()->create_user();
$PAGE->set_url('/my/index.php'); // Need this because some internal API calls require the $PAGE url to be set.
+ $systempage = $DB->get_record('my_pages', array('userid' => null, 'name' => MY_PAGE_DEFAULT, 'private' => true));
// Get the expected default blocks.
- $alldefaultblocks = $DB->get_records_menu('block_instances', array('pagetypepattern' => 'my-index'), '', 'id, blockname');
+ $alldefaultblocks = $DB->get_records_menu(
+ 'block_instances', array('pagetypepattern' => 'my-index', 'subpagepattern' => $systempage->id),
+ '',
+ 'id, blockname'
+ );
// Now, add a sticky block.
$page = new moodle_page();
@@ -411,8 +421,14 @@ public function test_get_dashboard_blocks_custom_user_dashboard() {
$user = $this->getDataGenerator()->create_user();
$PAGE->set_url('/my/index.php'); // Need this because some internal API calls require the $PAGE url to be set.
+ $systempage = $DB->get_record('my_pages', array('userid' => null, 'name' => MY_PAGE_DEFAULT, 'private' => true));
// Get the expected default blocks.
- $alldefaultblocks = $DB->get_records_menu('block_instances', array('pagetypepattern' => 'my-index'), '', 'id, blockname');
+ $alldefaultblocks = $DB->get_records_menu(
+ 'block_instances',
+ array('pagetypepattern' => 'my-index', 'subpagepattern' => $systempage->id),
+ '',
+ 'id, blockname'
+ );
// Add a custom block.
$page = new moodle_page();
diff --git a/blocks/timeline/templates/event-list-item.mustache b/blocks/timeline/templates/event-list-item.mustache
index ad1365bff8a26..4d60eaa830db1 100644
--- a/blocks/timeline/templates/event-list-item.mustache
+++ b/blocks/timeline/templates/event-list-item.mustache
@@ -57,8 +57,8 @@
");f.find("label").html(b);h.create({title:d,type:h.types.SAVE_CANCEL,body:f.html()},c).done(function(b){var e=a(b.getBody()).find("#add_section_numsections"),f=function(){if(""+parseInt(e.val())===e.val()&&1<=parseInt(e.val())){document.location=c.attr("href")+"&numsections="+parseInt(e.val())}};b.setSaveButtonText(d);b.getRoot().on(i.shown,function(){e.focus().select().on("keydown",function(a){if(a.keyCode===j.enter){f()}})});b.getRoot().on(i.save,function(a){a.preventDefault();f()})})})},replaceSectionActionItem:function replaceSectionActionItem(a,b,c,d,e,f){k.debug("replaceSectionActionItem() is deprecated and will be removed.");var g=a.find(s.SECTIONACTIONMENU+" "+b);I(g,c,d,e,f)},refreshModule:F,refreshSection:function refreshSection(c,e,f){if(f===void 0){f=p.sectionReturn}var g=a(c),h="refresh",i=b.call([{methodname:"core_course_edit_section",args:{id:e,action:h,sectionreturn:f}}],!0),j=x(g);return new Promise(function(b,c){a.when.apply(a,i).done(function(c){z(g,j);var d=a.parseJSON(c),f=a(d.content);g.replaceWith(f);a("".concat(s.SECTIONLI,"#").concat(e," ").concat(s.ACTIVITYLI)).each(function(a,b){B(b.data("id"))});var i=t(n.sectionRefreshed,{ajaxreturn:d,action:h,newSectionElement:f.get(0)},f);if(!i.defaultPrevented){J(f,a(s.SECTIONLI+"#"+e),d,q,e)}b(d)}).fail(function(a){var b=t("coursesectionrefreshfailed",{exception:a,action:h},g);if(!b.defaultPrevented){d.exception(a)}c()})})}}});
//# sourceMappingURL=actions.min.js.map
diff --git a/course/amd/build/actions.min.js.map b/course/amd/build/actions.min.js.map
index 681509f9cb2b4..c4a15ba265198 100644
--- a/course/amd/build/actions.min.js.map
+++ b/course/amd/build/actions.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/actions.js"],"names":["define","$","ajax","templates","notification","str","url","Y","ModalFactory","ModalEvents","KeyCodes","log","editor","EventDispatcher","CourseEvents","componentActions","courseeditor","getCurrentCourseEditor","formatname","CSS","EDITINPROGRESS","SECTIONDRAGGABLE","EDITINGMOVE","SELECTOR","ACTIVITYLI","ACTIONAREA","ACTIVITYACTION","MENU","TOGGLE","SECTIONLI","SECTIONACTIONMENU","ADDSECTIONS","use","courseformatselector","M","course","format","get_section_selector","dispatchEvent","eventName","detail","container","options","Element","get","getModuleId","element","item","dataset","id","Moodle","core_course","util","cm","getId","Node","getModuleName","name","getName","state","cmid","addActivitySpinner","activity","addClass","actionarea","find","spinner","add_spinner","show","data","dispatch","addSectionSpinner","sectionelement","addSectionLightbox","lightbox","add_lightbox","removeSpinner","delay","window","setTimeout","removeClass","hide","mutation","removeLightbox","initActionMenu","elementid","coursebase","invoke_function","core","actionmenu","newDOMNode","one","focusActionItem","elementId","action","mainelement","selector","is","focus","findNextFocusable","mainElement","tabables","isInside","foundElement","each","contains","editModule","moduleElement","target","attr","promises","call","methodname","args","sectionreturn","closest","when","apply","done","elementToFocus","replaceWith","affectedids","index","push","trigger","Event","ajaxreturn","fail","ex","e","exception","isDefaultPrevented","refreshModule","sectionReturn","activityElement","Promise","resolve","reject","replaceActivityHtmlWith","confirmDeleteModule","onconfirm","modtypename","match","modulename","get_string","pluginname","get_strings","key","component","param","type","s","confirm","confirmEditSection","message","replaceActionItem","actionitem","image","stringname","stringcomponent","newaction","then","strings","html","renderPix","pixhtml","catch","defaultEditSectionHandler","sectionElement","actionItem","courseformat","sectionid","modules","i","section_availability","first","section","oldmarker","oldActionItem","getActivityFocusedElement","document","getElementById","activeElement","querySelector","activityHTML","focusedPath","newItem","editSection","supportComponents","includes","dataencoded","parseJSON","register_module","set_visibility_resource_ui","getDOMNode","updateMovedCmState","params","updateMovedSectionState","addMutations","legacyActivityAction","statemanager","setReadOnly","locked","cmlist","reduce","current","delete","visible","legacySectionAction","forEach","initCoursePage","on","keyCode","moduleId","preventDefault","sectionId","isExecuted","itemid","strNumberSections","modalTitle","newSections","modalBody","create","title","types","SAVE_CANCEL","body","modal","numSections","getBody","addSections","parseInt","val","location","setSaveButtonText","getRoot","shown","select","enter","save","replaceSectionActionItem","debug","refreshSection","newSectionElement","content","event","sectionRefreshed","defaultPrevented"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Various actions on modules and sections in the editing mode - hiding, duplicating, deleting, etc.\n *\n * @module core_course/actions\n * @copyright 2016 Marina Glancy\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 3.3\n */\ndefine(\n [\n 'jquery',\n 'core/ajax',\n 'core/templates',\n 'core/notification',\n 'core/str',\n 'core/url',\n 'core/yui',\n 'core/modal_factory',\n 'core/modal_events',\n 'core/key_codes',\n 'core/log',\n 'core_courseformat/courseeditor',\n 'core/event_dispatcher',\n 'core_course/events'\n ],\n function(\n $,\n ajax,\n templates,\n notification,\n str,\n url,\n Y,\n ModalFactory,\n ModalEvents,\n KeyCodes,\n log,\n editor,\n EventDispatcher,\n CourseEvents\n ) {\n\n // Eventually, core_courseformat/local/content/actions will handle all actions for\n // component compatible formats and the default actions.js won't be necessary anymore.\n // Meanwhile, we filter the migrated actions.\n const componentActions = ['moveSection', 'moveCm', 'addSection', 'deleteSection'];\n\n // The course reactive instance.\n const courseeditor = editor.getCurrentCourseEditor();\n\n // The current course format name (loaded on init).\n let formatname;\n\n var CSS = {\n EDITINPROGRESS: 'editinprogress',\n SECTIONDRAGGABLE: 'sectiondraggable',\n EDITINGMOVE: 'editing_move'\n };\n var SELECTOR = {\n ACTIVITYLI: 'li.activity',\n ACTIONAREA: '.actions',\n ACTIVITYACTION: 'a.cm-edit-action',\n MENU: '.moodle-actionmenu[data-enhance=moodle-core-actionmenu]',\n TOGGLE: '.toggle-display,.dropdown-toggle',\n SECTIONLI: 'li.section',\n SECTIONACTIONMENU: '.section_action_menu',\n ADDSECTIONS: '.changenumsections [data-add-sections]'\n };\n\n Y.use('moodle-course-coursebase', function() {\n var courseformatselector = M.course.format.get_section_selector();\n if (courseformatselector) {\n SELECTOR.SECTIONLI = courseformatselector;\n }\n });\n\n /**\n * Dispatch event wrapper.\n *\n * Old jQuery events will be replaced by native events gradually.\n *\n * @method dispatchEvent\n * @param {String} eventName The name of the event\n * @param {Object} detail Any additional details to pass into the eveent\n * @param {Node|HTMLElement} container The point at which to dispatch the event\n * @param {Object} options\n * @param {Boolean} options.bubbles Whether to bubble up the DOM\n * @param {Boolean} options.cancelable Whether preventDefault() can be called\n * @param {Boolean} options.composed Whether the event can bubble across the ShadowDOM boundary\n * @returns {CustomEvent}\n */\n const dispatchEvent = function(eventName, detail, container, options) {\n // Most actions still uses jQuery node instead of regular HTMLElement.\n if (!(container instanceof Element) && container.get !== undefined) {\n container = container.get(0);\n }\n return EventDispatcher.dispatchEvent(eventName, detail, container, options);\n };\n\n /**\n * Wrapper for Y.Moodle.core_course.util.cm.getId\n *\n * @param {JQuery} element\n * @returns {Integer}\n */\n var getModuleId = function(element) {\n // Check if we have a data-id first.\n const item = element.get(0);\n if (item.dataset.id) {\n return item.dataset.id;\n }\n // Use YUI way if data-id is not present.\n let id;\n Y.use('moodle-course-util', function(Y) {\n id = Y.Moodle.core_course.util.cm.getId(Y.Node(item));\n });\n return id;\n };\n\n /**\n * Wrapper for Y.Moodle.core_course.util.cm.getName\n *\n * @param {JQuery} element\n * @returns {String}\n */\n var getModuleName = function(element) {\n var name;\n Y.use('moodle-course-util', function(Y) {\n name = Y.Moodle.core_course.util.cm.getName(Y.Node(element.get(0)));\n });\n // Check if we have the name in the course state.\n const state = courseeditor.state;\n const cmid = getModuleId(element);\n if (!name && state && cmid) {\n name = state.cm.get(cmid)?.name;\n }\n return name;\n };\n\n /**\n * Wrapper for M.util.add_spinner for an activity\n *\n * @param {JQuery} activity\n * @returns {Node}\n */\n var addActivitySpinner = function(activity) {\n activity.addClass(CSS.EDITINPROGRESS);\n var actionarea = activity.find(SELECTOR.ACTIONAREA).get(0);\n if (actionarea) {\n var spinner = M.util.add_spinner(Y, Y.Node(actionarea));\n spinner.show();\n // Lock the activity state element.\n if (activity.data('id') !== undefined) {\n courseeditor.dispatch('cmLock', [activity.data('id')], true);\n }\n return spinner;\n }\n return null;\n };\n\n /**\n * Wrapper for M.util.add_spinner for a section\n *\n * @param {JQuery} sectionelement\n * @returns {Node}\n */\n var addSectionSpinner = function(sectionelement) {\n sectionelement.addClass(CSS.EDITINPROGRESS);\n var actionarea = sectionelement.find(SELECTOR.SECTIONACTIONMENU).get(0);\n if (actionarea) {\n var spinner = M.util.add_spinner(Y, Y.Node(actionarea));\n spinner.show();\n // Lock the section state element.\n if (sectionelement.data('id') !== undefined) {\n courseeditor.dispatch('sectionLock', [sectionelement.data('id')], true);\n }\n return spinner;\n }\n return null;\n };\n\n /**\n * Wrapper for M.util.add_lightbox\n *\n * @param {JQuery} sectionelement\n * @returns {Node}\n */\n var addSectionLightbox = function(sectionelement) {\n var lightbox = M.util.add_lightbox(Y, Y.Node(sectionelement.get(0)));\n lightbox.show();\n return lightbox;\n };\n\n /**\n * Removes the spinner element\n *\n * @param {JQuery} element\n * @param {Node} spinner\n * @param {Number} delay\n */\n var removeSpinner = function(element, spinner, delay) {\n window.setTimeout(function() {\n element.removeClass(CSS.EDITINPROGRESS);\n if (spinner) {\n spinner.hide();\n }\n // Unlock the state element.\n if (element.data('id') !== undefined) {\n const mutation = (element.data('for') === 'section') ? 'sectionLock' : 'cmLock';\n courseeditor.dispatch(mutation, [element.data('id')], false);\n }\n }, delay);\n };\n\n /**\n * Removes the lightbox element\n *\n * @param {Node} lightbox lighbox YUI element returned by addSectionLightbox\n * @param {Number} delay\n */\n var removeLightbox = function(lightbox, delay) {\n if (lightbox) {\n window.setTimeout(function() {\n lightbox.hide();\n }, delay);\n }\n };\n\n /**\n * Initialise action menu for the element (section or module)\n *\n * @param {String} elementid CSS id attribute of the element\n */\n var initActionMenu = function(elementid) {\n // Initialise action menu in the new activity.\n Y.use('moodle-course-coursebase', function() {\n M.course.coursebase.invoke_function('setup_for_resource', '#' + elementid);\n });\n if (M.core.actionmenu && M.core.actionmenu.newDOMNode) {\n M.core.actionmenu.newDOMNode(Y.one('#' + elementid));\n }\n };\n\n /**\n * Returns focus to the element that was clicked or \"Edit\" link if element is no longer visible.\n *\n * @param {String} elementId CSS id attribute of the element\n * @param {String} action data-action property of the element that was clicked\n */\n var focusActionItem = function(elementId, action) {\n var mainelement = $('#' + elementId);\n var selector = '[data-action=' + action + ']';\n if (action === 'groupsseparate' || action === 'groupsvisible' || action === 'groupsnone') {\n // New element will have different data-action.\n selector = '[data-action=groupsseparate],[data-action=groupsvisible],[data-action=groupsnone]';\n }\n if (mainelement.find(selector).is(':visible')) {\n mainelement.find(selector).focus();\n } else {\n // Element not visible, focus the \"Edit\" link.\n mainelement.find(SELECTOR.MENU).find(SELECTOR.TOGGLE).focus();\n }\n };\n\n /**\n * Find next after the element\n *\n * @param {JQuery} mainElement element that is about to be deleted\n * @returns {JQuery}\n */\n var findNextFocusable = function(mainElement) {\n var tabables = $(\"a:visible\");\n var isInside = false;\n var foundElement = null;\n tabables.each(function() {\n if ($.contains(mainElement[0], this)) {\n isInside = true;\n } else if (isInside) {\n foundElement = this;\n return false; // Returning false in .each() is equivalent to \"break;\" inside the loop in php.\n }\n return true;\n });\n return foundElement;\n };\n\n /**\n * Performs an action on a module (moving, deleting, duplicating, hiding, etc.)\n *\n * @param {JQuery} moduleElement activity element we perform action on\n * @param {Number} cmid\n * @param {JQuery} target the element (menu item) that was clicked\n */\n var editModule = function(moduleElement, cmid, target) {\n var action = target.attr('data-action');\n var spinner = addActivitySpinner(moduleElement);\n var promises = ajax.call([{\n methodname: 'core_course_edit_module',\n args: {id: cmid,\n action: action,\n sectionreturn: target.attr('data-sectionreturn') ? target.attr('data-sectionreturn') : 0\n }\n }], true);\n\n var lightbox;\n if (action === 'duplicate') {\n lightbox = addSectionLightbox(target.closest(SELECTOR.SECTIONLI));\n }\n $.when.apply($, promises)\n .done(function(data) {\n var elementToFocus = findNextFocusable(moduleElement);\n moduleElement.replaceWith(data);\n let affectedids = [];\n // Initialise action menu for activity(ies) added as a result of this.\n $('
{{/uservisible}}
diff --git a/course/format/tests/behat/courseindex_keyboardnav.feature b/course/format/tests/behat/courseindex_keyboardnav.feature
index 34a5d40063603..46d746a3b0249 100644
--- a/course/format/tests/behat/courseindex_keyboardnav.feature
+++ b/course/format/tests/behat/courseindex_keyboardnav.feature
@@ -20,14 +20,14 @@ Feature: Verify that courseindex is usable with the keyboard
And I click on "Side panel" "button"
And I click on "Open course index drawer" "button"
And I should see "Topic 1" in the "courseindex-content" "region"
- And the focused element is ".drawertoggle" "css_element"
+ And the focused element is "[data-preference='drawer-open-index'] .drawertoggle" "css_element"
And I press the tab key
Then the focused element is ".courseindex-section" "css_element"
@javascript
Scenario: General focus on open course index.
When I press the shift tab key
- And the focused element is ".drawertoggle" "css_element"
+ And the focused element is "[data-preference='drawer-open-index'] .drawertoggle" "css_element"
And I press enter
Then I should not see "Topic 1" in the "courseindex-content" "region"
diff --git a/course/index.php b/course/index.php
index 6688b5471ffd9..910530f43512c 100644
--- a/course/index.php
+++ b/course/index.php
@@ -65,7 +65,6 @@
$PAGE->set_heading($heading);
$content = $courserenderer->course_category($categoryid);
-$PAGE->set_primary_active_tab('courses');
$PAGE->set_secondary_active_tab('categorymain');
echo $OUTPUT->header();
diff --git a/course/tests/behat/activities_edit_name.feature b/course/tests/behat/activities_edit_name.feature
index 18217384e980f..1a98500d68730 100644
--- a/course/tests/behat/activities_edit_name.feature
+++ b/course/tests/behat/activities_edit_name.feature
@@ -4,8 +4,7 @@ Feature: Edit activity name in-place
As a teacher
I need to use inplace editing
- @javascript
- Scenario: Edit activity name in-place
+ Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
@@ -21,6 +20,9 @@ Feature: Edit activity name in-place
| name | Test forum name |
| description | Test forum description |
| idnumber | forum1 |
+
+ @javascript
+ Scenario: Edit activity name in-place
When I log in as "teacher1"
And I am on "Course 1" course homepage with editing mode on
# Rename activity
@@ -41,3 +43,11 @@ Feature: Edit activity name in-place
And I am on "Course 1" course homepage
And I should see "Good news"
And I should not see "Terrible news"
+
+ @javascript
+ Scenario: Edit activity name in-place ensuring correct encoding
+ When I log in as "teacher1"
+ And I am on "Course 1" course homepage with editing mode on
+ And I set the field "Edit title" in the "Test forum name" "activity" to "Good & bad news"
+ Then I should not see "Test forum name" in the ".course-content" "css_element"
+ And I should see "Good & bad news" in the ".course-content" "css_element"
diff --git a/enrol/fee/templates/payment_region.mustache b/enrol/fee/templates/payment_region.mustache
index 7123554364812..a1bbdc5cbacda 100644
--- a/enrol/fee/templates/payment_region.mustache
+++ b/enrol/fee/templates/payment_region.mustache
@@ -67,7 +67,7 @@
data-itemid="{{instanceid}}"
data-cost="{{cost}}"
data-successurl="{{successurl}}"
- data-description={{# quote }}{{description}}{{/ quote }}
+ data-description="{{description}}"
>
{{# str }} sendpaymentbutton, enrol_fee {{/ str }}
diff --git a/enrol/lti/templates/copy_grid.mustache b/enrol/lti/templates/copy_grid.mustache
index fee6faf8e6ded..1adb662664fa1 100644
--- a/enrol/lti/templates/copy_grid.mustache
+++ b/enrol/lti/templates/copy_grid.mustache
@@ -49,7 +49,7 @@
{{#rows}}
{{> core/copy_box }}
diff --git a/grade/report/grader/tests/behat/switch_views.feature b/grade/report/grader/tests/behat/switch_views.feature
index fa65ba83ef95d..98b764b86c173 100644
--- a/grade/report/grader/tests/behat/switch_views.feature
+++ b/grade/report/grader/tests/behat/switch_views.feature
@@ -38,7 +38,6 @@ Feature: We can change what we are viewing on the grader report
And I give the grade "80.00" to the user "Student 1" for the grade item "Test assignment name 1"
And I give the grade "90.00" to the user "Student 1" for the grade item "Test assignment name 2"
And I press "Save changes"
- And I turn editing mode off
@javascript
Scenario: View and minimise the grader report containing hidden activities
diff --git a/grade/report/history/classes/helper.php b/grade/report/history/classes/helper.php
index 1ff2d1eb33e5f..189cbf7b02261 100644
--- a/grade/report/history/classes/helper.php
+++ b/grade/report/history/classes/helper.php
@@ -129,10 +129,13 @@ public static function get_users_count($context, $search = '') {
*/
protected static function get_users_sql_and_params($context, $search = '', $count = false) {
global $DB, $USER;
-
+ $userfieldsapi = \core_user\fields::for_identity($context)->with_userpic()->including('username');
+ $userfieldssql = $userfieldsapi->get_sql('u', true, '', '', false);
// Fields we need from the user table.
- // TODO Does not support custom user profile fields (MDL-70456).
- $extrafields = \core_user\fields::get_identity_fields($context, false);
+ $extrafields = [];
+ foreach ($userfieldsapi->get_required_fields([\core_user\fields::PURPOSE_IDENTITY]) as $field) {
+ $extrafields[$field] = $userfieldssql->mappings[$field];
+ }
$params = array();
if (!empty($search)) {
list($filtersql, $params) = users_search_sql($search, 'u', true, $extrafields);
@@ -141,13 +144,12 @@ protected static function get_users_sql_and_params($context, $search = '', $coun
$filtersql = '';
}
- $userfieldsapi = \core_user\fields::for_userpic()->including(...(array_merge($extrafields, ['username'])));
- $ufields = $userfieldsapi->get_sql('u', false, '', '', false)->selects;
+ $userfieldjoinssql = $userfieldssql->joins;
if ($count) {
$select = "SELECT COUNT(DISTINCT u.id) ";
$orderby = "";
} else {
- $select = "SELECT DISTINCT $ufields ";
+ $select = "SELECT DISTINCT $userfieldssql->selects ";
$orderby = " ORDER BY u.lastname ASC, u.firstname ASC";
}
@@ -161,7 +163,6 @@ protected static function get_users_sql_and_params($context, $search = '', $coun
if ($groupmode == SEPARATEGROUPS && !has_capability('moodle/site:accessallgroups', $context)) {
// Fetch the groups that the user can see.
$groups = groups_get_all_groups($courseid, $USER->id, 0, 'g.id');
-
// Add join condition to include users that only belong to the same group as the user.
list($insql, $inparams) = $DB->get_in_or_equal(array_keys($groups), SQL_PARAMS_NAMED, 'gid', true, 0);
$groupjoinsql = " JOIN {groups_members} gm ON gm.userid = u.id ";
@@ -173,11 +174,12 @@ protected static function get_users_sql_and_params($context, $search = '', $coun
FROM {user} u
JOIN {grade_grades_history} ggh ON u.id = ggh.userid
JOIN {grade_items} gi ON gi.id = ggh.itemid
+ $userfieldjoinssql
$groupjoinsql
WHERE $filtersql gi.courseid = :courseid $groupwheresql";
$sql .= $orderby;
$params['courseid'] = $courseid;
-
+ $params = array_merge($userfieldssql->params, $params);
return array($sql, $params);
}
diff --git a/grade/report/history/classes/output/tablelog.php b/grade/report/history/classes/output/tablelog.php
index 663e29488f8f1..afacc119d352e 100644
--- a/grade/report/history/classes/output/tablelog.php
+++ b/grade/report/history/classes/output/tablelog.php
@@ -140,8 +140,7 @@ protected function define_table_configs(\moodle_url $url) {
* Setup the headers for the html table.
*/
protected function define_table_columns() {
- // TODO Does not support custom user profile fields (MDL-70456).
- $extrafields = \core_user\fields::get_identity_fields($this->context, false);
+ $extrafields = \core_user\fields::get_identity_fields($this->context);
// Define headers and columns.
$cols = array(
@@ -154,7 +153,7 @@ protected function define_table_columns() {
if (get_string_manager()->string_exists($field, 'moodle')) {
$cols[$field] = get_string($field);
} else {
- $cols[$field] = $field;
+ $cols[$field] = \core_user\fields::get_display_name($field);
}
}
@@ -394,15 +393,24 @@ protected function get_sql_and_params($count = false) {
ggh.source, ggh.overridden, ggh.locked, ggh.excluded, ggh.feedback, ggh.feedbackformat,
gi.itemtype, gi.itemmodule, gi.iteminstance, gi.itemnumber, ';
+ $userfieldsapi = \core_user\fields::for_identity($this->context);
+ $userfieldssql = $userfieldsapi->get_sql('u', true, '', '', true);
+ $userfieldsselects = '';
+ $userfieldsjoins = '';
+ $userfieldsparams = [];
+ if (!$count) {
+ $userfieldsselects = $userfieldssql->selects;
+ $userfieldsjoins = $userfieldssql->joins;
+ $userfieldsparams = $userfieldssql->params;
+ }
+
// Add extra user fields that we need for the graded user.
- // TODO Does not support custom user profile fields (MDL-70456).
- $extrafields = \core_user\fields::get_identity_fields($this->context, false);
- foreach ($extrafields as $field) {
- $fields .= 'u.' . $field . ', ';
+ $extrafields = [];
+ foreach ($userfieldsapi->get_required_fields([\core_user\fields::PURPOSE_IDENTITY]) as $field) {
+ $extrafields[$field] = $userfieldssql->mappings[$field];
}
$userfieldsapi = \core_user\fields::for_name();
- $gradeduserfields = $userfieldsapi->get_sql('u', false, '', '', false)->selects;
- $fields .= $gradeduserfields . ', ';
+ $fields .= $userfieldsapi->get_sql('u', false, '', '', false)->selects . ', ';
$groupby = $fields;
// Add extra user fields that we need for the grader user.
@@ -437,12 +445,14 @@ protected function get_sql_and_params($count = false) {
list($where, $params) = $this->get_filters_sql_and_params();
- $sql = "SELECT $select
+ $sql = " SELECT $select $userfieldsselects
FROM {grade_grades_history} ggh
JOIN {grade_items} gi ON gi.id = ggh.itemid
JOIN {user} u ON u.id = ggh.userid
+ $userfieldsjoins
LEFT JOIN {user} ug ON ug.id = ggh.usermodified
WHERE $where";
+ $params = array_merge($userfieldsparams, $params);
// As prevgrade is a dynamic field, we need to wrap the query. This is the only filtering
// that should be defined outside the method self::get_filters_sql_and_params().
diff --git a/grade/report/history/templates/user_button.mustache b/grade/report/history/templates/user_button.mustache
index 15cd1303c183f..1c881e07787f3 100644
--- a/grade/report/history/templates/user_button.mustache
+++ b/grade/report/history/templates/user_button.mustache
@@ -47,8 +47,8 @@
{{/params}}
diff --git a/grade/report/history/tests/behat/basic_functionality.feature b/grade/report/history/tests/behat/basic_functionality.feature
index bb5ecbc0b5cf6..25972ec3a9e57 100644
--- a/grade/report/history/tests/behat/basic_functionality.feature
+++ b/grade/report/history/tests/behat/basic_functionality.feature
@@ -9,12 +9,15 @@ Feature: A teacher checks the grade history report in a course
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
+ And the following "custom profile fields" exist:
+ | datatype | shortname | name |
+ | text | food | Favourite food |
And the following "users" exist:
- | username | firstname | lastname | email |
- | teacher1 | Teacher | 1 | teacher1@example.com |
- | teacher2 | Teacher | 2 | teacher2@example.com |
- | student1 | Student | 1 | student1@example.com |
- | student2 | Student | 2 | student2@example.com |
+ | username | firstname | lastname | email | profile_field_food |
+ | teacher1 | Teacher | 1 | teacher1@example.com | |
+ | teacher2 | Teacher | 2 | teacher2@example.com | |
+ | student1 | Student | 1 | student1@example.com | apple |
+ | student2 | Student | 2 | student2@example.com | orange |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
@@ -25,9 +28,13 @@ Feature: A teacher checks the grade history report in a course
| activity | course | section | name | intro |
| assign | C1 | 1 | The greatest assignment ever | Write a behat test for Moodle - it's amazing |
| assign | C1 | 1 | Rewarding assignment | After writing your behat test go grab a beer! |
+ Given the following config values are set as admin:
+ | showuseridentity | email,profile_field_food |
And I log in as "teacher1"
And I am on "Course 1" course homepage with editing mode on
And I navigate to "View > Grader report" in the course gradebook
+ And I should see "apple" in the "student1" "table_row"
+ And I should see "orange" in the "student2" "table_row"
And I turn editing mode on
And I give the grade "50.00" to the user "Student 1" for the grade item "The greatest assignment ever"
And I give the grade "60.00" to the user "Student 1" for the grade item "Rewarding assignment"
@@ -38,6 +45,8 @@ Feature: A teacher checks the grade history report in a course
And I log in as "teacher2"
And I am on "Course 1" course homepage
And I navigate to "View > Grader report" in the course gradebook
+ And I should see "apple" in the "student1" "table_row"
+ And I should see "orange" in the "student2" "table_row"
And I turn editing mode on
And I give the grade "70.00" to the user "Student 1" for the grade item "The greatest assignment ever"
And I give the grade "80.00" to the user "Student 1" for the grade item "Rewarding assignment"
@@ -47,15 +56,15 @@ Feature: A teacher checks the grade history report in a course
And I follow "Grade history"
When I press "Submit"
Then the following should exist in the "gradereport_history" table:
- | First name/Surname | Grade item | Original grade | Revised grade | Grader |
- | Student 1 | The greatest assignment ever | | 50.00 | Teacher 1 |
- | Student 1 | Rewarding assignment | | 60.00 | Teacher 1 |
- | Student 2 | The greatest assignment ever | | 50.00 | Teacher 1 |
- | Student 2 | Rewarding assignment | | 60.00 | Teacher 1 |
- | Student 1 | The greatest assignment ever | 50.00 | 70.00 | Teacher 2 |
- | Student 1 | Rewarding assignment | 60.00 | 80.00 | Teacher 2 |
- | Student 2 | The greatest assignment ever | 50.00 | 70.00 | Teacher 2 |
- | Student 2 | Rewarding assignment | 60.00 | 80.00 | Teacher 2 |
+ | First name/Surname | Email address | Favourite food | Grade item | Original grade | Revised grade | Grader |
+ | Student 1 | student1@example.com | apple | The greatest assignment ever | | 50.00 | Teacher 1 |
+ | Student 1 | student1@example.com | apple | Rewarding assignment | | 60.00 | Teacher 1 |
+ | Student 2 | student2@example.com | orange | The greatest assignment ever | | 50.00 | Teacher 1 |
+ | Student 2 | student2@example.com | orange | Rewarding assignment | | 60.00 | Teacher 1 |
+ | Student 1 | student1@example.com | apple | The greatest assignment ever | 50.00 | 70.00 | Teacher 2 |
+ | Student 1 | student1@example.com | apple | Rewarding assignment | 60.00 | 80.00 | Teacher 2 |
+ | Student 2 | student2@example.com | orange | The greatest assignment ever | 50.00 | 70.00 | Teacher 2 |
+ | Student 2 | student2@example.com | orange | Rewarding assignment | 60.00 | 80.00 | Teacher 2 |
# Test filtering by student.
And I press "Select users"
And I set the field with xpath "//form/input[@class='usp-search-field']" to "Student 1"
@@ -69,6 +78,9 @@ Feature: A teacher checks the grade history report in a course
| Student 1 | Rewarding assignment | | 60.00 | Teacher 1 |
| Student 1 | The greatest assignment ever | 50.00 | 70.00 | Teacher 2 |
| Student 1 | Rewarding assignment | 60.00 | 80.00 | Teacher 2 |
+ # Test for seeing custom fields contents in the rows.
+ And I should see "apple" in the "student1" "table_row"
+ And I should not see "orange"
And the following should not exist in the "gradereport_history" table:
| Student 2 | The greatest assignment ever | | 50.00 | Teacher 1 |
| Student 2 | Rewarding assignment | | 60.00 | Teacher 1 |
@@ -88,13 +100,13 @@ Feature: A teacher checks the grade history report in a course
And I set the field "Grader" to "Teacher 1"
And I press "Submit"
And the following should exist in the "gradereport_history" table:
- | First name/Surname | Grade item | Original grade | Revised grade | Grader |
- | Student 1 | The greatest assignment ever | | 50.00 | Teacher 1 |
+ | First name/Surname | Email address | Favourite food | Grade item | Original grade | Revised grade | Grader |
+ | Student 1 | student1@example.com | apple | The greatest assignment ever | | 50.00 | Teacher 1 |
And the following should not exist in the "gradereport_history" table:
| Student 1 | The greatest assignment ever | 50.00 | 70.00 | Teacher 2 |
# Test filtering by revised grades.
And I click on "id_revisedonly" "checkbox"
And I press "Submit"
And the following should exist in the "gradereport_history" table:
- | First name/Surname | Grade item | Original grade | Revised grade | Grader |
- | Student 1 | The greatest assignment ever | | 50.00 | Teacher 1 |
+ | First name/Surname | Email address | Favourite food | Grade item | Original grade | Revised grade | Grader |
+ | Student 1 | student1@example.com | apple | The greatest assignment ever | | 50.00 | Teacher 1 |
diff --git a/grade/report/history/tests/report_test.php b/grade/report/history/tests/report_test.php
index 7a58ae1363eda..24e407cbb39bc 100644
--- a/grade/report/history/tests/report_test.php
+++ b/grade/report/history/tests/report_test.php
@@ -241,6 +241,159 @@ public function test_get_users() {
$this->assertEquals(1, \gradereport_history\helper::get_users_count($c1ctx, 'c'));
}
+ /**
+ * Data provider for \gradereport_history_report_testcase::test_get_users_with_profile_fields()
+ * Testing get_users() and get_users_count() test cases.
+ *
+ * @return array List of data sets (test cases)
+ */
+ public function get_users_with_profile_fields_provider(): array {
+ return [
+ // User identity check boxes, 'email', 'profile_field_lang' and 'profile_field_height' are checked.
+ 'show email,lang and height;search for all users' =>
+ ['email,profile_field_lang,profile_field_height', '', ['u1', 'u2', 'u3', 'u4']],
+ 'show email,lang and height;search for users on .org ' =>
+ ['email,profile_field_lang,profile_field_height', '.org', ['u1', 'u2', 'u4']],
+ 'show email,lang and height;search for users on .com ' =>
+ ['email,profile_field_lang,profile_field_height', '.com', []],
+ 'show email,lang and height;search for users on .uk ' =>
+ ['email,profile_field_lang,profile_field_height', '.uk', ['u3']],
+ 'show email,lang and height,search for Spanish speakers' =>
+ ['email,profile_field_lang,profile_field_height', 'spanish', ['u1', 'u4']],
+ 'show email,lang and height,search for Spanish speakers' =>
+ ['email,profile_field_lang,profile_field_height', 'spa', ['u1', 'u4']],
+ 'show email,lang and height,search for German speakers' =>
+ ['email,profile_field_lang,profile_field_height', 'german', ['u2']],
+ 'show email,lang and height,search for German speakers' =>
+ ['email,profile_field_lang,profile_field_height', 'ger', ['u2']],
+ 'show email,lang and height,search for English speakers' =>
+ ['email,profile_field_lang,profile_field_height', 'english', ['u3']],
+ 'show email,lang and height,search for English speakers' =>
+ ['email,profile_field_lang,profile_field_height', 'eng', ['u3']],
+ 'show email,lang and height,search for English speakers' =>
+ ['email,profile_field_lang,profile_field_height', 'ish', ['u3']],
+ 'show email,lang and height,search for users with height 180cm' =>
+ ['email,profile_field_lang,profile_field_height', '180cm', ['u2', 'u3', 'u4']],
+ 'show email,lang and height,search for users with height 180cm' =>
+ ['email,profile_field_lang,profile_field_height', '180', ['u2', 'u3', 'u4']],
+ 'show email,lang and height,search for users with height 170cm' =>
+ ['email,profile_field_lang,profile_field_height', '170cm', ['u1']],
+ 'show email,lang and height,search for users with height 170cm' =>
+ ['email,profile_field_lang,profile_field_height', '170', ['u1']],
+
+ // User identity check boxes, 'email' and 'profile_field_height' are checked.
+ 'show email and height;search for users on .org' =>
+ ['email,profile_field_height', '.org', ['u1', 'u2', 'u4']],
+ 'show email and height;search for users on .com' =>
+ ['email,profile_field_height', '.com', []],
+ 'show email and height;search for users on .co' =>
+ ['email,profile_field_height', '.co', ['u3']],
+ 'show email and height,search for Spanish/German/English speakers' =>
+ ['email,profile_field_height', 'spanish', []],
+ 'show email and height,search for Spanish/German/English speakers' =>
+ ['email,profile_field_height', 'german', []],
+ 'show email and height,search for Spanish/German/English speakers' =>
+ ['email,profile_field_height', 'english', []],
+ 'show email,lang and height,search for English speakers' =>
+ ['email,profile_field_height', 'english', []],
+ 'show email and height,search for English speakers' =>
+ ['email,profile_field_height', 'eng', []],
+ 'show email and height,search for English speakers' =>
+ ['email,profile_field_height', 'ish', []],
+ 'show email and height,search for users with height 180cm' =>
+ ['email,profile_field_height', '180cm', ['u2', 'u3', 'u4']],
+ 'show email,lang and height,search for users with height 180cm' =>
+ ['email,profile_field_height', '180', ['u2', 'u3', 'u4']],
+ 'show email,lang and height,search for users with height 170cm' =>
+ ['email,profile_field_height', '170cm', ['u1']],
+ 'show email,lang and height,search for users with height 170cm' =>
+ ['email,profile_field_height', '170', ['u1']],
+
+ // User identity check boxes, only 'email' is checked.
+ 'show email only;search for users on .org' => ['email', '.org', ['u1', 'u2', 'u4']],
+ 'show email only;search for users on .com' => ['email', '.com', []],
+ 'show email only;search for users on .co.uk' => ['email', 'co.uk', ['u3']],
+ 'show email only;search for users on .uk' => ['email', '.uk', ['u3']],
+ 'show email only;search for users on .co' => ['email', '.co', ['u3']],
+ 'show email only;search for Spanish speakers' => ['email', 'spanish', []],
+ 'show email only;search for German speakers' => ['email', 'german', []],
+ 'show email only;search for English speakers' => ['email', 'english', []],
+ 'show email only;search for users with height 180cm' => ['email', '180cm', []],
+ 'show email only;search for users with height 180cm' => ['email', '180', []],
+ 'show email only;search for users with height 170cm' => ['email', '170cm', []],
+ 'show email only;search for users with height 170cm' => ['email', '170', []],
+ ];
+ }
+
+ /**
+ * Testing the search functionality on get_users() and get_users_count() and their inner methods.
+ *
+ * @dataProvider get_users_with_profile_fields_provider
+ *
+ * @param string $showuseridentity, list of user identities to be shown.
+ * @param string $searchstring, the string to be searched.
+ * @param array $expectedusernames, a list of expected usernames.
+ * @return void
+ */
+ public function test_get_users_with_profile_fields(string $showuseridentity, string $searchstring,
+ array $expectedusernames): void {
+ global $CFG, $DB;
+ require_once($CFG->dirroot . '/user/profile/lib.php');
+ $this->resetAfterTest();
+
+ // Create a couple of custom profile fields, which are in user identity.
+ $generator = $this->getDataGenerator();
+ $generator->create_custom_profile_field(['datatype' => 'text',
+ 'shortname' => 'lang', 'name' => 'Language']);
+ $generator->create_custom_profile_field(['datatype' => 'text',
+ 'shortname' => 'height', 'name' => 'Height']);
+
+ // Create a couple of test users.
+ $u1 = $generator->create_user(['firstname' => 'Eduardo', 'lastname' => 'Gomes',
+ 'username' => 'u1', 'email' => 'u1@x.org', 'profile_field_lang' => 'Spanish',
+ 'profile_field_height' => '170cm']);
+ $u2 = $generator->create_user(['firstname' => 'Dieter', 'lastname' => 'Schmitt',
+ 'username' => 'u2', 'email' => 'u2@x.org', 'profile_field_lang' => 'German',
+ 'profile_field_height' => '180cm']);
+
+ $u3 = $generator->create_user(['firstname' => 'Peter', 'lastname' => 'Jones',
+ 'username' => 'u3', 'email' => 'u3@x.co.uk', 'profile_field_lang' => 'English',
+ 'profile_field_height' => '180cm']);
+ $u4 = $generator->create_user(['firstname' => 'Pedro', 'lastname' => 'Gomes',
+ 'username' => 'u4', 'email' => 'u3@x.org', 'profile_field_lang' => 'Spanish',
+ 'profile_field_height' => '180cm']);
+
+ // Do this as admin user.
+ $this->setAdminUser();
+
+ // Making the setup.
+ $c1 = $this->getDataGenerator()->create_course();
+ $c1ctx = context_course::instance($c1->id);
+ $c1m1 = $this->getDataGenerator()->create_module('assign', array('course' => $c1));
+
+ // Creating grade history for some users.
+ $gi = grade_item::fetch(array('iteminstance' => $c1m1->id, 'itemtype' => 'mod', 'itemmodule' => 'assign'));
+ $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id));
+ $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u2->id));
+ $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u3->id));
+ $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u4->id));
+
+ // Checking fetching some users with this config settings.
+ set_config('showuseridentity', $showuseridentity);
+ $numberofexpectedusers = count($expectedusernames);
+ $users = \gradereport_history\helper::get_users($c1ctx, $searchstring);
+ $userscount = \gradereport_history\helper::get_users_count($c1ctx, $searchstring);
+ $this->assertEquals($numberofexpectedusers, $userscount);
+ $this->assertCount($numberofexpectedusers, $users);
+ foreach ($users as $user) {
+ if (in_array($user->username, $expectedusernames)) {
+ $this->assertArrayHasKey($user->id, $users);
+ } else {
+ $this->assertArrayNotHasKey($user->id, $users);
+ }
+ }
+ }
+
/**
* Data provider method for \gradereport_history_report_testcase::test_get_users_with_groups()
*/
diff --git a/grade/report/history/users_ajax.php b/grade/report/history/users_ajax.php
index 038cf0274d4dd..ede28aebc3b15 100644
--- a/grade/report/history/users_ajax.php
+++ b/grade/report/history/users_ajax.php
@@ -51,8 +51,8 @@
$outcome->response = array('users' => array());
$outcome->response['totalusers'] = \gradereport_history\helper::get_users_count($context, $search);;
-// TODO Does not support custom user profile fields (MDL-70456).
-$extrafields = \core_user\fields::get_identity_fields($context, false);
+$userfieldsapi = \core_user\fields::for_identity($context)->with_userpic();
+$extrafields = $userfieldsapi->get_required_fields([\core_user\fields::PURPOSE_IDENTITY]);
$useroptions = array('link' => false, 'visibletoscreenreaders' => false);
// Format the user record.
@@ -61,11 +61,11 @@
$newuser->userid = $user->id;
$newuser->picture = $OUTPUT->user_picture($user, $useroptions);
$newuser->fullname = fullname($user);
- $fieldvalues = array();
foreach ($extrafields as $field) {
- $fieldvalues[] = s($user->{$field});
+ if ($user->{$field}) {
+ $newuser->extrafields[] = $user->{$field};
+ }
}
- $newuser->extrafields = implode(', ', $fieldvalues);
$outcome->response['users'][] = $newuser;
}
diff --git a/grade/report/singleview/templates/button.mustache b/grade/report/singleview/templates/button.mustache
index 5d43733af4f1b..52de296e38b83 100644
--- a/grade/report/singleview/templates/button.mustache
+++ b/grade/report/singleview/templates/button.mustache
@@ -25,4 +25,4 @@
"value": "Save"
}
}}
-
+
diff --git a/grade/templates/edit_tree.mustache b/grade/templates/edit_tree.mustache
index eb678f87a8608..e9317ce42de20 100644
--- a/grade/templates/edit_tree.mustache
+++ b/grade/templates/edit_tree.mustache
@@ -51,7 +51,7 @@
{{{table}}}