914686bc5e
This commit brings in support for multiple versions of the Matrix
specification.
A Matrix server is compromised of a number of individually versioned API
endpoints, for example:
/_matrix/client/v3/createRoom
/_matrix/client/v3/rooms/:roomid/joined_members
/_matrix/media/v1/create
The combination of a large number of these individually versioned
endpoints forms a Matrix Specification version.
For example:
* the /_matrix/media/v1/create endpoint was created for version 1.7 of the
specification, and does not exist in earlier versions.
* in the future a new behaviour or parameter may be created for the
`createRoom` endpoint and a new endpoint created at:
/_matrix/client/v4/createRoom
A single server can support multiple versions of the Matrix
specification. The server declares the versions of the specification
that it supports using a non-versioned endpoint at
`/_matrix/client/versions`.
As a Matrix client, Moodle should:
* query the server version endpoint
* determine the combination of mutually supported Matrix specification
versions
* create a client instance of the highest-supported version of the
specification.
For example, if Moodle (Matrix client) and a remote server have the
following support:
```
Moodle: 1.1 1.2 1.3 1.4 1.5 1.6 1.7
Server: r0 1.1 1.2 1.3 1.4 1.5 1.6
```
The versions in common are 1.1 through 1.6, and version 1.6 would be
chosen.
To avoid duplication and allow for support of future features more
easily, the Moodle client is written as:
* a set of classes named `v1p1` through `v1p7` (currently) which extend
the `matrix_client` abstract class; and
* a set if PHP traits which provide the implementation for individual
versioned endpoints.
Each client version then imports any relevant traits which are present
in that version of the Matrix Specification. For example versions 1.1 to
1.6 do _not_ have the `/_matrix/media/v1/create` endpoint so they do not
import this trait. This trait was introduced in version 1.7, so the
trait is included from that version onwards.
In the future, if an endpoint is created which conflicts with an
existing endpoint, then it would be easy to create a new client version
which uses the existing common traits, and adds the new trait.
Each endpoint is written using a `command` class which extends the
Guzzle implementation of the PSR-7 Request interface. This command
class adds support for easy creation of:
* path parameters within the URI
* query parameters
* body parameters
This is done to avoid complex patterns of Request creation which are
repeated for every client endpoint.
292 lines
10 KiB
PHP
292 lines
10 KiB
PHP
<?php
|
|
// This file is part of Moodle - http://moodle.org/
|
|
//
|
|
// Moodle is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// Moodle is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
namespace core_communication;
|
|
|
|
defined('MOODLE_INTERNAL') || die();
|
|
|
|
require_once(__DIR__ . '/communication_test_helper_trait.php');
|
|
|
|
/**
|
|
* Class api_test to test the communication public api and its associated methods.
|
|
*
|
|
* @package core_communication
|
|
* @category test
|
|
* @copyright 2023 Safat Shahin <safat.shahin@moodle.com>
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
* @covers \core_communication\api
|
|
*/
|
|
class api_test extends \advanced_testcase {
|
|
|
|
use communication_test_helper_trait;
|
|
|
|
public function setUp(): void {
|
|
parent::setUp();
|
|
$this->resetAfterTest();
|
|
$this->setup_communication_configs();
|
|
}
|
|
|
|
/**
|
|
* Test the communication plugin list for the form element returns the correct number of plugins.
|
|
*/
|
|
public function test_get_communication_plugin_list_for_form(): void {
|
|
$communicationplugins = \core_communication\api::get_communication_plugin_list_for_form();
|
|
// Get the communication plugins.
|
|
$plugins = \core_component::get_plugin_list('communication');
|
|
// Check the number of plugins matches plus 1 as we have none in the selection.
|
|
$this->assertCount(count($plugins) + 1, $communicationplugins);
|
|
}
|
|
|
|
/**
|
|
* Test set data to the instance.
|
|
*/
|
|
public function test_set_data(): void {
|
|
$course = $this->get_course();
|
|
|
|
$communication = \core_communication\api::load_by_instance(
|
|
'core_course',
|
|
'coursecommunication',
|
|
$course->id
|
|
);
|
|
|
|
// Sample data.
|
|
$roomname = 'Sampleroom';
|
|
$provider = 'communication_matrix';
|
|
|
|
// Set the data.
|
|
$communication->set_data($course);
|
|
|
|
// Test the set data.
|
|
$this->assertEquals($roomname, $course->communicationroomname);
|
|
$this->assertEquals($provider, $course->selectedcommunication);
|
|
}
|
|
|
|
/**
|
|
* Test get_current_communication_provider method.
|
|
*/
|
|
public function test_get_provider(): void {
|
|
$course = $this->get_course();
|
|
|
|
$communication = \core_communication\api::load_by_instance(
|
|
'core_course',
|
|
'coursecommunication',
|
|
$course->id
|
|
);
|
|
|
|
$this->assertEquals('communication_matrix', $communication->get_provider());
|
|
}
|
|
|
|
/**
|
|
* Test set_avatar method.
|
|
*/
|
|
public function test_set_avatar(): void {
|
|
global $CFG;
|
|
$this->setAdminUser();
|
|
$course = $this->get_course('Sampleroom', 'none');
|
|
|
|
// Sample data.
|
|
$communicationroomname = 'Sampleroom';
|
|
$selectedcommunication = 'communication_matrix';
|
|
|
|
$avatar = $this->create_communication_file(
|
|
'moodle_logo.jpg',
|
|
'moodle_logo.jpg',
|
|
);
|
|
|
|
// Create the room, settingthe avatar.
|
|
$communication = \core_communication\api::load_by_instance(
|
|
'core_course',
|
|
'coursecommunication',
|
|
$course->id,
|
|
);
|
|
|
|
$communication->create_and_configure_room($selectedcommunication, $communicationroomname, $avatar);
|
|
|
|
// Reload the communication processor.
|
|
$communicationprocessor = processor::load_by_instance(
|
|
'core_course',
|
|
'coursecommunication',
|
|
$course->id,
|
|
);
|
|
|
|
// Compare result.
|
|
$this->assertEquals(
|
|
$avatar->get_contenthash(),
|
|
$communicationprocessor->get_avatar()->get_contenthash(),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Test the create_and_configure_room method to add/create tasks.
|
|
*/
|
|
public function test_create_and_configure_room(): void {
|
|
// Get the course by disabling communication so that we can create it manually calling the api.
|
|
$course = $this->get_course('Sampleroom', 'none');
|
|
|
|
// Sample data.
|
|
$communicationroomname = 'Sampleroom';
|
|
$selectedcommunication = 'communication_matrix';
|
|
|
|
$communication = \core_communication\api::load_by_instance(
|
|
'core_course',
|
|
'coursecommunication',
|
|
$course->id
|
|
);
|
|
$communication->create_and_configure_room($selectedcommunication, $communicationroomname);
|
|
|
|
// Test the tasks added.
|
|
$adhoctask = \core\task\manager::get_adhoc_tasks('\\core_communication\\task\\create_and_configure_room_task');
|
|
$this->assertCount(1, $adhoctask);
|
|
|
|
$adhoctask = reset($adhoctask);
|
|
$this->assertInstanceOf('\\core_communication\\task\\create_and_configure_room_task', $adhoctask);
|
|
|
|
// Test the communication record exists.
|
|
$communicationprocessor = processor::load_by_instance(
|
|
'core_course',
|
|
'coursecommunication',
|
|
$course->id
|
|
);
|
|
|
|
$this->assertEquals($communicationroomname, $communicationprocessor->get_room_name());
|
|
$this->assertEquals($selectedcommunication, $communicationprocessor->get_provider());
|
|
}
|
|
|
|
/**
|
|
* Test the create_and_configure_room method to add/create tasks when no communication provider selected.
|
|
*/
|
|
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->get_course('Sampleroom', 'none');
|
|
|
|
// Test the tasks added.
|
|
$adhoctask = \core\task\manager::get_adhoc_tasks('\\core_communication\\task\\create_and_configure_room_task');
|
|
$this->assertCount(0, $adhoctask);
|
|
|
|
// Test the communication record exists.
|
|
$communicationprocessor = processor::load_by_instance(
|
|
'core_course',
|
|
'coursecommunication',
|
|
$course->id
|
|
);
|
|
|
|
$this->assertNull($communicationprocessor);
|
|
}
|
|
|
|
/**
|
|
* Test update operation.
|
|
*/
|
|
public function test_update_room(): void {
|
|
$course = $this->get_course();
|
|
|
|
// Sample data.
|
|
$communicationroomname = 'Sampleroomupdated';
|
|
$selectedcommunication = 'communication_matrix';
|
|
|
|
$communication = \core_communication\api::load_by_instance(
|
|
'core_course',
|
|
'coursecommunication',
|
|
$course->id
|
|
);
|
|
$communication->update_room($selectedcommunication, $communicationroomname);
|
|
|
|
// Test the communication record exists.
|
|
$communicationprocessor = processor::load_by_instance(
|
|
'core_course',
|
|
'coursecommunication',
|
|
$course->id
|
|
);
|
|
|
|
$this->assertEquals($communicationroomname, $communicationprocessor->get_room_name());
|
|
$this->assertEquals($selectedcommunication, $communicationprocessor->get_provider());
|
|
}
|
|
|
|
/**
|
|
* Test delete operation.
|
|
*/
|
|
public function test_delete_room(): void {
|
|
$course = $this->get_course();
|
|
|
|
// Sample data.
|
|
$communicationroomname = 'Sampleroom';
|
|
$selectedcommunication = 'communication_matrix';
|
|
|
|
// Test the communication record exists.
|
|
$communicationprocessor = processor::load_by_instance(
|
|
'core_course',
|
|
'coursecommunication',
|
|
$course->id
|
|
);
|
|
|
|
$this->assertEquals($communicationroomname, $communicationprocessor->get_room_name());
|
|
$this->assertEquals($selectedcommunication, $communicationprocessor->get_provider());
|
|
|
|
$communication = \core_communication\api::load_by_instance(
|
|
'core_course',
|
|
'coursecommunication',
|
|
$course->id
|
|
);
|
|
$communication->delete_room();
|
|
|
|
// Test the tasks added.
|
|
$adhoctask = \core\task\manager::get_adhoc_tasks('\\core_communication\\task\\delete_room_task');
|
|
// Should be 2 as one for create, another for update.
|
|
$this->assertCount(1, $adhoctask);
|
|
|
|
$adhoctask = reset($adhoctask);
|
|
$this->assertInstanceOf('\\core_communication\\task\\delete_room_task', $adhoctask);
|
|
}
|
|
|
|
/**
|
|
* Test the update_room_membership for adding adn removing members.
|
|
*/
|
|
public function test_update_room_membership(): void {
|
|
$course = $this->get_course();
|
|
$userid = $this->get_user()->id;
|
|
|
|
// First test the adding members to a room.
|
|
$communication = \core_communication\api::load_by_instance(
|
|
'core_course',
|
|
'coursecommunication',
|
|
$course->id
|
|
);
|
|
$communication->add_members_to_room([$userid]);
|
|
|
|
// Test the tasks added.
|
|
$adhoctask = \core\task\manager::get_adhoc_tasks('\\core_communication\\task\\add_members_to_room_task');
|
|
$this->assertCount(1, $adhoctask);
|
|
|
|
// Now test the removing members from a room.
|
|
$communication->remove_members_from_room([$userid]);
|
|
|
|
// Test the tasks added.
|
|
$adhoctask = \core\task\manager::get_adhoc_tasks('\\core_communication\\task\\remove_members_from_room');
|
|
$this->assertCount(1, $adhoctask);
|
|
}
|
|
|
|
/**
|
|
* Test the enabled communication plugin list and default.
|
|
*/
|
|
public function test_get_enabled_providers_and_default(): void {
|
|
list($communicationproviders, $defaulprovider) = \core_communication\api::get_enabled_providers_and_default();
|
|
// Get the communication plugins.
|
|
$plugins = \core_component::get_plugin_list('communication');
|
|
// Check the number of plugins matches plus 1 as we have none in the selection.
|
|
$this->assertCount(count($plugins) + 1, $communicationproviders);
|
|
$this->assertEquals(processor::PROVIDER_NONE, $defaulprovider);
|
|
}
|
|
}
|