Proyectos de Subversion Moodle

Rev

Ir a la última revisión | | 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 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
}