Skip to content

Commit

Permalink
MDL-78619 communication_customlink: Implement custom link provider
Browse files Browse the repository at this point in the history
  • Loading branch information
mickhawkins committed Aug 27, 2023
1 parent bfbb314 commit a3fa3e3
Show file tree
Hide file tree
Showing 9 changed files with 564 additions and 0 deletions.
168 changes: 168 additions & 0 deletions communication/provider/customlink/classes/communication_feature.php
@@ -0,0 +1,168 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

namespace communication_customlink;

use core_communication\processor;

/**
* class communication_feature to handle custom link specific actions.
*
* @package communication_customlink
* @copyright 2023 Michael Hawkins <michaelh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class communication_feature implements
\core_communication\communication_provider,
\core_communication\room_chat_provider,
\core_communication\form_provider {

/** @var string The database table storing custom link specific data */
protected const CUSTOMLINK_TABLE = 'communication_customlink';

/** @var \cache_application $cache The application cache for this provider. */
protected \cache_application $cache;

/**
* Load the communication provider for the communication API.
*
* @param processor $communication The communication processor object.
* @return communication_feature The communication provider object.
*/
public static function load_for_instance(processor $communication): self {
return new self($communication);
}

/**
* Constructor for communication provider.
*
* @param processor $communication The communication processor object.
*/
private function __construct(
private \core_communication\processor $communication,
) {
$this->cache = \cache::make('communication_customlink', 'customlink');
}

/**
* Create room - room existence managed externally, always return true.
*
* @return boolean
*/
public function create_chat_room(): bool {
return true;
}

/**
* Update room - room existence managed externally, always return true.
*
* @return boolean
*/
public function update_chat_room(): bool {
return true;
}

/**
* Delete room - room existence managed externally, always return true.
*
* @return boolean
*/
public function delete_chat_room(): bool {
return true;
}

/**
* Fetch the URL for this custom link provider.
*
* @return string|null The custom URL, or null if not found.
*/
public function get_chat_room_url(): ?string {
global $DB;

$commid = $this->communication->get_id();
$cachekey = "link_url_{$commid}";

// Attempt to fetch the room URL from the cache.
if ($url = $this->cache->get($cachekey)) {
return $url;
}

// If not found in the cache, fetch the URL from the database.
$url = $DB->get_field(
self::CUSTOMLINK_TABLE,
'url',
['commid' => $commid],
);

// Cache the URL.
$this->cache->set($cachekey, $url);

return $url;
}

public function save_form_data(\stdClass $instance): void {
global $DB;

$commid = $this->communication->get_id();
$cachekey = "link_url_{$commid}";

$newrecord = new \stdClass();
$newrecord->url = $instance->customlinkurl ?? null;

$existingrecord = $DB->get_record(
self::CUSTOMLINK_TABLE,
['commid' => $commid],
'id, url'
);

if (!$existingrecord) {
// Create the record if it does not exist.
$newrecord->commid = $commid;
$DB->insert_record(self::CUSTOMLINK_TABLE, $newrecord);

} else if ($newrecord->url !== $existingrecord->url) {
// Update record if the URL has changed.
$newrecord->id = $existingrecord->id;
$DB->update_record(self::CUSTOMLINK_TABLE, $newrecord);
} else {
// No change made.
return;
}

// Cache the new URL.
$this->cache->set($cachekey, $newrecord->url);
}

public function set_form_data(\stdClass $instance): void {
if (!empty($instance->id) && !empty($this->communication->get_id())) {
$instance->customlinkurl = $this->get_chat_room_url();
}
}

public static function set_form_definition(\MoodleQuickForm $mform): void {
// Custom link description for the communication provider.
$mform->insertElementBefore($mform->createElement('text', 'customlinkurl',
get_string('customlinkurl', 'communication_customlink'),
'maxlength="255" size="40"'), 'addcommunicationoptionshere');
$mform->addHelpButton('customlinkurl', 'customlinkurl', 'communication_customlink');
$mform->setType('customlinkurl', PARAM_URL);
$mform->addRule('customlinkurl', get_string('required'), 'required', null, 'client');
$mform->addRule('customlinkurl', get_string('maximumchars', '', 255), 'maxlength', 255);
$mform->insertElementBefore($mform->createElement('static', 'customlinkurlinfo', '',
get_string('customlinkurlinfo', 'communication_customlink'),
'addcommunicationoptionshere'), 'addcommunicationoptionshere');
}
}
39 changes: 39 additions & 0 deletions communication/provider/customlink/classes/privacy/provider.php
@@ -0,0 +1,39 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

namespace communication_customlink\privacy;

use core_privacy\local\metadata\null_provider;

