diff --git a/communication/amd/build/providerchooser.min.js b/communication/amd/build/providerchooser.min.js
index b62029acef428..1504f7e6ab590 100644
--- a/communication/amd/build/providerchooser.min.js
+++ b/communication/amd/build/providerchooser.min.js
@@ -7,6 +7,6 @@ define("core_communication/providerchooser",["exports"],(function(_exports){Obje
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 4.2
*/
-const Selectors_fields={selector:'[data-communicationchooser-field="selector"]',updateButton:'[data-communicationchooser-field="updateButton"]'};_exports.init=()=>{document.querySelector(Selectors_fields.selector).addEventListener("change",(e=>{const form=e.target.closest("form"),updateButton=form.querySelector(Selectors_fields.updateButton),fieldset=updateButton.closest("fieldset"),url=new URL(form.action);url.hash=fieldset.id,form.action=url.toString(),updateButton.click()}))}}));
+const Selectors_fields={selector:'[data-communicationchooser-field="selector"]',updateButton:'[data-communicationchooser-field="updateButton"]'};_exports.init=()=>{document.querySelector(Selectors_fields.selector).addEventListener("change",(e=>{const form=e.target.closest("form"),updateButton=form.querySelector(Selectors_fields.updateButton),url=new URL(form.action);form.action=url.toString(),updateButton.click()}))}}));
//# sourceMappingURL=providerchooser.min.js.map
\ No newline at end of file
diff --git a/communication/amd/build/providerchooser.min.js.map b/communication/amd/build/providerchooser.min.js.map
index 2dd6bb97d4d5e..2869a533188b3 100644
--- a/communication/amd/build/providerchooser.min.js.map
+++ b/communication/amd/build/providerchooser.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"providerchooser.min.js","sources":["../src/providerchooser.js"],"sourcesContent":["\n// This file is part of Moodle - http://moodle.org/ //\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 * Communication provider selection handler.\n *\n * @module core_communication/communicationchooser\n * @copyright 2023 Safat Shahin \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.2\n */\n\nconst Selectors = {\n fields: {\n selector: '[data-communicationchooser-field=\"selector\"]',\n updateButton: '[data-communicationchooser-field=\"updateButton\"]',\n },\n};\n\n/**\n * Initialise the format chooser.\n */\nexport const init = () => {\n document.querySelector(Selectors.fields.selector).addEventListener('change', e => {\n const form = e.target.closest('form');\n const updateButton = form.querySelector(Selectors.fields.updateButton);\n const fieldset = updateButton.closest('fieldset');\n\n const url = new URL(form.action);\n url.hash = fieldset.id;\n\n form.action = url.toString();\n updateButton.click();\n });\n};\n"],"names":["Selectors","selector","updateButton","document","querySelector","addEventListener","e","form","target","closest","fieldset","url","URL","action","hash","id","toString","click"],"mappings":";;;;;;;;;MAwBMA,iBACM,CACJC,SAAU,+CACVC,aAAc,kEAOF,KAChBC,SAASC,cAAcJ,iBAAiBC,UAAUI,iBAAiB,UAAUC,UACnEC,KAAOD,EAAEE,OAAOC,QAAQ,QACxBP,aAAeK,KAAKH,cAAcJ,iBAAiBE,cACnDQ,SAAWR,aAAaO,QAAQ,YAEhCE,IAAM,IAAIC,IAAIL,KAAKM,QACzBF,IAAIG,KAAOJ,SAASK,GAEpBR,KAAKM,OAASF,IAAIK,WAClBd,aAAae"}
\ No newline at end of file
+{"version":3,"file":"providerchooser.min.js","sources":["../src/providerchooser.js"],"sourcesContent":["\n// This file is part of Moodle - http://moodle.org/ //\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 * Communication provider selection handler.\n *\n * @module core_communication/communicationchooser\n * @copyright 2023 Safat Shahin \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.2\n */\n\nconst Selectors = {\n fields: {\n selector: '[data-communicationchooser-field=\"selector\"]',\n updateButton: '[data-communicationchooser-field=\"updateButton\"]',\n },\n};\n\n/**\n * Initialise the format chooser.\n */\nexport const init = () => {\n document.querySelector(Selectors.fields.selector).addEventListener('change', e => {\n const form = e.target.closest('form');\n const updateButton = form.querySelector(Selectors.fields.updateButton);\n const url = new URL(form.action);\n\n form.action = url.toString();\n updateButton.click();\n });\n};\n"],"names":["Selectors","selector","updateButton","document","querySelector","addEventListener","e","form","target","closest","url","URL","action","toString","click"],"mappings":";;;;;;;;;MAwBMA,iBACM,CACJC,SAAU,+CACVC,aAAc,kEAOF,KAChBC,SAASC,cAAcJ,iBAAiBC,UAAUI,iBAAiB,UAAUC,UACnEC,KAAOD,EAAEE,OAAOC,QAAQ,QACxBP,aAAeK,KAAKH,cAAcJ,iBAAiBE,cACnDQ,IAAM,IAAIC,IAAIJ,KAAKK,QAEzBL,KAAKK,OAASF,IAAIG,WAClBX,aAAaY"}
\ No newline at end of file
diff --git a/communication/amd/src/providerchooser.js b/communication/amd/src/providerchooser.js
index ccfbe69b8907a..1e0b35d880d0d 100644
--- a/communication/amd/src/providerchooser.js
+++ b/communication/amd/src/providerchooser.js
@@ -36,10 +36,7 @@ export const init = () => {
document.querySelector(Selectors.fields.selector).addEventListener('change', e => {
const form = e.target.closest('form');
const updateButton = form.querySelector(Selectors.fields.updateButton);
- const fieldset = updateButton.closest('fieldset');
-
const url = new URL(form.action);
- url.hash = fieldset.id;
form.action = url.toString();
updateButton.click();
diff --git a/communication/classes/api.php b/communication/classes/api.php
index 93dbdff90528d..1698f719313a4 100644
--- a/communication/classes/api.php
+++ b/communication/classes/api.php
@@ -148,8 +148,6 @@ public function form_definition(
$PAGE->requires->js_call_amd('core_communication/providerchooser', 'init');
- $mform->addElement('header', 'communication', get_string('communication', 'communication'));
-
// List the communication providers.
$mform->addElement(
'select',
diff --git a/communication/classes/form/configure_form.php b/communication/classes/form/configure_form.php
new file mode 100644
index 0000000000000..e3cc7f6a4e784
--- /dev/null
+++ b/communication/classes/form/configure_form.php
@@ -0,0 +1,87 @@
+.
+
+/**
+ * Configure communication for a given instance - the form definition.
+ *
+ * @package core_communication
+ * @copyright 2023 David Woloszyn
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace core_communication\form;
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once($CFG->libdir.'/formslib.php');
+
+/**
+ * Defines the configure communication form.
+ */
+class configure_form extends \moodleform {
+
+ /**
+ * @var \core_communication\api $communication The communication api object.
+ */
+ protected $communication;
+
+ /**
+ * Defines the form fields.
+ */
+ public function definition() {
+ $mform = $this->_form;
+ $instanceid = $this->_customdata['instanceid'];
+ $instancetype = $this->_customdata['instancetype'];
+ $component = $this->_customdata['component'];
+ $instance = $this->_customdata['instance'];
+
+ // Add communication plugins to the form.
+ $this->communication = \core_communication\api::load_by_instance(
+ $component,
+ $instancetype,
+ $instanceid
+ );
+ $this->communication->form_definition($mform);
+ $this->communication->set_data($instance);
+
+ // Form buttons.
+ $buttonarray = [];
+ $buttonarray[] = $mform->createElement('submit', 'saveandreturn', get_string('savechanges'));
+ $buttonarray[] = $mform->createElement('cancel');
+ $mform->addGroup($buttonarray, 'buttonar', '', [' '], false);
+ $mform->closeHeaderBefore('buttonar');
+
+ // Hidden elements.
+ $mform->addElement('hidden', 'instanceid', $instanceid);
+ $mform->setType('instanceid', PARAM_INT);
+ $mform->addElement('hidden', 'instancetype', $instancetype);
+ $mform->setType('instancetype', PARAM_TEXT);
+ $mform->addElement('hidden', 'component', $component);
+ $mform->setType('component', PARAM_TEXT);
+
+ // Finally set the current form data.
+ $this->set_data($instance);
+ }
+
+ /**
+ * Fill in the communication page data depending on provider selected.
+ */
+ public function definition_after_data() {
+ $mform = $this->_form;
+ // Add communication plugins to the form with respect to the provider.
+ $this->communication->form_definition_for_provider($mform);
+ }
+}
diff --git a/communication/configure.php b/communication/configure.php
new file mode 100644
index 0000000000000..36724e082f84c
--- /dev/null
+++ b/communication/configure.php
@@ -0,0 +1,86 @@
+.
+
+/**
+ * Configure communication for a given instance.
+ *
+ * @package core_communication
+ * @copyright 2023 David Woloszyn
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once('../config.php');
+require_once('lib.php');
+
+require_login();
+
+$instanceid = required_param('instanceid', PARAM_INT);
+$instancetype = required_param('instancetype', PARAM_TEXT);
+$component = required_param('component', PARAM_COMPONENT);
+
+$instanceinfo = [
+ 'instanceid' => $instanceid,
+ 'instancetype' => $instancetype,
+ 'component' => $component,
+];
+
+// Requires communication to be enabled.
+if (!core_communication\api::is_available()) {
+ throw new \moodle_exception('communicationdisabled', 'communication');
+}
+
+// Attempt to load the communication instance with the provided params.
+$communication = \core_communication\api::load_by_instance($component, $instancetype, $instanceid);
+
+// No communication, no way this form can be used.
+if (!$communication) {
+ throw new \moodle_exception('nocommunicationinstance', 'communication');
+}
+
+// Set variables according to the component callback and use them on the page.
+list($instance, $context, $heading, $returnurl) = component_callback(
+ $component,
+ 'get_communication_instance_data',
+ [$instanceid]
+);
+
+// Set up the page.
+$PAGE->set_context($context);
+$PAGE->set_url('/communication/configure.php', $instanceinfo);
+$PAGE->set_title(get_string('communication', 'communication'));
+$PAGE->set_heading($heading);
+$PAGE->add_body_class('limitedwidth');
+
+// Append the instance data before passing to form object.
+$instanceinfo['instance'] = $instance;
+// Get our form definitions.
+$form = new \core_communication\form\configure_form(null, $instanceinfo);
+
+if ($form->is_cancelled()) {
+
+ redirect($returnurl);
+
+} else if ($data = $form->get_data()) {
+
+ component_callback($component, 'update_communication_instance_data', [$data]);
+ redirect($returnurl);
+}
+
+// Display the page contents.
+echo $OUTPUT->header();
+echo $OUTPUT->heading(get_string('communication', 'communication'), 2);
+$form->display();
+echo $OUTPUT->footer();
diff --git a/communication/provider/matrix/tests/behat/matrix_form_fields.feature b/communication/provider/matrix/tests/behat/matrix_form_fields.feature
index f403db6fd6a08..78ea9fdbedc52 100644
--- a/communication/provider/matrix/tests/behat/matrix_form_fields.feature
+++ b/communication/provider/matrix/tests/behat/matrix_form_fields.feature
@@ -19,35 +19,30 @@ Feature: Communication matrix form field
Given a Matrix mock server is configured
And I log in as "teacher1"
And I am on "Test course" course homepage
- When I navigate to "Settings" in current page administration
- And I click on "Communication" "link"
+ When I navigate to "Communication" in current page administration
And I set the field "id_selectedcommunication" to "Matrix"
And I wait to be redirected
And I should see "Room name"
And I set the field "id_communicationroomname" to "Sampleroomname"
- And I press "Save and display"
- And I navigate to "Settings" in current page administration
- And I expand all fieldsets
+ And I press "Save changes"
+ And I navigate to "Communication" in current page administration
Then the field "id_communicationroomname" matches value "Sampleroomname"
Scenario: I can add room topic for matrix room
Given a Matrix mock server is configured
And I log in as "teacher1"
And I am on "Test course" course homepage
- When I navigate to "Settings" in current page administration
- And I click on "Communication" "link"
+ When I navigate to "Communication" in current page administration
And I set the field "id_selectedcommunication" to "Matrix"
And I wait to be redirected
And I should see "Room name"
And I should see "Room topic"
And I set the field "id_communicationroomname" to "Sampleroomname"
And I set the field "id_matrixroomtopic" to "Sampleroomtopic"
- And I press "Save and display"
- And I navigate to "Settings" in current page administration
- And I click on "Communication" "link"
+ And I press "Save changes"
+ And I navigate to "Communication" in current page administration
Then the field "id_communicationroomname" matches value "Sampleroomname"
And I press "Cancel"
And I run all adhoc tasks
- And I navigate to "Settings" in current page administration
- And I click on "Communication" "link"
+ And I navigate to "Communication" in current page administration
And the field "id_matrixroomtopic" matches value "Sampleroomtopic"
diff --git a/communication/provider/matrix/tests/behat/matrix_room_link.feature b/communication/provider/matrix/tests/behat/matrix_room_link.feature
index b20a64fe4e58e..0b968a7321019 100644
--- a/communication/provider/matrix/tests/behat/matrix_room_link.feature
+++ b/communication/provider/matrix/tests/behat/matrix_room_link.feature
@@ -37,10 +37,11 @@ Feature: Communication matrix
And ".footer-link-communication" "css_element" should be visible
Scenario: I cannot see the matrix room link when communication provider is disabled
- Given I am on the "Test course" "Course editing" page logged in as "teacher1"
+ Given I am on the "Test course" "Course" page logged in as "teacher1"
+ When I navigate to "Communication" in current page administration
And I set the following fields to these values:
| selectedcommunication | none |
- And I press "Save and display"
+ And I press "Save changes"
And I run all adhoc tasks
And I reload the page
Then ".btn-footer-communication" "css_element" should not be visible
diff --git a/communication/tests/api_test.php b/communication/tests/api_test.php
index f8400cdac5b75..0c9c3251d6597 100644
--- a/communication/tests/api_test.php
+++ b/communication/tests/api_test.php
@@ -191,7 +191,7 @@ public function test_create_and_configure_room(): void {
*/
public function test_create_and_configure_room_without_communication_provider_selected(): void {
// Get the course by disabling communication so that we can create it manually calling the api.
- $course = $this->getDataGenerator()->create_course();
+ $course = $this->get_course('Sampleroom', 'none');
// Test the tasks added.
$adhoctask = \core\task\manager::get_adhoc_tasks('\\core_communication\\task\\create_and_configure_room_task');
diff --git a/communication/tests/behat/communication_configuration.feature b/communication/tests/behat/communication_configuration.feature
new file mode 100644
index 0000000000000..a311c19519f86
--- /dev/null
+++ b/communication/tests/behat/communication_configuration.feature
@@ -0,0 +1,41 @@
+@communication
+Feature: Access the communication configuration page
+ As an editing teacher
+ See dynamic form fields based on selected provider
+
+ Background: Set up teachers and course for the communication confifiguration page
+ Given I enable communication experimental feature
+ And the following "users" exist:
+ | username | firstname | lastname | email |
+ | teacher1 | Teacher | 1 | teacher1@example.com |
+ | teacher2 | Teacher | 2 | teacher2@example.com |
+ And the following "courses" exist:
+ | fullname | shortname | category | selectedcommunication |
+ | Test course | Test course | 0 | none |
+ And the following "course enrolments" exist:
+ | user | course | role |
+ | teacher1 | Test course | editingteacher |
+ | teacher2 | Test course | teacher |
+
+ Scenario: A teacher with the correct capability can access the communication configuration page
+ Given I am on the "Test course" "Course" page logged in as "teacher1"
+ When I navigate to "Communication" in current page administration
+ Then I should see "Communication"
+
+ Scenario: A teacher without the correct capability cannot access the communication configuration page
+ Given I am on the "Test course" "Course" page logged in as "teacher2"
+ Then "Communication" "link" should not exist in current page administration
+
+ Scenario: I cannot see the communication link when communication provider is disabled
+ Given I disable communication experimental feature
+ And I am on the "Test course" "Course" page logged in as "teacher1"
+ Then "Communication" "link" should not exist in current page administration
+
+ @javascript
+ Scenario: The communication form fields toggle dynamically when valid provider is set
+ Given I am on the "Test course" "Course" page logged in as "teacher1"
+ When I navigate to "Communication" in current page administration
+ And I set the following fields to these values:
+ | selectedcommunication | communication_matrix |
+ Then I should see "Room name"
+ And I should see "Room topic"
diff --git a/course/edit_form.php b/course/edit_form.php
index 73d630e158104..c5f2b44611e8f 100644
--- a/course/edit_form.php
+++ b/course/edit_form.php
@@ -401,28 +401,6 @@ function definition() {
$handler->set_parent_context($categorycontext); // For course handler only.
$handler->instance_form_definition($mform, empty($course->id) ? 0 : $course->id);
- // Add communication plugins to the form.
- if (core_communication\api::is_available()) {
-
- $instanceconfig = core_communication\processor::PROVIDER_NONE;
- // For new courses.
- if (empty($course->id)) {
- $instanceid = 0;
- if (!empty($courseconfig->coursecommunicationprovider)) {
- $instanceconfig = $courseconfig->coursecommunicationprovider;
- }
- } else {
- // For existing courses.
- $instanceid = $course->id;
- }
-
- $communication = \core_communication\api::load_by_instance(
- 'core_course',
- 'coursecommunication',
- $instanceid);
- $communication->form_definition($mform, $instanceconfig);
- $communication->set_data($course);
- }
// When two elements we need a group.
$buttonarray = array();
@@ -494,15 +472,6 @@ function definition_after_data() {
$handler = core_course\customfield\course_handler::create();
$handler->instance_form_definition_after_data($mform, empty($courseid) ? 0 : $courseid);
- // Add communication plugins to the form.
- if (core_communication\api::is_available()) {
- $communication = \core_communication\api::load_by_instance(
- 'core_course',
- 'coursecommunication',
- empty($course->id) ? 0 : $course->id
- );
- $communication->form_definition_for_provider($mform);
- }
}
/**
diff --git a/course/lib.php b/course/lib.php
index 31e451e0a1ab9..5f6bb58817a44 100644
--- a/course/lib.php
+++ b/course/lib.php
@@ -2322,17 +2322,24 @@ function create_course($data, $editoroptions = NULL) {
if (isset($data->tags)) {
core_tag_tag::set_item_tags('core', 'course', $course->id, context_course::instance($course->id), $data->tags);
}
-
- // Communication api implementation in course.
- if (isset($data->selectedcommunication) && core_communication\api::is_available()) {
- // Prepare the communication api date.
- $courseimage = course_summary_exporter::get_course_image($course);
- $communicationroomname = !empty($data->communicationroomname) ? $data->communicationroomname : $data->fullname;
- $selectedcommunication = $data->selectedcommunication;
-
- // Communication api call.
- $communication = \core_communication\api::load_by_instance('core_course', 'coursecommunication', $course->id);
- $communication->create_and_configure_room($selectedcommunication, $communicationroomname, $courseimage, $data);
+ // Set up communication.
+ if (core_communication\api::is_available()) {
+ // Check for default provider config setting.
+ $defaultprovider = get_config('moodlecourse', 'coursecommunicationprovider');
+ $provider = (isset($data->selectedcommunication)) ? $data->selectedcommunication : $defaultprovider;
+
+ if (!empty($provider)) {
+ // Prepare the communication api data.
+ $courseimage = course_summary_exporter::get_course_image($course);
+ $communicationroomname = !empty($data->communicationroomname) ? $data->communicationroomname : $data->fullname;
+ // Communication api call.
+ $communication = \core_communication\api::load_by_instance(
+ 'core_course',
+ 'coursecommunication',
+ $course->id
+ );
+ $communication->create_and_configure_room($provider, $communicationroomname, $courseimage, $data);
+ }
}
// Save custom fields if there are any of them in the form.
@@ -2463,6 +2470,11 @@ function update_course($data, $editoroptions = NULL) {
$provider = 'none';
}
+ // Attempt to get the communication provider if it wasn't provided in the data.
+ if (empty($provider) && core_communication\api::is_available()) {
+ $provider = \core_communication\api::load_by_instance('core_course', 'coursecommunication', $data->id)->get_provider();
+ }
+
// Communication api call.
if (!empty($provider) && core_communication\api::is_available()) {
// Prepare the communication api data.
@@ -4007,6 +4019,7 @@ function course_get_user_navigation_options($context, $course = null) {
'participants' => false,
'search' => false,
'tags' => false,
+ 'communication' => false,
];
$options->blogs = !empty($CFG->enableblogs) &&
@@ -4078,6 +4091,10 @@ function course_get_user_navigation_options($context, $course = null) {
$options->grades = $grades;
}
+ if (\core_communication\api::is_available()) {
+ $options->communication = has_capability('moodle/course:configurecoursecommunication', $context);
+ }
+
if (\core_competency\api::is_enabled()) {
$capabilities = array('moodle/competency:coursecompetencyview', 'moodle/competency:coursecompetencymanage');
$options->competencies = has_any_capability($capabilities, $context);
@@ -5133,3 +5150,32 @@ function course_output_fragment_new_base_form($args) {
return $o;
}
+
+/**
+ * Get course specific data for configuring a communication instance.
+ *
+ * @param integer $courseid The course id.
+ * @return array Returns course data, context and heading.
+ */
+function course_get_communication_instance_data(int $courseid): array {
+ // Do some checks and prepare instance specific data.
+ $course = get_course($courseid);
+ require_login($course);
+ $context = context_course::instance($course->id);
+ require_capability('moodle/course:configurecoursecommunication', $context);
+
+ $heading = $course->fullname;
+ $returnurl = new moodle_url('/course/view.php', ['id' => $courseid]);
+
+ return [$course, $context, $heading, $returnurl];
+}
+
+/**
+ * Update a course using communication configuration data.
+ *
+ * @param stdClass $data The data to update the course with.
+ */
+function course_update_communication_instance_data(stdClass $data): void {
+ $data->id = $data->instanceid; // For correct use in update_course.
+ update_course($data);
+}
diff --git a/course/tests/behat/course_communication_defaults.feature b/course/tests/behat/course_communication_defaults.feature
index c7fc5982fb2f5..d314bef4f09da 100644
--- a/course/tests/behat/course_communication_defaults.feature
+++ b/course/tests/behat/course_communication_defaults.feature
@@ -1,4 +1,4 @@
-@core @core_course
+@core @core_course @communication
Feature: Course communication
In order to create a new communication room in for course
As an admin
@@ -7,22 +7,23 @@ Feature: Course communication
Background:
Given the following "courses" exist:
- | fullname | shortname |
- | Test course | C |
+ | fullname | shortname |
+ | Course 1 | C1 |
And I enable communication experimental feature
And I log in as "admin"
Scenario: I should have matrix plugin by default for new courses
Given I go to the courses management page
- And I should see the "Categories" management page
And I click on category "Category 1" in the management interface
- And I should see the "Course categories and courses" management page
And I follow "Create new course"
- When I click on "Communication" "link"
+ And I set the following fields to these values:
+ | Course full name | Course 2 |
+ | Course short name | C2 |
+ And I press "Save and display"
+ When I navigate to "Communication" in current page administration
Then the field "Communication service" matches value "Matrix"
Scenario: I should have communication disabled by default for existing courses
- Given I am on "Test course" course homepage
- When I navigate to "Settings" in current page administration
- And I click on "Communication" "link"
+ Given I am on "Course 1" course homepage
+ When I navigate to "Communication" in current page administration
Then the field "Communication service" matches value "None"
diff --git a/course/tests/courselib_test.php b/course/tests/courselib_test.php
index f972ed5c346f4..51a4b3db179fd 100644
--- a/course/tests/courselib_test.php
+++ b/course/tests/courselib_test.php
@@ -7271,4 +7271,67 @@ public function test_set_downloadcontent() {
// The download course content value has changed, it should return true in this case.
$this->assertTrue(set_downloadcontent($page->cmid, DOWNLOAD_COURSE_CONTENT_ENABLED));
}
+
+ /**
+ * Test the course_get_communication_instance_data() function.
+ *
+ * @covers ::course_get_communication_instance_data
+ */
+ public function test_course_get_communication_instance_data(): void {
+ $this->resetAfterTest();
+ $course = $this->getDataGenerator()->create_course();
+
+ // Set admin user as a valid enrolment will be checked in the callback function.
+ $this->setAdminUser();
+
+ // Use the callback function and return the data.
+ list($instance, $context, $heading, $returnurl) = component_callback(
+ 'core_course',
+ 'get_communication_instance_data',
+ [$course->id]
+ );
+
+ // Check the url is as expected.
+ $expectedreturnurl = new moodle_url('/course/view.php', ['id' => $course->id]);
+ $this->assertEquals($expectedreturnurl, $returnurl);
+
+ // Check the context is as expected.
+ $expectedcontext = context_course::instance($course->id);
+ $this->assertEquals($expectedcontext, $context);
+
+ // Check the instance id is as expected.
+ $this->assertEquals($course->id, $instance->id);
+
+ // Check the heading is as expected.
+ $this->assertEquals($course->fullname, $heading);
+ }
+
+ /**
+ * Test the course_update_communication_instance_data() function.
+ *
+ * @covers ::course_update_communication_instance_data
+ */
+ public function test_course_update_communication_instance_data(): void {
+ $this->resetAfterTest();
+ $course = $this->getDataGenerator()->create_course();
+
+ // Set some data to update with.
+ $data = new stdClass();
+ $data->instanceid = $course->id;
+ $data->fullname = 'newname';
+
+ // These should not be the same yet.
+ $this->assertNotEquals($course->fullname, $data->fullname);
+
+ // Use the callback function to update the course with the data.
+ component_callback(
+ 'core_course',
+ 'update_communication_instance_data',
+ [$data]
+ );
+
+ // Get the course and check it was updated.
+ $course = get_course($course->id);
+ $this->assertEquals($course->fullname, $data->fullname);
+ }
}
diff --git a/course/tests/externallib_test.php b/course/tests/externallib_test.php
index b026cbfd7c461..83404ad7b2539 100644
--- a/course/tests/externallib_test.php
+++ b/course/tests/externallib_test.php
@@ -2636,7 +2636,7 @@ public function test_get_user_navigation_options() {
foreach ($course['options'] as $option) {
$navoptions->{$option['name']} = $option['available'];
}
- $this->assertCount(8, $course['options']);
+ $this->assertCount(9, $course['options']);
if ($course['id'] == SITEID) {
$this->assertTrue($navoptions->blogs);
$this->assertFalse($navoptions->notes);
@@ -2646,6 +2646,7 @@ public function test_get_user_navigation_options() {
$this->assertFalse($navoptions->grades);
$this->assertFalse($navoptions->search);
$this->assertTrue($navoptions->competencies);
+ $this->assertFalse($navoptions->communication);
} else {
$this->assertTrue($navoptions->blogs);
$this->assertFalse($navoptions->notes);
@@ -2655,6 +2656,7 @@ public function test_get_user_navigation_options() {
$this->assertTrue($navoptions->grades);
$this->assertFalse($navoptions->search);
$this->assertTrue($navoptions->competencies);
+ $this->assertFalse($navoptions->communication);
}
}
}
diff --git a/lang/en/communication.php b/lang/en/communication.php
index 46fa746b930cb..bdadec765ac17 100644
--- a/lang/en/communication.php
+++ b/lang/en/communication.php
@@ -23,12 +23,14 @@
*/
$string['communication'] = 'Communication';
+$string['communicationdisabled'] = 'Communication is disabled.';
$string['communicationprovidernotfound'] = 'The \'{$a}\' communication provider doesn\'t exist or is not recognised.';
$string['communicationroomname'] = 'Room name';
$string['communicationroomname_help'] = 'The name that participants see when they visit the room. If you leave this blank, a default room name will be automatically set.';
$string['communicationroompending'] = 'Your {$a} room will be ready soon.';
$string['communicationroomready'] = 'Your {$a} room is ready!';
$string['managecommunicationproviders'] = 'Manage communication providers';
+$string['nocommunicationinstance'] = 'No communication instance found.';
$string['nocommunicationprovider'] = 'No communication provider found.';
$string['nocommunicationselected'] = 'None';
$string['privacy:metadata:communication_user'] = 'The communication user table stores the user id and communication id for communication provider mapping.';
diff --git a/lang/en/role.php b/lang/en/role.php
index 5f9b0ff7f0021..117a489e991e1 100644
--- a/lang/en/role.php
+++ b/lang/en/role.php
@@ -164,6 +164,7 @@
$string['contextrolenotallowed'] = 'Role {$a} not allowed in this context.';
$string['course:activityvisibility'] = 'Hide/show activities';
$string['course:bulkmessaging'] = 'Send a message to many people';
+$string['course:configurecoursecommunication'] = 'Configure course communication settings';
$string['course:create'] = 'Create courses';
$string['course:creategroupconversations'] = 'Create group conversations';
$string['course:delete'] = 'Delete courses';
diff --git a/lib/classes/navigation/views/secondary.php b/lib/classes/navigation/views/secondary.php
index 9abc2b270f8a9..b533fe5881886 100644
--- a/lib/classes/navigation/views/secondary.php
+++ b/lib/classes/navigation/views/secondary.php
@@ -89,6 +89,7 @@ protected function get_default_course_mapping(): array {
'grades' => 2,
'badgesview' => 7,
'competencies' => 8,
+ 'communication' => 14,
],
self::TYPE_CUSTOM => [
'contentbank' => 5,
diff --git a/lib/db/access.php b/lib/db/access.php
index 37bd3aa509baa..3a326b40ea451 100644
--- a/lib/db/access.php
+++ b/lib/db/access.php
@@ -2691,4 +2691,14 @@
'manager' => CAP_ALLOW,
]
],
+
+ // Allow users to configure course communication rooms.
+ 'moodle/course:configurecoursecommunication' => [
+ 'captype' => 'write',
+ 'contextlevel' => CONTEXT_COURSE,
+ 'archetypes' => [
+ 'editingteacher' => CAP_ALLOW,
+ 'manager' => CAP_ALLOW,
+ ]
+ ],
);
diff --git a/lib/navigationlib.php b/lib/navigationlib.php
index c95f7ebcbb242..11522aa9c9b4f 100644
--- a/lib/navigationlib.php
+++ b/lib/navigationlib.php
@@ -2976,6 +2976,14 @@ public function add_course_essentials($coursenode, stdClass $course) {
}
}
+ // Add link for configuring communication.
+ if ($navoptions->communication) {
+ $url = new moodle_url('/communication/configure.php', ['instanceid' => $course->id,
+ 'instancetype' => 'coursecommunication', 'component' => 'core_course']);
+ $coursenode->add(get_string('communication', 'communication'), $url,
+ navigation_node::TYPE_SETTING, null, 'communication');
+ }
+
return true;
}
/**
diff --git a/version.php b/version.php
index c6de877291901..55147bd1c999f 100644
--- a/version.php
+++ b/version.php
@@ -29,7 +29,7 @@
defined('MOODLE_INTERNAL') || die();
-$version = 2023072800.00; // YYYYMMDD = weekly release date of this DEV branch.
+$version = 2023072800.01; // YYYYMMDD = weekly release date of this DEV branch.
// RR = release increments - 00 in DEV branches.
// .XX = incremental changes.
$release = '4.3dev (Build: 20230728)'; // Human-friendly version name