Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
}