Skip to content

Commit

Permalink
MDL-78575 mod_lti: Add deletion support to course tools page
Browse files Browse the repository at this point in the history
  • Loading branch information
snake committed Jul 17, 2023
1 parent 5e077e1 commit 51cc455
Show file tree
Hide file tree
Showing 12 changed files with 301 additions and 7 deletions.
3 changes: 3 additions & 0 deletions mod/lti/amd/build/course_tools_list.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions mod/lti/amd/build/course_tools_list.min.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

82 changes: 82 additions & 0 deletions mod/lti/amd/src/course_tools_list.js
@@ -0,0 +1,82 @@
// 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/>.

/**
* Course LTI External tools list management.
*
* @module mod_lti/course_tools_list
* @copyright 2023 Jake Dallimore <jrhdallimore@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

"use strict";

import Notification from 'core/notification';
import Pending from 'core/pending';
import Ajax from 'core/ajax';
import {add as addToast} from 'core/toast';
import {prefetchStrings} from 'core/prefetch';
import {get_string as getString} from 'core/str';
import {refreshTableContent} from 'core_table/dynamic';
import * as Selectors from 'core_table/local/dynamic/selectors';

/**
* Initialise module.
*/
export const init = () => {
prefetchStrings('mod_lti', [
'deletecoursetool',
'deletecoursetoolconfirm',
'coursetooldeleted'
]);

prefetchStrings('core', [
'delete',
]);

document.addEventListener('click', event => {

const courseToolDelete = event.target.closest('[data-action="course-tool-delete"]');
if (courseToolDelete) {
event.preventDefault();

// Use triggerElement to return focus to the action menu toggle.
const triggerElement = courseToolDelete.closest('.dropdown').querySelector('.dropdown-toggle');
Notification.saveCancelPromise(
getString('deletecoursetool', 'mod_lti'),
getString('deletecoursetoolconfirm', 'mod_lti', courseToolDelete.dataset.courseToolName),
getString('delete', 'core'),
{triggerElement}
).then(() => {
const pendingPromise = new Pending('mod_lti/course_tools:delete');

const request = {
methodname: 'mod_lti_delete_course_tool_type',
args: {tooltypeid: courseToolDelete.dataset.courseToolId}
};
return Ajax.call([request])[0]
.then(addToast(getString('coursetooldeleted', 'mod_lti')))
.then(() => {
const tableRoot = triggerElement.closest(Selectors.main.region);
return refreshTableContent(tableRoot);
})
.then(pendingPromise.resolve)
.catch(Notification.exception);
}).catch(() => {
return;
});
}
});
};
81 changes: 81 additions & 0 deletions mod/lti/classes/external/delete_course_tool_type.php
@@ -0,0 +1,81 @@
<?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 mod_lti\external;

use core_external\external_api;
use core_external\external_function_parameters;
use core_external\external_value;

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

global $CFG;
require_once($CFG->dirroot . '/mod/lti/locallib.php');

/**
* External function to delete a course tool type.
*
* @package mod_lti
* @copyright 2023 Jake Dallimore <jrhdallimore@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class delete_course_tool_type extends external_api {

/**
* Get parameter definition.
*
* @return external_function_parameters
*/
public static function execute_parameters(): external_function_parameters {
return new external_function_parameters([
'tooltypeid' => new external_value(PARAM_INT, 'Tool type ID'),
]);
}

/**
* Delete a course tool type.
*
* @param int $tooltypeid the id of the course external tool type.
* @return bool true
* @throws \invalid_parameter_exception if the provided id refers to a site level tool which cannot be deleted.
*/
public static function execute(int $tooltypeid): bool {

['tooltypeid' => $tooltypeid] = self::validate_parameters(self::execute_parameters(), ['tooltypeid' => $tooltypeid]);

global $DB;
$course = (int) $DB->get_field('lti_types', 'course', ['id' => $tooltypeid]);
if ($course == get_site()->id) {
throw new \invalid_parameter_exception('This is a site-level tool and cannot be deleted via this service');
}

$context = \context_course::instance($course);
self::validate_context($context);
require_capability('mod/lti:addcoursetool', $context);

\lti_delete_type($tooltypeid);
return true;
}

/**
* Get service returns definition.
*
* @return external_value
*/
public static function execute_returns(): external_value {
return new external_value(PARAM_BOOL, 'Success');
}
}
4 changes: 2 additions & 2 deletions mod/lti/coursetools.php
Expand Up @@ -21,6 +21,7 @@
* @copyright 2023 Jake Dallimore <jrhdallimore@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

use mod_lti\output\course_tools_page;

require_once("../../config.php");
Expand All @@ -39,7 +40,7 @@
}

// Page setup.
global $PAGE;
global $PAGE, $OUTPUT;
$pagetitle = get_string('courseexternaltools', 'mod_lti');
$pageurl = new moodle_url('/mod/lti/coursetools.php', ['id' => $course->id]);
$PAGE->set_pagelayout('incourse');
Expand All @@ -59,4 +60,3 @@
$PAGE->requires->js_call_amd('mod_lti/course_tools_list', 'init');