/**
* Privacy Subsystem for communication_customlink implementing null_provider.
*
* @package communication_customlink
* @copyright 2023 Michael Hawkins <michaelh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements null_provider {

/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason(): string {
return 'privacy:metadata';
}
}
35 changes: 35 additions & 0 deletions communication/provider/customlink/db/caches.php
@@ -0,0 +1,35 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

/**
* Defined caches used internally by the provider.
*
* @package communication_customlink
* @copyright 2023 Michael Hawkins <michaelh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

declare(strict_types=1);

defined('MOODLE_INTERNAL') || die();

$definitions = [
'customlink' => [
'mode' => cache_store::MODE_APPLICATION,
'simplekeys' => true,
'simpledata' => true,
],
];
19 changes: 19 additions & 0 deletions communication/provider/customlink/db/install.xml
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="communication/provider/customlink/db" VERSION="20230826" COMMENT="Stores the link associated with a custom link communication instance."
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../../lib/xmldb/xmldb.xsd"
>
<TABLES>
<TABLE NAME="communication_customlink" COMMENT="Stores the link associated with a custom link communication instance.">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
<FIELD NAME="commid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="ID of the communication record"/>
<FIELD NAME="url" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="URL being linked to by the provider"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
<KEY NAME="fk_commid" TYPE="foreign" FIELDS="commid" REFTABLE="communication" REFFIELDS="id" COMMENT="Foreign key for communication reference"/>
</KEYS>
</TABLE>
</TABLES>
</XMLDB>
@@ -0,0 +1,30 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

/**
* Strings for component communication_customlink, language 'en'.
*
* @package communication_customlink
* @copyright 2023 Michael Hawkins <michaelh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

$string['cachedef_customlink'] = 'Custom link data';
$string['customlinkurl'] = 'Custom link URL';
$string['customlinkurl_help'] = 'Provide a link to an existing room from any communication service you would like to make available to participants - such as Microsoft Teams, Slack or Matrix.';
$string['customlinkurlinfo'] = 'The URL of an existing room already set up for this course.';
$string['pluginname'] = 'Custom link';
$string['privacy:metadata'] = 'Custom link communication plugin does not store any personal data.';
86 changes: 86 additions & 0 deletions communication/provider/customlink/tests/behat/custom_link.feature
@@ -0,0 +1,86 @@
@communication @communication_customlink @javascript
Feature: Communication custom link
In order to facilitate easy access to an existing communication platform
As a teacher
I need to be able to make a custom communication link available in my course

Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
And the following "courses" exist:
| fullname | shortname |
| Course 1 | C1 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And the following config values are set as admin:
| enablecommunicationsubsystem | 1 |

Scenario: As a teacher I can configure a custom communication provider for my course
Given I am on the "Course 1" "Course" page logged in as "teacher1"
And "Chat to course participants" "button" should not be visible
When I navigate to "Communication" in current page administration
And the "Communication service" select box should contain "Custom link"
And I should not see "Custom link URL"
And I select "Custom link" from the "Communication service" singleselect
And I should see "Custom link URL"
And I set the following fields to these values:
| communicationroomname | Test URL |
| customlinkurl | #wwwroot#/communication/provider/customlink/tests/behat/fixtures/custom_link_test_page.php |
And I press "Save changes"
Then "Chat to course participants" "button" should be visible
And I click on "Chat to course participants" "button"
# Check the link hits the expected destination.
And I switch to a second window
And I should see "Example messaging service - teacher1" in the "region-main" "region"
And I close all opened windows
# Ensure any communication subsystem tasks have no impact on availability.
And I run all adhoc tasks
And I am on the "Course 1" course page
And "Chat to course participants" "button" should be visible
And I click on "Chat to course participants" "button"
And I switch to a second window
And I should see "Example messaging service - teacher1" in the "region-main" "region"
And I close all opened windows
And I log out
# Confirm student also has access to the custom link.
And I am on the "Course 1" "Course" page logged in as "student1"
And "Chat to course participants" "button" should be visible
And I click on "Chat to course participants" "button"
And I switch to a second window
And I should see "Example messaging service - student1" in the "region-main" "region"

Scenario: As a teacher I can disable and re-enable a custom communication provider for my course
Given I am on the "Course 1" "Course" page logged in as "teacher1"
And "Chat to course participants" "button" should not be visible
When I navigate to "Communication" in current page administration
And I select "Custom link" from the "Communication service" singleselect
And I set the following fields to these values:
| communicationroomname | Test URL |
| customlinkurl | #wwwroot#/communication/provider/customlink/tests/behat/fixtures/custom_link_test_page.php |
And I press "Save changes"
And "Chat to course participants" "button" should be visible
And I run all adhoc tasks
And I navigate to "Communication" in current page administration
And I select "None" from the "Communication service" singleselect
And I press "Save changes"
And "Chat to course participants" "button" should not be visible
And I run all adhoc tasks
And I am on the "Course 1" course page
And "Chat to course participants" "button" should not be visible
And I navigate to "Communication" in current page administration
And I select "Custom link" from the "Communication service" singleselect
And I set the following fields to these values:
| communicationroomname | Test URL |
| customlinkurl | #wwwroot#/communication/provider/customlink/tests/behat/fixtures/custom_link_test_page.php |
And I press "Save changes"
And "Chat to course participants" "button" should be visible
And I run all adhoc tasks
And I am on the "Course 1" course page
And "Chat to course participants" "button" should be visible
And I click on "Chat to course participants" "button"
And I switch to a second window
And I should see "Example messaging service - teacher1" in the "region-main" "region"

0 comments on commit a3fa3e3

Please sign in to comment.