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 core_communication;
|
|
|
18 |
|
|
|
19 |
use core\context;
|
|
|
20 |
use core_communication\task\add_members_to_room_task;
|
|
|
21 |
use core_communication\task\create_and_configure_room_task;
|
|
|
22 |
use core_communication\task\delete_room_task;
|
|
|
23 |
use core_communication\task\remove_members_from_room;
|
|
|
24 |
use core_communication\task\synchronise_provider_task;
|
|
|
25 |
use core_communication\task\update_room_task;
|
|
|
26 |
use core_communication\task\update_room_membership_task;
|
|
|
27 |
use stdClass;
|
|
|
28 |
|
|
|
29 |
/**
|
|
|
30 |
* Class api is the public endpoint of the communication api. This class is the point of contact for api usage.
|
|
|
31 |
*
|
|
|
32 |
* Communication api allows to add ad-hoc tasks to the queue to perform actions on the communication providers. This api will
|
|
|
33 |
* not allow any immediate actions to be performed on the communication providers. It will only add the tasks to the queue. The
|
|
|
34 |
* exception has been made for deletion of members in case of deleting the user. This is because the user will not be available.
|
|
|
35 |
* The member management api part allows run actions immediately if required.
|
|
|
36 |
*
|
|
|
37 |
* Communication api does allow to have form elements related to communication api in the required forms. This is done by using
|
|
|
38 |
* the form_definition method. This method will add the form elements to the form.
|
|
|
39 |
*
|
|
|
40 |
* @package core_communication
|
|
|
41 |
* @copyright 2023 Safat Shahin <safat.shahin@moodle.com>
|
|
|
42 |
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
|
43 |
*/
|
|
|
44 |
class api {
|
|
|
45 |
/**
|
|
|
46 |
* @var null|processor $communication The communication settings object
|
|
|
47 |
*/
|
|
|
48 |
private ?processor $communication;
|
|
|
49 |
|
|
|
50 |
/**
|
|
|
51 |
* Communication handler constructor to manage and handle all communication related actions.
|
|
|
52 |
*
|
|
|
53 |
* This class is the entrypoint for all kinda usages.
|
|
|
54 |
* It will be used by the other api to manage the communication providers.
|
|
|
55 |
*
|
|
|
56 |
* @param context $context The context of the item for the instance
|
|
|
57 |
* @param string $component The component of the item for the instance
|
|
|
58 |
* @param string $instancetype The type of the item for the instance
|
|
|
59 |
* @param int $instanceid The id of the instance
|
|
|
60 |
* @param string|null $provider The provider type - if null will load for this context's active provider.
|
|
|
61 |
*
|
|
|
62 |
*/
|
|
|
63 |
private function __construct(
|
|
|
64 |
private context $context,
|
|
|
65 |
private string $component,
|
|
|
66 |
private string $instancetype,
|
|
|
67 |
private int $instanceid,
|
|
|
68 |
private ?string $provider = null,
|
|
|
69 |
) {
|
|
|
70 |
$this->communication = processor::load_by_instance(
|
|
|
71 |
context: $context,
|
|
|
72 |
component: $component,
|
|
|
73 |
instancetype: $instancetype,
|
|
|
74 |
instanceid: $instanceid,
|
|
|
75 |
provider: $provider,
|
|
|
76 |
);
|
|
|
77 |
}
|
|
|
78 |
|
|
|
79 |
/**
|
|
|
80 |
* Get the communication processor object.
|
|
|
81 |
*
|
|
|
82 |
* @param context $context The context of the item for the instance
|
|
|
83 |
* @param string $component The component of the item for the instance
|
|
|
84 |
* @param string $instancetype The type of the item for the instance
|
|
|
85 |
* @param int $instanceid The id of the instance
|
|
|
86 |
* @param string|null $provider The provider type - if null will load for this context's active provider.
|
|
|
87 |
* @return api
|
|
|
88 |
*/
|
|
|
89 |
public static function load_by_instance(
|
|
|
90 |
context $context,
|
|
|
91 |
string $component,
|
|
|
92 |
string $instancetype,
|
|
|
93 |
int $instanceid,
|
|
|
94 |
?string $provider = null,
|
|
|
95 |
): self {
|
|
|
96 |
return new self(
|
|
|
97 |
context: $context,
|
|
|
98 |
component: $component,
|
|
|
99 |
instancetype: $instancetype,
|
|
|
100 |
instanceid: $instanceid,
|
|
|
101 |
provider: $provider,
|
|
|
102 |
);
|
|
|
103 |
}
|
|
|
104 |
|
|
|
105 |
/**
|
|
|
106 |
* Reload in the internal instance data.
|
|
|
107 |
*/
|
|
|
108 |
public function reload(): void {
|
|
|
109 |
$this->communication = processor::load_by_instance(
|
|
|
110 |
context: $this->context,
|
|
|
111 |
component: $this->component,
|
|
|
112 |
instancetype: $this->instancetype,
|
|
|
113 |
instanceid: $this->instanceid,
|
|
|
114 |
provider: $this->provider,
|
|
|
115 |
);
|
|
|
116 |
}
|
|
|
117 |
|
|
|
118 |
/**
|
|
|
119 |
* Return the underlying communication processor object.
|
|
|
120 |
*
|
|
|
121 |
* @return ?processor
|
|
|
122 |
*/
|
|
|
123 |
public function get_processor(): ?processor {
|
|
|
124 |
return $this->communication;
|
|
|
125 |
}
|
|
|
126 |
|
|
|
127 |
/**
|
|
|
128 |
* Return the room provider.
|
|
|
129 |
*
|
|
|
130 |
* @return \core_communication\room_chat_provider
|
|
|
131 |
*/
|
|
|
132 |
public function get_room_provider(): \core_communication\room_chat_provider {
|
|
|
133 |
return $this->communication->get_room_provider();
|
|
|
134 |
}
|
|
|
135 |
|
|
|
136 |
/**
|
|
|
137 |
* Return the user provider.
|
|
|
138 |
*
|
|
|
139 |
* @return \core_communication\user_provider
|
|
|
140 |
*/
|
|
|
141 |
public function get_user_provider(): \core_communication\user_provider {
|
|
|
142 |
return $this->communication->get_user_provider();
|
|
|
143 |
}
|
|
|
144 |
|
|
|
145 |
/**
|
|
|
146 |
* Return the room user provider.
|
|
|
147 |
*
|
|
|
148 |
* @return \core_communication\room_user_provider
|
|
|
149 |
*/
|
|
|
150 |
public function get_room_user_provider(): \core_communication\room_user_provider {
|
|
|
151 |
return $this->communication->get_room_user_provider();
|
|
|
152 |
}
|
|
|
153 |
|
|
|
154 |
/**
|
|
|
155 |
* Return the form provider.
|
|
|
156 |
*
|
|
|
157 |
* @return \core_communication\form_provider
|
|
|
158 |
*/
|
|
|
159 |
public function get_form_provider(): \core_communication\form_provider {
|
|
|
160 |
return $this->communication->get_form_provider();
|
|
|
161 |
}
|
|
|
162 |
|
|
|
163 |
/**
|
|
|
164 |
* Check if the communication api is enabled.
|
|
|
165 |
*/
|
|
|
166 |
public static function is_available(): bool {
|
|
|
167 |
return (bool) get_config('core', 'enablecommunicationsubsystem');
|
|
|
168 |
}
|
|
|
169 |
|
|
|
170 |
/**
|
|
|
171 |
* Get the communication room url.
|
|
|
172 |
*
|
|
|
173 |
* @return string|null
|
|
|
174 |
*/
|
|
|
175 |
public function get_communication_room_url(): ?string {
|
|
|
176 |
return $this->communication?->get_room_url();
|
|
|
177 |
}
|
|
|
178 |
|
|
|
179 |
/**
|
|
|
180 |
* Get the list of plugins for form selection.
|
|
|
181 |
*
|
|
|
182 |
* @return array
|
|
|
183 |
*/
|
|
|
184 |
public static function get_communication_plugin_list_for_form(): array {
|
|
|
185 |
// Add the option to have communication disabled.
|
|
|
186 |
$selection[processor::PROVIDER_NONE] = get_string('nocommunicationselected', 'communication');
|
|
|
187 |
$communicationplugins = \core\plugininfo\communication::get_enabled_plugins();
|
|
|
188 |
foreach ($communicationplugins as $pluginname => $notusing) {
|
|
|
189 |
$provider = 'communication_' . $pluginname;
|
|
|
190 |
if (processor::is_provider_available($provider)) {
|
|
|
191 |
$selection[$provider] = get_string('pluginname', 'communication_' . $pluginname);
|
|
|
192 |
}
|
|
|
193 |
}
|
|
|
194 |
return $selection;
|
|
|
195 |
}
|
|
|
196 |
|
|
|
197 |
/**
|
|
|
198 |
* Get the enabled communication providers and default provider according to the selected provider.
|
|
|
199 |
*
|
|
|
200 |
* @param string|null $selecteddefaulprovider
|
|
|
201 |
* @return array
|
|
|
202 |
*/
|
|
|
203 |
public static function get_enabled_providers_and_default(string $selecteddefaulprovider = null): array {
|
|
|
204 |
$communicationproviders = self::get_communication_plugin_list_for_form();
|
|
|
205 |
$defaulprovider = processor::PROVIDER_NONE;
|
|
|
206 |
if (!empty($selecteddefaulprovider) && array_key_exists($selecteddefaulprovider, $communicationproviders)) {
|
|
|
207 |
$defaulprovider = $selecteddefaulprovider;
|
|
|
208 |
}
|
|
|
209 |
return [$communicationproviders, $defaulprovider];
|
|
|
210 |
}
|
|
|
211 |
|
|
|
212 |
/**
|
|
|
213 |
* Define the form elements for the communication api.
|
|
|
214 |
* This method will be called from the form definition method of the instance.
|
|
|
215 |
*
|
|
|
216 |
* @param \MoodleQuickForm $mform The form element
|
|
|
217 |
* @param string $selectdefaultcommunication The default selected communication provider in the form field
|
|
|
218 |
*/
|
|
|
219 |
public function form_definition(
|
|
|
220 |
\MoodleQuickForm $mform,
|
|
|
221 |
string $selectdefaultcommunication = processor::PROVIDER_NONE
|
|
|
222 |
): void {
|
|
|
223 |
global $PAGE;
|
|
|
224 |
|
|
|
225 |
[$communicationproviders, $defaulprovider] = self::get_enabled_providers_and_default($selectdefaultcommunication);
|
|
|
226 |
|
|
|
227 |
$PAGE->requires->js_call_amd('core_communication/providerchooser', 'init');
|
|
|
228 |
|
|
|
229 |
// List the communication providers.
|
|
|
230 |
$mform->addElement(
|
|
|
231 |
'select',
|
|
|
232 |
'selectedcommunication',
|
|
|
233 |
get_string('selectcommunicationprovider', 'communication'),
|
|
|
234 |
$communicationproviders,
|
|
|
235 |
['data-communicationchooser-field' => 'selector'],
|
|
|
236 |
);
|
|
|
237 |
$mform->addHelpButton('selectedcommunication', 'selectcommunicationprovider', 'communication');
|
|
|
238 |
$mform->setDefault('selectedcommunication', $defaulprovider);
|
|
|
239 |
|
|
|
240 |
$mform->registerNoSubmitButton('updatecommunicationprovider');
|
|
|
241 |
$mform->addElement(
|
|
|
242 |
'submit',
|
|
|
243 |
'updatecommunicationprovider',
|
|
|
244 |
'update communication',
|
|
|
245 |
['data-communicationchooser-field' => 'updateButton', 'class' => 'd-none']
|
|
|
246 |
);
|
|
|
247 |
|
|
|
248 |
// Just a placeholder for the communication options.
|
|
|
249 |
$mform->addElement('hidden', 'addcommunicationoptionshere');
|
|
|
250 |
$mform->setType('addcommunicationoptionshere', PARAM_BOOL);
|
|
|
251 |
}
|
|
|
252 |
|
|
|
253 |
/**
|
|
|
254 |
* Set the form definitions for the plugins.
|
|
|
255 |
*
|
|
|
256 |
* @param \MoodleQuickForm $mform The moodle form
|
|
|
257 |
* @param string $provider The provider name
|
|
|
258 |
*/
|
|
|
259 |
public function form_definition_for_provider(\MoodleQuickForm $mform, string $provider = processor::PROVIDER_NONE): void {
|
|
|
260 |
if ($provider === processor::PROVIDER_NONE) {
|
|
|
261 |
return;
|
|
|
262 |
}
|
|
|
263 |
|
|
|
264 |
// Room name for the communication provider.
|
|
|
265 |
$mform->insertElementBefore(
|
|
|
266 |
$mform->createElement(
|
|
|
267 |
'text',
|
|
|
268 |
'communicationroomname',
|
|
|
269 |
get_string('communicationroomname', 'communication'),
|
|
|
270 |
'maxlength="100" size="20"'
|
|
|
271 |
),
|
|
|
272 |
'addcommunicationoptionshere'
|
|
|
273 |
);
|
|
|
274 |
$mform->setType('communicationroomname', PARAM_TEXT);
|
|
|
275 |
|
|
|
276 |
$mform->insertElementBefore(
|
|
|
277 |
$mform->createElement(
|
|
|
278 |
'static',
|
|
|
279 |
'communicationroomnameinfo',
|
|
|
280 |
'',
|
|
|
281 |
get_string('communicationroomnameinfo', 'communication'),
|
|
|
282 |
),
|
|
|
283 |
'addcommunicationoptionshere',
|
|
|
284 |
);
|
|
|
285 |
|
|
|
286 |
processor::set_provider_specific_form_definition($provider, $mform);
|
|
|
287 |
}
|
|
|
288 |
|
|
|
289 |
/**
|
|
|
290 |
* Get the avatar file.
|
|
|
291 |
*
|
|
|
292 |
* @return null|\stored_file
|
|
|
293 |
*/
|
|
|
294 |
public function get_avatar(): ?\stored_file {
|
|
|
295 |
$filename = $this->communication->get_avatar_filename();
|
|
|
296 |
if ($filename === null) {
|
|
|
297 |
return null;
|
|
|
298 |
}
|
|
|
299 |
$fs = get_file_storage();
|
|
|
300 |
$args = (array) $this->get_avatar_filerecord($filename);
|
|
|
301 |
return $fs->get_file(...$args) ?: null;
|
|
|
302 |
}
|
|
|
303 |
|
|
|
304 |
/**
|
|
|
305 |
* Get the avatar file record for the avatar for filesystem.
|
|
|
306 |
*
|
|
|
307 |
* @param string $filename The filename of the avatar
|
|
|
308 |
* @return stdClass
|
|
|
309 |
*/
|
|
|
310 |
protected function get_avatar_filerecord(string $filename): stdClass {
|
|
|
311 |
return (object) [
|
|
|
312 |
'contextid' => \core\context\system::instance()->id,
|
|
|
313 |
'component' => 'core_communication',
|
|
|
314 |
'filearea' => 'avatar',
|
|
|
315 |
'itemid' => $this->communication->get_id(),
|
|
|
316 |
'filepath' => '/',
|
|
|
317 |
'filename' => $filename,
|
|
|
318 |
];
|
|
|
319 |
}
|
|
|
320 |
|
|
|
321 |
/**
|
|
|
322 |
* Get the avatar file.
|
|
|
323 |
*
|
|
|
324 |
* If null is set, then delete the old area file and set the avatarfilename to null.
|
|
|
325 |
* This will make sure the plugin api deletes the avatar from the room.
|
|
|
326 |
*
|
|
|
327 |
* @param null|\stored_file $avatar The stored file for the avatar
|
|
|
328 |
* @return bool
|
|
|
329 |
*/
|
|
|
330 |
public function set_avatar(?\stored_file $avatar): bool {
|
|
|
331 |
$currentfilename = $this->communication->get_avatar_filename();
|
|
|
332 |
if ($avatar === null && empty($currentfilename)) {
|
|
|
333 |
return false;
|
|
|
334 |
}
|
|
|
335 |
|
|
|
336 |
$currentfilerecord = $this->get_avatar();
|
|
|
337 |
if ($avatar && $currentfilerecord) {
|
|
|
338 |
$currentfilehash = $currentfilerecord->get_contenthash();
|
|
|
339 |
$updatedfilehash = $avatar->get_contenthash();
|
|
|
340 |
|
|
|
341 |
// No update required.
|
|
|
342 |
if ($currentfilehash === $updatedfilehash) {
|
|
|
343 |
return false;
|
|
|
344 |
}
|
|
|
345 |
}
|
|
|
346 |
|
|
|
347 |
$context = \core\context\system::instance();
|
|
|
348 |
|
|
|
349 |
$fs = get_file_storage();
|
|
|
350 |
$fs->delete_area_files(
|
|
|
351 |
$context->id,
|
|
|
352 |
'core_communication',
|
|
|
353 |
'avatar',
|
|
|
354 |
$this->communication->get_id()
|
|
|
355 |
);
|
|
|
356 |
|
|
|
357 |
if ($avatar) {
|
|
|
358 |
$fs->create_file_from_storedfile(
|
|
|
359 |
$this->get_avatar_filerecord($avatar->get_filename()),
|
|
|
360 |
$avatar,
|
|
|
361 |
);
|
|
|
362 |
$this->communication->set_avatar_filename($avatar->get_filename());
|
|
|
363 |
} else {
|
|
|
364 |
$this->communication->set_avatar_filename(null);
|
|
|
365 |
}
|
|
|
366 |
|
|
|
367 |
// Indicate that we need to sync the avatar when the update task is run.
|
|
|
368 |
$this->communication->set_avatar_synced_flag(false);
|
|
|
369 |
|
|
|
370 |
return true;
|
|
|
371 |
}
|
|
|
372 |
|
|
|
373 |
/**
|
|
|
374 |
* A helper to fetch the room name
|
|
|
375 |
*
|
|
|
376 |
* @return string
|
|
|
377 |
*/
|
|
|
378 |
public function get_room_name(): string {
|
|
|
379 |
return $this->communication->get_room_name();
|
|
|
380 |
}
|
|
|
381 |
|
|
|
382 |
/**
|
|
|
383 |
* Set the form data if the data is already available.
|
|
|
384 |
*
|
|
|
385 |
* @param \stdClass $instance The instance object
|
|
|
386 |
*/
|
|
|
387 |
public function set_data(\stdClass $instance): void {
|
|
|
388 |
if (!empty($instance->id) && $this->communication) {
|
|
|
389 |
$instance->selectedcommunication = $this->communication->get_provider();
|
|
|
390 |
$instance->communicationroomname = $this->communication->get_room_name();
|
|
|
391 |
|
|
|
392 |
$this->communication->get_form_provider()->set_form_data($instance);
|
|
|
393 |
}
|
|
|
394 |
}
|
|
|
395 |
|
|
|
396 |
/**
|
|
|
397 |
* Get the communication provider.
|
|
|
398 |
*
|
|
|
399 |
* @return string
|
|
|
400 |
*/
|
|
|
401 |
public function get_provider(): string {
|
|
|
402 |
if (!$this->communication) {
|
|
|
403 |
return '';
|
|
|
404 |
}
|
|
|
405 |
return $this->communication->get_provider();
|
|
|
406 |
}
|
|
|
407 |
|
|
|
408 |
/**
|
|
|
409 |
* Configure the room and membership by provider selected for the communication instance.
|
|
|
410 |
*
|
|
|
411 |
* This method will add a task to the queue to configure the room and membership by comparing the change of provider.
|
|
|
412 |
* There are some major cases to consider for this method to allow minimum duplication when this api is used.
|
|
|
413 |
* Some of the major cases are:
|
|
|
414 |
* 1. If the communication instance is not created at all, then create it and add members.
|
|
|
415 |
* 2. If the current provider is none and the new provider is also none, then nothing to do.
|
|
|
416 |
* 3. If the current and existing provider is the same, don't need to do anything.
|
|
|
417 |
* 4. If provider set to none, remove all the members.
|
|
|
418 |
* 5. If previous provider was not none and current provider is not none, but a different provider, remove members and add
|
|
|
419 |
* for the new one.
|
|
|
420 |
* 6. If previous provider was none and current provider is not none, don't need to remove, just
|
|
|
421 |
* update the selected provider and add users to that provider. Do not queue the task to add members to room as the room
|
|
|
422 |
* might not have created yet. The add room task adds the task to add members to room anyway.
|
|
|
423 |
* 7. If it's a new provider, never used/created, now create the room after considering all these cases for a new provider.
|
|
|
424 |
*
|
|
|
425 |
* @param string $provider The provider name
|
|
|
426 |
* @param \stdClass $instance The instance object
|
|
|
427 |
* @param string $communicationroomname The communication room name
|
|
|
428 |
* @param array $users The user ids to add to the room
|
|
|
429 |
* @param null|\stored_file $instanceimage The stored file for the avatar
|
|
|
430 |
* @param bool $queue Queue the task for the provider room or not
|
|
|
431 |
*/
|
|
|
432 |
public function configure_room_and_membership_by_provider(
|
|
|
433 |
string $provider,
|
|
|
434 |
stdClass $instance,
|
|
|
435 |
string $communicationroomname,
|
|
|
436 |
array $users,
|
|
|
437 |
?\stored_file $instanceimage = null,
|
|
|
438 |
bool $queue = true,
|
|
|
439 |
): void {
|
|
|
440 |
// If the current provider is inactive and the new provider is also none, then nothing to do.
|
|
|
441 |
if (
|
|
|
442 |
$this->communication !== null &&
|
|
|
443 |
$this->communication->get_provider_status() === processor::PROVIDER_INACTIVE &&
|
|
|
444 |
$provider === processor::PROVIDER_NONE
|
|
|
445 |
) {
|
|
|
446 |
return;
|
|
|
447 |
}
|
|
|
448 |
|
|
|
449 |
// If provider set to none, remove all the members.
|
|
|
450 |
if (
|
|
|
451 |
$this->communication !== null &&
|
|
|
452 |
$this->communication->get_provider_status() === processor::PROVIDER_ACTIVE &&
|
|
|
453 |
$provider === processor::PROVIDER_NONE
|
|
|
454 |
) {
|
|
|
455 |
$this->remove_all_members_from_room();
|
|
|
456 |
$this->update_room(
|
|
|
457 |
active: processor::PROVIDER_INACTIVE,
|
|
|
458 |
communicationroomname: $communicationroomname,
|
|
|
459 |
avatar: $instanceimage,
|
|
|
460 |
instance: $instance,
|
|
|
461 |
queue: $queue,
|
|
|
462 |
);
|
|
|
463 |
return;
|
|
|
464 |
}
|
|
|
465 |
|
|
|
466 |
if (
|
|
|
467 |
// If previous provider was active and not none and current provider is not none, but a different provider,
|
|
|
468 |
// remove members and de-activate the previous provider.
|
|
|
469 |
$this->communication !== null &&
|
|
|
470 |
$this->communication->get_provider_status() === processor::PROVIDER_ACTIVE &&
|
|
|
471 |
$provider !== $this->get_provider()
|
|
|
472 |
) {
|
|
|
473 |
$this->remove_all_members_from_room();
|
|
|
474 |
// Now deactivate the previous provider.
|
|
|
475 |
$this->update_room(
|
|
|
476 |
active: processor::PROVIDER_INACTIVE,
|
|
|
477 |
communicationroomname: $communicationroomname,
|
|
|
478 |
avatar: $instanceimage,
|
|
|
479 |
instance: $instance,
|
|
|
480 |
queue: $queue,
|
|
|
481 |
);
|
|
|
482 |
}
|
|
|
483 |
|
|
|
484 |
// Now re-init the constructor for the new provider.
|
|
|
485 |
$this->__construct(
|
|
|
486 |
context: $this->context,
|
|
|
487 |
component: $this->component,
|
|
|
488 |
instancetype: $this->instancetype,
|
|
|
489 |
instanceid: $this->instanceid,
|
|
|
490 |
provider: $provider,
|
|
|
491 |
);
|
|
|
492 |
|
|
|
493 |
// If it's a new provider, never used/created, now create the room.
|
|
|
494 |
if ($this->communication === null) {
|
|
|
495 |
$this->create_and_configure_room(
|
|
|
496 |
communicationroomname: $communicationroomname,
|
|
|
497 |
avatar: $instanceimage,
|
|
|
498 |
instance: $instance,
|
|
|
499 |
queue: $queue,
|
|
|
500 |
);
|
|
|
501 |
$queueusertask = false;
|
|
|
502 |
} else {
|
|
|
503 |
// Otherwise update the room.
|
|
|
504 |
$this->update_room(
|
|
|
505 |
active: processor::PROVIDER_ACTIVE,
|
|
|
506 |
communicationroomname: $communicationroomname,
|
|
|
507 |
avatar: $instanceimage,
|
|
|
508 |
instance: $instance,
|
|
|
509 |
queue: $queue,
|
|
|
510 |
);
|
|
|
511 |
$queueusertask = true;
|
|
|
512 |
}
|
|
|
513 |
|
|
|
514 |
// Now add the members.
|
|
|
515 |
$this->add_members_to_room(
|
|
|
516 |
userids: $users,
|
|
|
517 |
queue: $queueusertask,
|
|
|
518 |
);
|
|
|
519 |
|
|
|
520 |
}
|
|
|
521 |
|
|
|
522 |
/**
|
|
|
523 |
* Create a communication ad-hoc task for create operation.
|
|
|
524 |
* This method will add a task to the queue to create the room.
|
|
|
525 |
*
|
|
|
526 |
* @param string $communicationroomname The communication room name
|
|
|
527 |
* @param null|\stored_file $avatar The stored file for the avatar
|
|
|
528 |
* @param \stdClass|null $instance The actual instance object
|
|
|
529 |
* @param bool $queue Whether to queue the task or not
|
|
|
530 |
*/
|
|
|
531 |
public function create_and_configure_room(
|
|
|
532 |
string $communicationroomname,
|
|
|
533 |
?\stored_file $avatar = null,
|
|
|
534 |
?\stdClass $instance = null,
|
|
|
535 |
bool $queue = true,
|
|
|
536 |
): void {
|
|
|
537 |
if ($this->provider === processor::PROVIDER_NONE || $this->provider === '') {
|
|
|
538 |
return;
|
|
|
539 |
}
|
|
|
540 |
// Create communication record.
|
|
|
541 |
$this->communication = processor::create_instance(
|
|
|
542 |
context: $this->context,
|
|
|
543 |
provider: $this->provider,
|
|
|
544 |
instanceid: $this->instanceid,
|
|
|
545 |
component: $this->component,
|
|
|
546 |
instancetype: $this->instancetype,
|
|
|
547 |
roomname: $communicationroomname,
|
|
|
548 |
);
|
|
|
549 |
|
|
|
550 |
// Update provider record from form data.
|
|
|
551 |
if ($instance !== null) {
|
|
|
552 |
$this->communication->get_form_provider()->save_form_data($instance);
|
|
|
553 |
}
|
|
|
554 |
|
|
|
555 |
// Set the avatar.
|
|
|
556 |
if (!empty($avatar)) {
|
|
|
557 |
$this->set_avatar($avatar);
|
|
|
558 |
}
|
|
|
559 |
|
|
|
560 |
// Nothing else to do if the queue is false.
|
|
|
561 |
if (!$queue) {
|
|
|
562 |
return;
|
|
|
563 |
}
|
|
|
564 |
|
|
|
565 |
// Add ad-hoc task to create the provider room.
|
|
|
566 |
create_and_configure_room_task::queue(
|
|
|
567 |
$this->communication,
|
|
|
568 |
);
|
|
|
569 |
}
|
|
|
570 |
|
|
|
571 |
/**
|
|
|
572 |
* Create a communication ad-hoc task for update operation.
|
|
|
573 |
* This method will add a task to the queue to update the room.
|
|
|
574 |
*
|
|
|
575 |
* @param null|int $active The selected active state of the provider
|
|
|
576 |
* @param null|string $communicationroomname The communication room name
|
|
|
577 |
* @param null|\stored_file $avatar The stored file for the avatar
|
|
|
578 |
* @param \stdClass|null $instance The actual instance object
|
|
|
579 |
* @param bool $queue Whether to queue the task or not
|
|
|
580 |
*/
|
|
|
581 |
public function update_room(
|
|
|
582 |
?int $active = null,
|
|
|
583 |
?string $communicationroomname = null,
|
|
|
584 |
?\stored_file $avatar = null,
|
|
|
585 |
?\stdClass $instance = null,
|
|
|
586 |
bool $queue = true,
|
|
|
587 |
): void {
|
|
|
588 |
if (!$this->communication) {
|
|
|
589 |
return;
|
|
|
590 |
}
|
|
|
591 |
|
|
|
592 |
// If the provider is none, we don't need to do anything from room point of view.
|
|
|
593 |
if ($this->communication->get_provider() === processor::PROVIDER_NONE) {
|
|
|
594 |
return;
|
|
|
595 |
}
|
|
|
596 |
|
|
|
597 |
$roomnamechange = null;
|
|
|
598 |
$activestatuschange = null;
|
|
|
599 |
|
|
|
600 |
// Check if the room name is being changed.
|
|
|
601 |
if (
|
|
|
602 |
$communicationroomname !== null &&
|
|
|
603 |
$communicationroomname !== $this->communication->get_room_name()
|
|
|
604 |
) {
|
|
|
605 |
$roomnamechange = $communicationroomname;
|
|
|
606 |
}
|
|
|
607 |
|
|
|
608 |
// Check if the active status of the provider is being changed.
|
|
|
609 |
if (
|
|
|
610 |
$active !== null &&
|
|
|
611 |
$active !== $this->communication->is_instance_active()
|
|
|
612 |
) {
|
|
|
613 |
$activestatuschange = $active;
|
|
|
614 |
}
|
|
|
615 |
|
|
|
616 |
if ($roomnamechange !== null || $activestatuschange !== null) {
|
|
|
617 |
$this->communication->update_instance(
|
|
|
618 |
active: $active,
|
|
|
619 |
roomname: $communicationroomname,
|
|
|
620 |
);
|
|
|
621 |
}
|
|
|
622 |
|
|
|
623 |
// Update provider record from form data.
|
|
|
624 |
if ($instance !== null) {
|
|
|
625 |
$this->communication->get_form_provider()->save_form_data($instance);
|
|
|
626 |
}
|
|
|
627 |
|
|
|
628 |
// Update the avatar.
|
|
|
629 |
// If the value is `null`, then unset the avatar.
|
|
|
630 |
$this->set_avatar($avatar);
|
|
|
631 |
|
|
|
632 |
// Nothing else to do if the queue is false.
|
|
|
633 |
if (!$queue) {
|
|
|
634 |
return;
|
|
|
635 |
}
|
|
|
636 |
|
|
|
637 |
// Always queue a room update, even if none of the above standard fields have changed.
|
|
|
638 |
// It is possible for providers to have custom fields that have been updated.
|
|
|
639 |
update_room_task::queue(
|
|
|
640 |
$this->communication,
|
|
|
641 |
);
|
|
|
642 |
}
|
|
|
643 |
|
|
|
644 |
/**
|
|
|
645 |
* Create a communication ad-hoc task for delete operation.
|
|
|
646 |
* This method will add a task to the queue to delete the room.
|
|
|
647 |
*/
|
|
|
648 |
public function delete_room(): void {
|
|
|
649 |
if ($this->communication !== null) {
|
|
|
650 |
// Add the ad-hoc task to remove the room data from the communication table and associated provider actions.
|
|
|
651 |
delete_room_task::queue(
|
|
|
652 |
$this->communication,
|
|
|
653 |
);
|
|
|
654 |
}
|
|
|
655 |
}
|
|
|
656 |
|
|
|
657 |
/**
|
|
|
658 |
* Create a communication ad-hoc task for add members operation and add the user mapping.
|
|
|
659 |
*
|
|
|
660 |
* This method will add a task to the queue to add the room users.
|
|
|
661 |
*
|
|
|
662 |
* @param array $userids The user ids to add to the room
|
|
|
663 |
* @param bool $queue Whether to queue the task or not
|
|
|
664 |
*/
|
|
|
665 |
public function add_members_to_room(array $userids, bool $queue = true): void {
|
|
|
666 |
// No communication object? something not done right.
|
|
|
667 |
if (!$this->communication) {
|
|
|
668 |
return;
|
|
|
669 |
}
|
|
|
670 |
|
|
|
671 |
// No user IDs or this provider does not manage users? No action required.
|
|
|
672 |
if (empty($userids) || !$this->communication->supports_user_features()) {
|
|
|
673 |
return;
|
|
|
674 |
}
|
|
|
675 |
|
|
|
676 |
$this->communication->create_instance_user_mapping($userids);
|
|
|
677 |
|
|
|
678 |
if ($queue) {
|
|
|
679 |
add_members_to_room_task::queue(
|
|
|
680 |
$this->communication
|
|
|
681 |
);
|
|
|
682 |
}
|
|
|
683 |
}
|
|
|
684 |
|
|
|
685 |
/**
|
|
|
686 |
* Create a communication ad-hoc task for updating members operation and update the user mapping.
|
|
|
687 |
*
|
|
|
688 |
* This method will add a task to the queue to update the room users.
|
|
|
689 |
*
|
|
|
690 |
* @param array $userids The user ids to add to the room
|
|
|
691 |
* @param bool $queue Whether to queue the task or not
|
|
|
692 |
*/
|
|
|
693 |
public function update_room_membership(array $userids, bool $queue = true): void {
|
|
|
694 |
// No communication object? something not done right.
|
|
|
695 |
if (!$this->communication) {
|
|
|
696 |
return;
|
|
|
697 |
}
|
|
|
698 |
|
|
|
699 |
// No userids? don't bother doing anything.
|
|
|
700 |
if (empty($userids)) {
|
|
|
701 |
return;
|
|
|
702 |
}
|
|
|
703 |
|
|
|
704 |
$this->communication->reset_users_sync_flag($userids);
|
|
|
705 |
|
|
|
706 |
if ($queue) {
|
|
|
707 |
update_room_membership_task::queue(
|
|
|
708 |
$this->communication
|
|
|
709 |
);
|
|
|
710 |
}
|
|
|
711 |
}
|
|
|
712 |
|
|
|
713 |
/**
|
|
|
714 |
* Create a communication ad-hoc task for remove members operation or action immediately.
|
|
|
715 |
*
|
|
|
716 |
* This method will add a task to the queue to remove the room users.
|
|
|
717 |
*
|
|
|
718 |
* @param array $userids The user ids to remove from the room
|
|
|
719 |
* @param bool $queue Whether to queue the task or not
|
|
|
720 |
*/
|
|
|
721 |
public function remove_members_from_room(array $userids, bool $queue = true): void {
|
|
|
722 |
// No communication object? something not done right.
|
|
|
723 |
if (!$this->communication) {
|
|
|
724 |
return;
|
|
|
725 |
}
|
|
|
726 |
|
|
|
727 |
$provider = $this->communication->get_provider();
|
|
|
728 |
|
|
|
729 |
if ($provider === processor::PROVIDER_NONE) {
|
|
|
730 |
return;
|
|
|
731 |
}
|
|
|
732 |
|
|
|
733 |
// No user IDs or this provider does not manage users? No action required.
|
|
|
734 |
if (empty($userids) || !$this->communication->supports_user_features()) {
|
|
|
735 |
return;
|
|
|
736 |
}
|
|
|
737 |
|
|
|
738 |
$this->communication->add_delete_user_flag($userids);
|
|
|
739 |
|
|
|
740 |
if ($queue) {
|
|
|
741 |
remove_members_from_room::queue(
|
|
|
742 |
$this->communication
|
|
|
743 |
);
|
|
|
744 |
}
|
|
|
745 |
}
|
|
|
746 |
|
|
|
747 |
/**
|
|
|
748 |
* Remove all users from the room.
|
|
|
749 |
*
|
|
|
750 |
* @param bool $queue Whether to queue the task or not
|
|
|
751 |
*/
|
|
|
752 |
public function remove_all_members_from_room(bool $queue = true): void {
|
|
|
753 |
// No communication object? something not done right.
|
|
|
754 |
if (!$this->communication) {
|
|
|
755 |
return;
|
|
|
756 |
}
|
|
|
757 |
|
|
|
758 |
if ($this->communication->get_provider() === processor::PROVIDER_NONE) {
|
|
|
759 |
return;
|
|
|
760 |
}
|
|
|
761 |
|
|
|
762 |
// This provider does not manage users? No action required.
|
|
|
763 |
if (!$this->communication->supports_user_features()) {
|
|
|
764 |
return;
|
|
|
765 |
}
|
|
|
766 |
|
|
|
767 |
$this->communication->add_delete_user_flag($this->communication->get_all_userids_for_instance());
|
|
|
768 |
|
|
|
769 |
if ($queue) {
|
|
|
770 |
remove_members_from_room::queue(
|
|
|
771 |
$this->communication
|
|
|
772 |
);
|
|
|
773 |
}
|
|
|
774 |
}
|
|
|
775 |
|
|
|
776 |
/**
|
|
|
777 |
* Display the communication room status notification.
|
|
|
778 |
*/
|
|
|
779 |
public function show_communication_room_status_notification(): void {
|
|
|
780 |
// No communication, no room.
|
|
|
781 |
if (!$this->communication) {
|
|
|
782 |
return;
|
|
|
783 |
}
|
|
|
784 |
|
|
|
785 |
if ($this->communication->get_provider() === processor::PROVIDER_NONE) {
|
|
|
786 |
return;
|
|
|
787 |
}
|
|
|
788 |
|
|
|
789 |
$roomstatus = $this->get_communication_room_url()
|
|
|
790 |
? constants::COMMUNICATION_STATUS_READY
|
|
|
791 |
: constants::COMMUNICATION_STATUS_PENDING;
|
|
|
792 |
$pluginname = get_string('pluginname', $this->get_provider());
|
|
|
793 |
$message = get_string('communicationroom' . $roomstatus, 'communication', $pluginname);
|
|
|
794 |
|
|
|
795 |
// We only show the ready notification once per user.
|
|
|
796 |
// We check this with a custom user preference.
|
|
|
797 |
$roomreadypreference = "{$this->component}_{$this->instancetype}_{$this->instanceid}_room_ready";
|
|
|
798 |
|
|
|
799 |
switch ($roomstatus) {
|
|
|
800 |
case constants::COMMUNICATION_STATUS_PENDING:
|
|
|
801 |
\core\notification::add($message, \core\notification::INFO);
|
|
|
802 |
unset_user_preference($roomreadypreference);
|
|
|
803 |
break;
|
|
|
804 |
|
|
|
805 |
case constants::COMMUNICATION_STATUS_READY:
|
|
|
806 |
if (empty(get_user_preferences($roomreadypreference))) {
|
|
|
807 |
\core\notification::add($message, \core\notification::SUCCESS);
|
|
|
808 |
set_user_preference($roomreadypreference, true);
|
|
|
809 |
}
|
|
|
810 |
break;
|
|
|
811 |
}
|
|
|
812 |
}
|
|
|
813 |
|
|
|
814 |
/**
|
|
|
815 |
* Add the task to sync the provider data with local Moodle data.
|
|
|
816 |
*/
|
|
|
817 |
public function sync_provider(): void {
|
|
|
818 |
// No communication, return.
|
|
|
819 |
if (!$this->communication) {
|
|
|
820 |
return;
|
|
|
821 |
}
|
|
|
822 |
|
|
|
823 |
if ($this->communication->get_provider() === processor::PROVIDER_NONE) {
|
|
|
824 |
return;
|
|
|
825 |
}
|
|
|
826 |
|
|
|
827 |
synchronise_provider_task::queue(
|
|
|
828 |
$this->communication
|
|
|
829 |
);
|
|
|
830 |
}
|
|
|
831 |
}
|