Skip to content

Commit

Permalink
MDL-79573 communication: Support new records for each provider type
Browse files Browse the repository at this point in the history
Previously, we replaced information in the same communication record
in the database, now there will be a unique record per provider.
This ensures when switching between different providers, the correct
actions such as room member management can be actioned for the correct
provider.

This also includes the required updates for the instances to no
longer assume a provider must be enabled to be relevant. Specifying a
provider is optional to fetch a specific provider instance, the default
will use the currently enabled provider.
  • Loading branch information
mickhawkins committed Oct 5, 2023
1 parent 0350bc8 commit 93c5ae3
Show file tree
Hide file tree
Showing 4 changed files with 208 additions and 140 deletions.
203 changes: 101 additions & 102 deletions communication/classes/api.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,19 +56,22 @@ class api {
* @param string $component The component of the item for the instance
* @param string $instancetype The type of the item for the instance
* @param int $instanceid The id of the instance
* @param string|null $provider The provider type - if null will load for this context's active provider.
*
*/
private function __construct(
private context $context,
private string $component,
private string $instancetype,
private int $instanceid,
private ?string $provider = null,
) {
$this->communication = processor::load_by_instance(
context: $context,
component: $component,
instancetype: $instancetype,
instanceid: $instanceid,
provider: $provider,
);
}

Expand All @@ -79,19 +82,22 @@ private function __construct(
* @param string $component The component of the item for the instance
* @param string $instancetype The type of the item for the instance
* @param int $instanceid The id of the instance
* @param string|null $provider The provider type - if null will load for this context's active provider.
* @return api
*/
public static function load_by_instance(
context $context,
string $component,
string $instancetype,
int $instanceid,
?string $provider = null,
): self {
return new self(
context: $context,
component: $component,
instancetype: $instancetype,
instanceid: $instanceid,
provider: $provider,
);
}

Expand All @@ -104,6 +110,7 @@ public function reload(): void {
component: $this->component,
instancetype: $this->instancetype,
instanceid: $this->instanceid,
provider: $this->provider,
);
}

Expand Down Expand Up @@ -246,31 +253,33 @@ public function form_definition(
* @param string $provider The provider name
*/
public function form_definition_for_provider(\MoodleQuickForm $mform, string $provider = processor::PROVIDER_NONE): void {
if ($provider !== processor::PROVIDER_NONE) {
// Room name for the communication provider.
$mform->insertElementBefore(
$mform->createElement(
'text',
'communicationroomname',
get_string('communicationroomname', 'communication'),
'maxlength="100" size="20"'
),
'addcommunicationoptionshere'
);
$mform->setType('communicationroomname', PARAM_TEXT);

$mform->insertElementBefore(
$mform->createElement(
'static',
'communicationroomnameinfo',
'',
get_string('communicationroomnameinfo', 'communication'),
),
'addcommunicationoptionshere',
);

processor::set_provider_specific_form_definition($provider, $mform);
if ($provider === processor::PROVIDER_NONE) {
return;
}

// Room name for the communication provider.
$mform->insertElementBefore(
$mform->createElement(
'text',
'communicationroomname',
get_string('communicationroomname', 'communication'),
'maxlength="100" size="20"'
),
'addcommunicationoptionshere'
);
$mform->setType('communicationroomname', PARAM_TEXT);

$mform->insertElementBefore(
$mform->createElement(
'static',
'communicationroomnameinfo',
'',
get_string('communicationroomnameinfo', 'communication'),
),
'addcommunicationoptionshere',
);

processor::set_provider_specific_form_definition($provider, $mform);
}

/**
Expand Down Expand Up @@ -407,109 +416,99 @@ public function create_and_configure_room(
?\stored_file $avatar = null,
?\stdClass $instance = null,
): void {
if ($selectedcommunication !== processor::PROVIDER_NONE && $selectedcommunication !== '') {
// Create communication record.
$this->communication = processor::create_instance(
context: $this->context,
provider: $selectedcommunication,
instanceid: $this->instanceid,
component: $this->component,
instancetype: $this->instancetype,
roomname: $communicationroomname,
);
if ($selectedcommunication === processor::PROVIDER_NONE || $selectedcommunication === '') {
return;
}

// Update provider record from form data.
if ($instance !== null) {
$this->communication->get_form_provider()->save_form_data($instance);
}
// Create communication record.
$this->communication = processor::create_instance(
context: $this->context,
provider: $selectedcommunication,
instanceid: $this->instanceid,
component: $this->component,
instancetype: $this->instancetype,
roomname: $communicationroomname,
);

// Set the avatar.
if (!empty($avatar)) {
$this->set_avatar($avatar);
}
// Update provider record from form data.
if ($instance !== null) {
$this->communication->get_form_provider()->save_form_data($instance);
}

// Add ad-hoc task to create the provider room.
create_and_configure_room_task::queue(
$this->communication,
);
// Set the avatar.
if (!empty($avatar)) {
$this->set_avatar($avatar);
}

// Add ad-hoc task to create the provider room.
create_and_configure_room_task::queue(
$this->communication,
);
}

/**
* Create a communication ad-hoc task for update operation.
* This method will add a task to the queue to update the room.
*
* @param string $selectedprovider The selected communication provider
* @param string $communicationroomname The communication room name
* @param null|int $active The selected active state of the provider
* @param null|string $communicationroomname The communication room name
* @param null|\stored_file $avatar The stored file for the avatar
* @param \stdClass|null $instance The actual instance object
*/
public function update_room(
?string $selectedprovider = null,
?int $active = null,
?string $communicationroomname = null,
?\stored_file $avatar = null,
?\stdClass $instance = null,
): void {
// Existing object found, let's update the communication record and associated actions.
if ($this->communication !== null) {
// Get the previous data to compare for update.
$previousprovider = $this->communication->get_provider();
if ($previousprovider === $selectedprovider) {
// If the provider is the same, unset it.
$selectedprovider = null;
}

$previousroomname = $this->communication->get_room_name();
if ($previousroomname === $communicationroomname) {
// If the room name is the same, we don't need to update the room.
$communicationroomname = null;
}
// Reload so the currently selected provider is used.
$this->reload();

if ($selectedprovider !== null || $communicationroomname !== null) {
// Something to update. Update communication record.
$this->communication->update_instance(
provider: $selectedprovider,
roomname: $communicationroomname,
);
}
// If the provider is none, we don't need to do anything from room point of view.
if ($this->communication->get_provider() === processor::PROVIDER_NONE) {
return;
}

// Reload so the currently selected provider is used.
$this->reload();
$roomnamechange = null;
$activestatuschange = null;

// Update provider record from form data.
if ($instance !== null) {
$this->communication->get_form_provider()->save_form_data($instance);
}
// Check if the room name is being changed.
if (
$communicationroomname !== null &&
$communicationroomname !== $this->communication->get_room_name()
) {
$roomnamechange = $communicationroomname;
}

// Update the avatar.
// If the value is `null`, then unset the avatar.
$this->set_avatar($avatar);
// Check if the active status of the provider is being changed.
if (
$active !== null &&
$active !== $this->communication->is_instance_active()
) {
$activestatuschange = $active;
}

// If the provider is none, we don't need to do anything from room point of view.
if ($this->communication->get_provider() === processor::PROVIDER_NONE) {
return;
}
if ($roomnamechange !== null || $activestatuschange !== null) {
$this->communication->update_instance(
active: $active,
roomname: $communicationroomname,
);
}

// Add ad-hoc task to update the provider room if the room name changed.
// TODO add efficiency considering dynamic fields.
if (
$previousprovider === $selectedprovider
) {
update_room_task::queue(
$this->communication,
);
} else if (
$previousprovider !== $selectedprovider
) {
// Add ad-hoc task to create the provider room.
create_and_configure_room_task::queue(
$this->communication,
);
}
} else {
// The instance didn't have any communication record, so create one.
$this->create_and_configure_room($selectedprovider, $communicationroomname, $avatar, $instance);
// Update provider record from form data.
if ($instance !== null) {
$this->communication->get_form_provider()->save_form_data($instance);
}

// Update the avatar.
// If the value is `null`, then unset the avatar.
$this->set_avatar($avatar);

// Always queue a room update, even if none of the above standard fields have changed.
// It is possible for providers to have custom fields that have been updated.
update_room_task::queue(
$this->communication,
);
}

/**
Expand Down
50 changes: 28 additions & 22 deletions communication/classes/processor.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,22 +109,17 @@ public static function create_instance(
/**
* Update the communication instance with any changes.
*
* @param null|string $provider The communication provider
* @param null|int $active Active state of the instance (PROVIDER_ACTIVE or PROVIDER_INACTIVE)
* @param null|string $roomname The room name
*/
public function update_instance(
?string $provider = null,
?string $active = null,
?string $roomname = null,
): void {
global $DB;

if ($provider !== null) {
if ($provider === self::PROVIDER_NONE) {
$this->instancedata->active = self::PROVIDER_INACTIVE;
} else {
$this->instancedata->provider = $provider;
$this->instancedata->active = self::PROVIDER_ACTIVE;
}
if ($active !== null && in_array($active, [self::PROVIDER_ACTIVE, self::PROVIDER_INACTIVE])) {
$this->instancedata->active = $active;
}

if ($roomname !== null) {
Expand Down Expand Up @@ -365,24 +360,38 @@ public static function load_by_id(int $id): ?self {
* @param string $component The component name
* @param string $instancetype The instance type
* @param int $instanceid The instance id
* @param string|null $provider The provider type - if null will load for this context's active provider.
* @return processor|null
*/
public static function load_by_instance(
context $context,
string $component,
string $instancetype,
int $instanceid
int $instanceid,
?string $provider = null,
): ?self {

global $DB;

$record = $DB->get_record('communication', [
'contextid' => $context->id,
'instanceid' => $instanceid,
'component' => $component,
'instancetype' => $instancetype,
]);

if ($provider === null) {
// Fetch the active provider in this context.
$record = $DB->get_record('communication', [
'contextid' => $context->id,
'instanceid' => $instanceid,
'component' => $component,
'instancetype' => $instancetype,
'active' => 1,
]);
} else {
// Fetch a specific provider in this context (which may be inactive).
$record = $DB->get_record('communication', [
'contextid' => $context->id,
'instanceid' => $instanceid,
'component' => $component,
'instancetype' => $instancetype,
'provider' => $provider,
]);
}
if ($record && self::is_provider_available($record->provider)) {
return new self($record);
}
Expand Down Expand Up @@ -464,15 +473,12 @@ public function get_component(): string {
}

/**
* Get communication provider.
* Get communication provider type.
*
* @return string|null
*/
public function get_provider(): ?string {
if ((int)$this->instancedata->active === self::PROVIDER_ACTIVE) {
return $this->instancedata->provider;
}
return self::PROVIDER_NONE;
return $this->instancedata->provider;
}

/**
Expand Down
1 change: 1 addition & 0 deletions communication/configure.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
component: $component,
instancetype: $instancetype,
instanceid: $instanceid,
provider: $selectedcommunication,
);

// No communication, no way this form can be used.
Expand Down
Loading

0 comments on commit 93c5ae3

Please sign in to comment.