1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 namespace communication_matrix; 18 19 use core\context; 20 use GuzzleHttp\Psr7\Response; 21 22 /** 23 * Trait matrix_helper_trait to generate initial setup for matrix mock and associated helpers. 24 * 25 * @package communication_matrix 26 * @copyright 2023 Safat Shahin <safat.shahin@moodle.com> 27 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 28 */ 29 trait matrix_test_helper_trait { 30 /** 31 * @var string $accesstoken The token for matrix connection 32 */ 33 protected string $accesstoken; 34 35 /** 36 * @var string $matrixhomeserverurl The server url of matrix synapse server 37 */ 38 protected string $matrixhomeserverurl; 39 40 /** 41 * Initialize the mock configs in settings. 42 * 43 * @return void 44 */ 45 protected function initialise_mock_configs(): void { 46 $this->matrixhomeserverurl = TEST_COMMUNICATION_MATRIX_MOCK_SERVER; 47 set_config('matrixhomeserverurl', $this->matrixhomeserverurl, 'communication_matrix'); 48 $request = $this->request(); 49 $response = $request->post($this->matrixhomeserverurl . '/backoffice/create-admin'); 50 $admindata = json_decode($response->getBody()); 51 $json = [ 52 'identifier' => [ 53 'type' => 'm.id.user', 54 'user' => $admindata->user_id, 55 ], 56 'type' => 'm.login.password', 57 'password' => $admindata->password, 58 ]; 59 $request = $this->request($json); 60 $response = $request->post($this->matrixhomeserverurl . '/_matrix/client/r0/login'); 61 $response = json_decode($response->getBody()); 62 if (empty($response->access_token)) { 63 $this->markTestSkipped( 64 'The matrix mock server is not responsive, can not continue the tests' 65 ); 66 } 67 $this->accesstoken = $response->access_token; 68 set_config('matrixaccesstoken', $this->accesstoken, 'communication_matrix'); 69 } 70 71 /** 72 * Get the mock server url. 73 * 74 * @return string 75 */ 76 public function get_matrix_server_url(): string { 77 if (empty($this->matrixhomeserverurl)) { 78 throw new \coding_exception('Can not get this information without initializing the mock server.'); 79 } 80 return $this->matrixhomeserverurl; 81 } 82 83 /** 84 * Get the matrix access token. 85 * 86 * @return string 87 */ 88 public function get_matrix_access_token(): string { 89 if (empty($this->accesstoken)) { 90 throw new \coding_exception('Can not get this information without initializing the mock server.'); 91 } 92 return $this->accesstoken; 93 } 94 95 /** 96 * This test requires mock server to be present. 97 * 98 * @return void 99 */ 100 protected function initialise_mock_server(): void { 101 if (!defined('TEST_COMMUNICATION_MATRIX_MOCK_SERVER')) { 102 $this->markTestSkipped( 103 'The TEST_COMMUNICATION_MATRIX_MOCK_SERVER constant must be defined to run communication_matrix tests' 104 ); 105 } 106 $this->reset_mock(); 107 $this->initialise_mock_configs(); 108 } 109 110 /** 111 * Get matrix room data from matrix server. 112 * 113 * @param string $roomid The id of the room 114 * @return \stdClass 115 */ 116 public function get_matrix_room_data(string $roomid): \stdClass { 117 $rooms = $this->backoffice_get_all_rooms(); 118 foreach ($rooms as $room) { 119 if ($room->room_id === $roomid) { 120 return $room; 121 } 122 } 123 } 124 125 /** 126 * Get matrix user data from matrix server. 127 * 128 * @param string $roomid The id of the room 129 * @param string $matrixuserid The id of the user 130 * @return \stdClass 131 */ 132 public function get_matrix_user_data(string $roomid, string $matrixuserid): \stdClass { 133 $users = $this->backoffice_get_all_users(); 134 135 foreach ($users as $user) { 136 if ($user->userid === $matrixuserid) { 137 return $user; 138 } 139 } 140 } 141 142 /** 143 * A backoffice call to get all registered users from our mock server. 144 * 145 * @return array 146 */ 147 public function backoffice_get_all_users(): array { 148 $client = new \core\http_client(); 149 150 return json_decode($client->get($this->get_backoffice_uri('users'))->getBody())->users; 151 } 152 153 /** 154 * A backoffice method to create users and rooms on our mock server. 155 * 156 * @param array $users 157 * @param array $rooms 158 */ 159 public function backoffice_create_users_and_rooms( 160 array $users = [], 161 array $rooms = [], 162 ): Response { 163 $client = new \core\http_client(); 164 return $client->put( 165 $this->get_backoffice_uri('create'), 166 [ 167 'json' => [ 168 'users' => $users, 169 'rooms' => $rooms, 170 ], 171 ], 172 ); 173 } 174 175 /** 176 * The http request for the api call. 177 * 178 * @param array $jsonarray The array of json 179 * @param array $headers The array of headers 180 * @return \core\http_client 181 */ 182 public function request(array $jsonarray = [], array $headers = []): \core\http_client { 183 $response = new \core\http_client([ 184 'headers' => $headers, 185 'json' => $jsonarray, 186 ]); 187 return $response; 188 } 189 190 /** 191 * Get the URI of a backoffice endpoint on the mock server. 192 * 193 * @param string $endpoint 194 * @return string 195 */ 196 protected function get_backoffice_uri(string $endpoint): string { 197 return $this->get_matrix_server_url() . '/backoffice/' . $endpoint; 198 } 199 200 /** 201 * Fetch all rooms from the back office. 202 * 203 * @return array 204 */ 205 public function backoffice_get_all_rooms(): array { 206 $client = new \core\http_client(); 207 208 return json_decode($client->get($this->get_backoffice_uri('rooms'))->getBody())->rooms; 209 } 210 211 /** 212 * Return the first room from the server. 213 * 214 * In most cases there is only one room. 215 * @return \stdClass 216 */ 217 public function backoffice_get_room(): \stdClass { 218 // Fetch the room information from the server. 219 $rooms = $this->backoffice_get_all_rooms(); 220 $this->assertCount(1, $rooms); 221 $room = reset($rooms); 222 return $room; 223 } 224 225 /** 226 * Reset the mock server 227 * 228 * @return void 229 */ 230 public function reset_mock(): void { 231 if (defined('TEST_COMMUNICATION_MATRIX_MOCK_SERVER')) { 232 $request = $this->request(); 233 $response = $request->post(TEST_COMMUNICATION_MATRIX_MOCK_SERVER . '/backoffice/reset'); 234 $response = json_decode($response->getBody()); 235 if (empty($response->reset)) { 236 $this->markTestSkipped( 237 'The matrix mock server is not responsive, can not continue the tests' 238 ); 239 } 240 } 241 } 242 243 /** 244 * Helper to create a room. 245 * 246 * @param null|string $component 247 * @param null|string $itemtype 248 * @param null|int $itemid 249 * @param null|string $roomname 250 * @param null|string $roomtopic 251 * @param null|stored_file $roomavatar 252 * @param array $members 253 * @return api 254 */ 255 protected function create_matrix_room( 256 ?string $component = 'core_course', 257 ?string $itemtype = 'example', 258 ?int $itemid = 1, 259 ?string $roomname = null, 260 ?string $roomtopic = null, 261 ?\stored_file $roomavatar = null, 262 array $members = [], 263 ?context $context = null, 264 ): \core_communication\api { 265 $context = $context ?? \core\context\system::instance(); 266 // Create a new room. 267 $communication = \core_communication\api::load_by_instance( 268 context: $context, 269 component: $component, 270 instancetype: $itemtype, 271 instanceid: $itemid, 272 provider: 'communication_matrix', 273 ); 274 275 $communication->create_and_configure_room( 276 communicationroomname: $roomname ?? 'Room name', 277 avatar: $roomavatar, 278 instance: (object) [ 279 'matrixroomtopic' => $roomtopic ?? 'A fun topic', 280 ], 281 ); 282 283 $communication->add_members_to_room($members); 284 285 // Run the adhoc task. 286 $this->run_all_adhoc_tasks(); 287 288 return \core_communication\api::load_by_instance( 289 context: $context, 290 component: $component, 291 instancetype: $itemtype, 292 instanceid: $itemid, 293 ); 294 } 295 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body