echo $OUTPUT->footer();

8 changes: 8 additions & 0 deletions mod/lti/db/services.php
Expand Up @@ -146,6 +146,14 @@
'ajax' => true
),

'mod_lti_delete_course_tool_type' => array(
'classname' => 'mod_lti\external\delete_course_tool_type',
'description' => 'Delete a course tool type',
'type' => 'write',
'capabilities' => 'mod/lti:addcoursetool',
'ajax' => true
),

'mod_lti_is_cartridge' => array(
'classname' => 'mod_lti_external',
'methodname' => 'is_cartridge',
Expand Down
3 changes: 3 additions & 0 deletions mod/lti/lang/en/lti.php
Expand Up @@ -130,6 +130,7 @@
$string['courseinformation'] = 'Course information';
$string['courselink'] = 'Go to course';
$string['coursemisconf'] = 'Course is misconfigured';
$string['coursetooldeleted'] = 'Course tool deleted';
$string['createdon'] = 'Created on';
$string['curllibrarymissing'] = 'PHP cURL extension required for the External tool.';
$string['custom'] = 'Custom parameters';
Expand Down Expand Up @@ -158,6 +159,8 @@
$string['delegate_tool'] = 'As specified in Deep Linking definition or Delegate to teacher';
$string['delete'] = 'Delete';
$string['delete_confirmation'] = 'Are you sure you want to delete this preconfigured tool?';
$string['deletecoursetool'] = 'Delete a course tool';
$string['deletecoursetoolconfirm'] = 'Are you sure you want to delete this course tool?';
$string['deletetype'] = 'Delete preconfigured tool';
$string['display_description'] = 'Display activity description when launched';
$string['display_description_help'] = 'If selected, the activity description (specified above) will display above the tool provider\'s content.
Expand Down
20 changes: 20 additions & 0 deletions mod/lti/tests/behat/managecoursetools.feature
Expand Up @@ -96,3 +96,23 @@ Feature: Manage course tools
And I should see "Test tool 20" in the "reportbuilder-table" "table"
And I click on "2" "link" in the "page" "region"
And I should see "Test tool 1" in the "reportbuilder-table" "table"

@javascript
Scenario: Delete a course tool
Given the following "mod_lti > course tools" exist:
| name | description | baseurl | course |
| Test tool | Example description | https://example.com/tool | C1 |
| Another tool | Example 123 | https://another.example.com/tool | C1 |
And I am on the "Course 1" course page logged in as teacher1
And I navigate to "LTI External tools" in current page administration
When I open the action menu in "Test tool" "table_row"
And I choose "Delete" in the open action menu
Then I should see "Are you sure you want to delete this course tool?"
And I click on "Cancel" "button" in the "Delete a course tool" "dialogue"
And I should see "Test tool" in the "reportbuilder-table" "table"
And I open the action menu in "Test tool" "table_row"
And I choose "Delete" in the open action menu
And I should see "Are you sure you want to delete this course tool?"
And I click on "Delete" "button" in the "Delete a course tool" "dialogue"
And I should see "Course tool deleted"
And I should not see "Test tool" in the "reportbuilder-table" "table"
82 changes: 82 additions & 0 deletions mod/lti/tests/external/delete_course_tool_type_test.php
@@ -0,0 +1,82 @@
<?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 mod_lti\external;

use core_external\external_api;

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

global $CFG;

require_once($CFG->dirroot . '/mod/lti/tests/mod_lti_testcase.php');

/**
* PHPUnit tests for delete_course_tool_type external function.
*
* @package mod_lti
* @copyright 2023 Jake Dallimore <jrhdallimore@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @coversDefaultClass \mod_lti\external\delete_course_tool_type
*/
class delete_course_tool_type_test extends \mod_lti_testcase {

/**
* Test delete_course_tool() for a course tool.
* @covers ::execute
*/
public function test_delete_course_tool() {
$this->resetAfterTest();

$course = $this->getDataGenerator()->create_course();
$editingteacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
$this->setUser($editingteacher);

$typeid = lti_add_type(
(object) [
'state' => LTI_TOOL_STATE_CONFIGURED,
'course' => $course->id
],
(object) [
'lti_typename' => "My course tool",
'lti_toolurl' => 'http://example.com',
'lti_ltiversion' => 'LTI-1p0'
]
);

$data = delete_course_tool_type::execute($typeid);
$data = external_api::clean_returnvalue(delete_course_tool_type::execute_returns(), $data);

$this->assertTrue($data);
}

/**
* Test delete_course_tool() for a site tool, which is forbidden.
* @covers ::execute
*/
public function test_delete_course_tool_site_tool() {
$this->resetAfterTest();

$course = $this->getDataGenerator()->create_course();
$editingteacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
$this->setUser($editingteacher);

$type = $this->generate_tool_type(123); // Creates a site tool.

$this->expectException(\invalid_parameter_exception::class);
delete_course_tool_type::execute($type->id);
}
}

0 comments on commit 51cc455

Please sign in to comment.