first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
+11
View File
@@ -0,0 +1,11 @@
define("qbank_comment/comment",["exports","core/fragment","core/str","core/modal_events","core/modal_save_cancel"],(function(_exports,_fragment,_str,_modal_events,_modal_save_cancel){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
/**
* Column selector js.
*
* @module qbank_comment/comment
* @copyright 2021 Catalyst IT Australia Pty Ltd
* @author Safat Shahin <safatshahin@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_fragment=_interopRequireDefault(_fragment),_modal_events=_interopRequireDefault(_modal_events),_modal_save_cancel=_interopRequireDefault(_modal_save_cancel);_exports.init=()=>{const target=document.querySelector("#categoryquestions");null!==target&&target.addEventListener("click",(e=>{e.target.dataset.target&&e.target.dataset.target.includes("questioncommentpreview")&&(async(questionId,courseID,contextId)=>{const args={questionid:questionId,courseid:courseID},modal=await _modal_save_cancel.default.create({title:(0,_str.get_string)("commentheader","qbank_comment"),body:_fragment.default.loadFragment("qbank_comment","question_comment",contextId,args),large:!0,show:!0,buttons:{save:(0,_str.get_string)("addcomment","qbank_comment"),cancel:(0,_str.get_string)("close","qbank_comment")},removeOnClose:!0}),root=modal.getRoot();root.on(_modal_events.default.bodyRendered,(function(){document.querySelectorAll("div.comment-area a")[0].style.display="none"})),root.on("change","#question_comment_version_dropdown",(e=>{args.questionid=e.target.value,modal.setBody(_fragment.default.loadFragment("qbank_comment","question_comment",contextId,args))})),root.on(_modal_events.default.hidden,(()=>location.reload())),root.on(_modal_events.default.save,(function(e){e.preventDefault();const submitlink=document.querySelectorAll("div.comment-area a")[0],textarea=document.querySelectorAll("div.comment-area textarea")[0];textarea.value!=textarea.getAttribute("aria-label")&&""!=textarea.value&&submitlink.click()}))})(e.target.dataset.questionid,e.target.dataset.courseid,e.target.dataset.contextid)}))}}));
//# sourceMappingURL=comment.min.js.map
File diff suppressed because one or more lines are too long
+100
View File
@@ -0,0 +1,100 @@
// 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/>.
/**
* Column selector js.
*
* @module qbank_comment/comment
* @copyright 2021 Catalyst IT Australia Pty Ltd
* @author Safat Shahin <safatshahin@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import Fragment from 'core/fragment';
import {get_string as getString} from 'core/str';
import ModalEvents from 'core/modal_events';
import SaveCancelModal from 'core/modal_save_cancel';
/**
* Event listeners for the module.
*
* @method clickEvent
* @param {Number} questionId
* @param {Number} courseID
* @param {Number} contextId
*/
const commentEvent = async(questionId, courseID, contextId) => {
const args = {
questionid: questionId,
courseid: courseID
};
const modal = await SaveCancelModal.create({
title: getString('commentheader', 'qbank_comment'),
body: Fragment.loadFragment('qbank_comment', 'question_comment', contextId, args),
large: true,
show: true,
buttons: {
save: getString('addcomment', 'qbank_comment'),
cancel: getString('close', 'qbank_comment'),
},
removeOnClose: true,
});
const root = modal.getRoot();
// Don't display the default add comment link in the modal.
root.on(ModalEvents.bodyRendered, function() {
const submitlink = document.querySelectorAll("div.comment-area a")[0];
submitlink.style.display = 'none';
});
// Version selection event.
root.on('change', '#question_comment_version_dropdown', (e) =>{
args.questionid = e.target.value;
modal.setBody(Fragment.loadFragment('qbank_comment', 'question_comment', contextId, args));
});
// Reload the page when the modal is closed.
root.on(ModalEvents.hidden, () => location.reload());
// Handle adding the comment when the button in the modal is clicked.
root.on(ModalEvents.save, function(e) {
e.preventDefault();
const submitlink = document.querySelectorAll("div.comment-area a")[0];
const textarea = document.querySelectorAll("div.comment-area textarea")[0];
// Check there is a valid comment to add, and trigger adding if there is.
if (textarea.value != textarea.getAttribute('aria-label') && textarea.value != '') {
submitlink.click();
}
});
};
/**
* Entrypoint of the js.
*
* @method init
*/
export const init = () => {
const target = document.querySelector('#categoryquestions');
if (target !== null) {
target.addEventListener('click', (e) => {
if (e.target.dataset.target && e.target.dataset.target.includes('questioncommentpreview')) {
// Call for the event listener to listed for clicks in any comment count row.
commentEvent(e.target.dataset.questionid, e.target.dataset.courseid, e.target.dataset.contextid);
}
});
}
};
@@ -0,0 +1,66 @@
<?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/>.
/**
* Provides the information to backup question comments.
*
* @package qbank_comment
* @copyright 2021 Catalyst IT Australia Pty Ltd
* @author Matt Porritt <mattp@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class backup_qbank_comment_plugin extends \backup_qbank_plugin {
/**
* Returns the comment information to attach to question element.
*/
protected function define_question_plugin_structure() {
// Define the virtual plugin element with the condition to fulfill.
$plugin = $this->get_plugin_element();
// Create one standard named plugin element (the visible container).
$pluginwrapper = new backup_nested_element($this->get_recommended_name());
// Connect the visible container ASAP.
$plugin->add_child($pluginwrapper);
$comments = new backup_nested_element('comments');
$comment = new backup_nested_element('comment', ['id'], ['component', 'commentarea', 'itemid', 'contextid',
'content', 'format', 'userid', 'timecreated']);
$pluginwrapper->add_child($comments);
$comments->add_child($comment);
$comment->set_source_sql(
"SELECT c.*
FROM {comments} c
WHERE c.contextid = :contextid
AND c.component = 'qbank_comment'
AND c.commentarea = 'question'
AND c.itemid = :itemid",
[
'contextid' => backup_helper::is_sqlparam(context_system::instance()->id),
'itemid' => backup::VAR_PARENTID,
]
);
$comment->annotate_ids('user', 'userid');
return $plugin;
}
}
@@ -0,0 +1,58 @@
<?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/>.
/**
* Restore plugin class that provides the necessary information needed to restore comments for questions.
*
* @package qbank_comment
* @copyright 2021 Catalyst IT Australia Pty Ltd
* @author Matt Porritt <mattp@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class restore_qbank_comment_plugin extends restore_qbank_plugin {
/**
* Returns the paths to be handled by the plugin at question level.
*/
protected function define_question_plugin_structure() {
return [
new restore_path_element('comment', $this->get_pathfor('/comments/comment'))
];
}
/**
* Process the question comments element.
*
* @param array $data The comment data to restore.
*/
public function process_comment($data) {
global $DB, $CFG;
$data = (object)$data;
$newquestionid = $this->get_new_parentid('question');
$questioncreated = (bool) $this->get_mappingid('question_created', $this->get_old_parentid('question'));
if (!$questioncreated) {
// This question already exists in the question bank. Nothing for us to do.
return;
}
if ($CFG->usecomments) {
$data->itemid = $newquestionid;
$DB->insert_record('comments', $data);
}
}
}
@@ -0,0 +1,116 @@
<?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 qbank_comment;
use core_question\local\bank\column_base;
use question_bank;
/**
* A column to show the number of comments.
*
* @package qbank_comment
* @copyright 2021 Catalyst IT Australia Pty Ltd
* @author Safat Shahin <safatshahin@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class comment_count_column extends column_base {
/**
* @var bool Comments enabled or not from config.
*/
protected $commentsenabled = true;
/**
* Load javascript module if enabled.
*
* @return void
*/
public function init(): void {
parent::init();
$this->check_comments_status();
if ($this->commentsenabled) {
global $PAGE;
$PAGE->requires->js_call_amd('qbank_comment/comment', 'init');
}
}
/**
* Check if comments is turned on in the system or not.
*/
protected function check_comments_status(): void {
global $CFG;
if (!$CFG->usecomments) {
$this->commentsenabled = false;
}
}
/**
* Get the name of the column, used internally.
*
* @return string
*/
public function get_name(): string {
return 'commentcount';
}
/**
* Get the title of the column that will be displayed.
*
* @return string
*/
public function get_title(): string {
return get_string('commentplural', 'qbank_comment');
}
/**
* Generate the content to be displayed.
*
* @param object $question The question object.
* @param string $rowclasses Classes that can be added.
*/
protected function display_content($question, $rowclasses): void {
global $DB;
$syscontext = \context_system::instance();
$args = [
'component' => 'qbank_comment',
'commentarea' => 'question',
'itemid' => $question->id,
'contextid' => $syscontext->id,
];
$commentcount = $DB->count_records('comments', $args);
$attributes = [];
if (question_has_capability_on($question, 'comment')) {
$target = 'questioncommentpreview_' . $question->id;
$attributes = [
'href' => '#',
'data-target' => $target,
'data-questionid' => $question->id,
'data-courseid' => $this->qbank->course->id,
'data-contextid' => $syscontext->id,
];
}
echo \html_writer::tag('a', $commentcount, $attributes);
}
public function get_extra_classes(): array {
return ['pr-3'];
}
public function get_default_width(): int {
return 150;
}
}
@@ -0,0 +1,51 @@
<?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 qbank_comment\event;
/**
* qbank_comment comment created event.
*
* @package qbank_comment
* @copyright 2021 Catalyst IT Australia Pty Ltd
* @author Safat Shahin <safatshahin@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class comment_created extends \core\event\comment_created {
/**
* Get URL related to the action, null in this case.
*
* @return null
*/
public function get_url() {
return null;
}
/**
* Returns description of what happened.
*
* @return string
*/
public function get_description() {
$a = new \stdClass();
$a->userid = $this->userid;
$a->objectid = $this->objectid;
$a->component = $this->component;
$a->itemid = $this->other['itemid'];
return get_string('comment_added', 'qbank_comment', $a);
}
}
@@ -0,0 +1,51 @@
<?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 qbank_comment\event;
/**
* qbank_comment comment deleted event.
*
* @package qbank_comment
* @copyright 2021 Catalyst IT Australia Pty Ltd
* @author Safat Shahin <safatshahin@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class comment_deleted extends \core\event\comment_deleted {
/**
* Get URL related to the action, null in this case.
*
* @return null
*/
public function get_url() {
return null;
}
/**
* Returns description of what happened.
*
* @return string
*/
public function get_description() {
$a = new \stdClass();
$a->userid = $this->userid;
$a->objectid = $this->objectid;
$a->component = $this->component;
$a->itemid = $this->other['itemid'];
return get_string('comment_removed', 'qbank_comment', $a);
}
}
@@ -0,0 +1,49 @@
<?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 qbank_comment\event;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/comment/lib.php');
use core\event\question_deleted;
/**
* Event observer for question deletion
*
* @package qbank_comment
* @copyright 2023 onwards Catalyst IT EU {@link https://catalyst-eu.net}
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class question_deleted_observer {
/**
* Delete any comments for the deleted question.
*
* @param question_deleted $event
* @return void
*/
public static function delete_question_comments(question_deleted $event): void {
\comment::delete_comments([
'contextid' => \context_system::instance()->id,
'component' => 'qbank_comment',
'commentarea' => 'question',
'itemid' => $event->objectid,
]);
}
}
@@ -0,0 +1,38 @@
<?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 qbank_comment\output;
/**
* Class renderer for comment.
*
* @package qbank_comment
* @copyright 2021 Catalyst IT Australia Pty Ltd
* @author Safat Shahin <safatshahin@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class renderer extends \plugin_renderer_base {
/**
* Render the html fragment for comment modal.
*
* @param array $displaydata
* @return string
*/
public function render_comment_fragment($displaydata): string {
return $this->render_from_template('qbank_comment/comment_modal', $displaydata);
}
}
@@ -0,0 +1,40 @@
<?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 qbank_comment;
/**
* Class plugin_features is the entrypoint for the columns.
*
* @package qbank_comment
* @copyright 2021 Catalyst IT Australia Pty Ltd
* @author Safat Shahin <safatshahin@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class plugin_feature extends \core_question\local\bank\plugin_features_base {
/**
* Get the columns provided by this plugin.
*
* @param \core_question\local\bank\view $qbank
* @return comment_count_column[]
*/
public function get_question_columns(\core_question\local\bank\view $qbank): array {
return [
new comment_count_column($qbank)
];
}
}
@@ -0,0 +1,140 @@
<?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 qbank_comment\privacy;
use core_privacy\local\metadata\collection;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\contextlist;
use core_privacy\local\request\userlist;
use core_privacy\local\request\approved_userlist;
/**
* Privacy Subsystem for qbank_comment.
*
* @package qbank_comment
* @copyright 2021 Catalyst IT Australia Pty Ltd
* @author Safat Shahin <safatshahin@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements
// The qbank_comment stores user provided data.
\core_privacy\local\metadata\provider,
\core_privacy\local\request\core_userlist_provider,
// The qbank_comment provides data directly to core.
\core_privacy\local\request\plugin\provider {
/**
* Returns meta data about this system.
*
* @param collection $collection
* @return collection
*/
public static function get_metadata(collection $collection): collection {
return $collection->add_subsystem_link('core_comment', [], 'privacy:metadata:core_comment');
}
/**
* Get the list of contexts that contain user information for the specified user.
*
* @param int $userid
* @return contextlist
*/
public static function get_contexts_for_userid(int $userid): contextlist {
$contextlist = new contextlist();
$sql = "SELECT contextid
FROM {comments}
WHERE component = :component
AND userid = :userid";
$params = [
'area' => 'question',
'component' => 'qbank_comment',
'userid' => $userid
];
$contextlist->add_from_sql($sql, $params);
return $contextlist;
}
/**
* Get the list of users within a specific context.
*
* @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
*/
public static function get_users_in_context(userlist $userlist) {
$context = $userlist->get_context();
$params = [
'contextid' => $context->id,
'area' => 'question',
'component' => 'qbank_comment'
];
$sql = "SELECT userid as userid
FROM {comments}
WHERE component = :component
AND contextid = :contextid";
$userlist->add_from_sql('userid', $sql, $params);
}
/**
* Export all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist
*/
public static function export_user_data(approved_contextlist $contextlist) {
$contexts = $contextlist->get_contexts();
foreach ($contexts as $context) {
\core_comment\privacy\provider::export_comments(
$context,
'qbank_comment',
'question',
0,
[]
);
}
}
/**
* Delete all data for all users in the specified context.
*
* @param \context $context
*/
public static function delete_data_for_all_users_in_context(\context $context) {
\core_comment\privacy\provider::delete_comments_for_all_users($context, 'qbank_comment');
}
/**
* Delete multiple users within a single context.
*
* @param approved_userlist $userlist The approved context and user information to delete information for.
*/
public static function delete_data_for_users(approved_userlist $userlist) {
\core_comment\privacy\provider::delete_comments_for_users($userlist, 'qbank_comment');
}
/**
* Delete all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist
*/
public static function delete_data_for_user(approved_contextlist $contextlist) {
\core_comment\privacy\provider::delete_comments_for_user($contextlist, 'qbank_comment');
}
}
+50
View File
@@ -0,0 +1,50 @@
<?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/>.
/**
* Capability definitions for this module.
*
* @package qbank_comment
* @copyright 2021 Catalyst IT Australia Pty Ltd
* @author Matt Porritt <mattp@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$capabilities = [
// Controls whether users can comment their own questions.
'moodle/question:commentmine' => [
'captype' => 'write',
'contextlevel' => CONTEXT_COURSE,
'archetypes' => [
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
],
'clonepermissionsfrom' => 'moodle/question:editmine'
],
// Controls whether users can comment all questions.
'moodle/question:commentall' => [
'captype' => 'write',
'contextlevel' => CONTEXT_COURSE,
'archetypes' => [
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
],
'clonepermissionsfrom' => 'moodle/question:editall'
],
];
+33
View File
@@ -0,0 +1,33 @@
<?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/>.
/**
* Question custom fields events
*
* @package qbank_comment
* @copyright 2023 onwards Catalyst IT EU {@link https://catalyst-eu.net}
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$observers = [
[
'eventname' => '\core\event\question_deleted',
'callback' => '\qbank_comment\event\question_deleted_observer::delete_question_comments',
]
];
@@ -0,0 +1,40 @@
<?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 qbank_comment, language 'en'.
*
* @package qbank_comment
* @copyright 2021 Catalyst IT Australia Pty Ltd
* @author Safat Shahin <safatshahin@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['pluginname'] = 'Question comments';
$string['privacy:metadata:core_comment'] = 'The Question comments question bank plugin enables users to comment on questions.';
// Column.
$string['comment'] = 'Comment';
$string['commentplural'] = 'Comments';
// Modal.
$string['addcomment'] = 'Add comment';
$string['close'] = 'Close';
$string['commentheader'] = 'Question comments';
$string['commentdisabled'] = 'Comments are currently disabled on this site. Please contact your site administrator.';
// Events.
$string['comment_added'] = 'The user with ID \'{$a->userid}\' added the comment with ID \'{$a->objectid}\'
to the \'{$a->component}\' for the question with ID \'{$a->itemid}\'.';
$string['comment_removed'] = 'The user with ID \'{$a->userid}\' deleted the comment with ID \'{$a->objectid}\'
from the \'{$a->component}\' for the question with ID \'{$a->itemid}\'.';
+142
View File
@@ -0,0 +1,142 @@
<?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/>.
/**
* Helper functions and callbacks.
*
* @package qbank_comment
* @copyright 2021 Catalyst IT Australia Pty Ltd
* @author Safat Shahin <safatshahin@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot. '/comment/lib.php');
/**
* Validate comment parameter before perform other comments actions.
*
* @param stdClass $commentparam
* {
* context => context the context object
* courseid => int course id
* cm => stdClass course module object
* commentarea => string comment area
* itemid => int itemid
* }
* @return boolean
*/
function qbank_comment_comment_validate($commentparam): bool {
if ($commentparam->commentarea != 'question' && $commentparam->component != 'qbank_comment') {
throw new comment_exception('invalidcommentarea');
}
return true;
}
/**
* Running additional permission check on plugins.
*
* @param stdClass $args
* @return array
*/
function qbank_comment_comment_permissions($args): array {
return ['post' => true, 'view' => true];
}
/**
* Validate comment data before displaying comments.
*
* @param array $comments
* @param stdClass $args
* @return array $comments
*/
function qbank_comment_comment_display($comments, $args): array {
if ($args->commentarea != 'question' && $args->component != 'qbank_comment') {
throw new comment_exception('core_question');
}
return $comments;
}
/**
* Comment content for callbacks.
*
* @param question_definition $question
* @param int $courseid
* @return string
*/
function qbank_comment_preview_display($question, $courseid): string {
global $CFG, $PAGE;
if (question_has_capability_on($question, 'comment') && $CFG->usecomments
&& core\plugininfo\qbank::is_plugin_enabled('qbank_comment')) {
\comment::init($PAGE);
$args = new \stdClass;
$args->contextid = context_system::instance()->id; // Static data to bypass comment sql as context is not needed.
$args->courseid = $courseid;
$args->area = 'question';
$args->itemid = $question->id;
$args->component = 'qbank_comment';
$args->notoggle = true;
$args->autostart = true;
$args->displaycancel = false;
$args->linktext = get_string('commentheader', 'qbank_comment');
$comment = new \comment($args);
$comment->set_view_permission(true);
$comment->set_fullwidth();
return $comment->output();
} else {
return '';
}
}
/**
* Question comment fragment callback.
*
* @param array $args
* @return string rendered output
*/
function qbank_comment_output_fragment_question_comment($args): string {
global $USER, $PAGE, $CFG, $DB;
$displaydata = [];
require_once($CFG->dirroot . '/question/engine/bank.php');
$question = question_bank::load_question($args['questionid']);
$quba = question_engine::make_questions_usage_by_activity(
'core_question_preview', context_user::instance($USER->id));
// Just in case of any regression, it should not break the modal, just show the comments.
if (class_exists('\\qbank_previewquestion\\question_preview_options')) {
$options = new \qbank_previewquestion\question_preview_options($question);
$quba->set_preferred_behaviour($options->behaviour);
$slot = $quba->add_question($question, $options->maxmark);
$quba->start_question($slot, $options->variant);
$transaction = $DB->start_delegated_transaction();
question_engine::save_questions_usage_by_activity($quba);
$transaction->allow_commit();
$displaydata['question'] = $quba->render_question($slot, $options, '1');
}
$displaydata['comment'] = qbank_comment_preview_display($question, $args['courseid']);
$displaydata['commenstdisabled'] = false;
if (empty($displaydata['comment']) && !$CFG->usecomments) {
$displaydata['commenstdisabled'] = true;
}
$selector = \core_question\output\question_version_selection::make_for_question('question_comment_version_dropdown',
$args['questionid']);
$qbankrenderer = $PAGE->get_renderer('core_question', 'bank');
$displaydata['versionselection'] = $selector->export_for_template($qbankrenderer);
return $PAGE->get_renderer('qbank_comment')->render_comment_fragment($displaydata);
}
+5
View File
@@ -0,0 +1,5 @@
/* Comment text area size to maximum */
.question-comment-view .comment-ctrl .comment-area {
max-width: none;
width: 100%;
}
@@ -0,0 +1,49 @@
{{!
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/>.
}}
{{!
@template qbank_comment/comment_modal
The template that renders the modal window for adding comments to questions.
* question - The html of the question.
* comment - The html of the comment.
* commenstdisabled - If true display the comment disabled notification.
Example context (json):
{
"commentdata": [
{
"question": "question html",
"comment": "comment html",
"commenstdisabled": "bool"
}
]
}
}}
{{#versionselection}}
{{> core_question/question_version_selection }}
{{/versionselection}}
<div class="question-comment-preview">
{{{question}}}
</div>
<div class="question-comment-view">
{{{comment}}}
{{#commenstdisabled}}
<a class="alert-danger">
{{#str}} commentdisabled, qbank_comment {{/str}}
</a>
{{/commenstdisabled}}
</div>
+216
View File
@@ -0,0 +1,216 @@
<?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 qbank_comment;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php');
require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php');
require_once($CFG->dirroot. '/comment/lib.php');
/**
* Question comment backup and restore unit tests.
*
* @package qbank_comment
* @copyright 2021 Catalyst IT Australia Pty Ltd
* @author Matt Porritt <mattp@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class backup_test extends \advanced_testcase {
/**
* @var array Data object for generating a question.
*/
protected $question1data;
/**
* @var array Data object for generating a question.
*/
protected $question2data;
/**
* @var component_generator_base Question Generator.
*/
protected $qgen;
/**
* @var core_course_category Course category.
*/
protected $category;
/**
* @var stdClass Course object.
*/
protected $course;
/**
* Set up
*/
protected function setUp(): void {
parent::setUp();
$this->resetAfterTest();
$this->setAdminUser();
// Set up custom fields.
$data = new \stdClass();
$data->component = 'qbank_comment';
$data->area = 'question';
// Question initial set up.
$this->category = $this->getDataGenerator()->create_category();
$this->course = $this->getDataGenerator()->create_course(['category' => $this->category->id]);
$context = \context_coursecat::instance($this->category->id);
$this->qgen = $this->getDataGenerator()->get_plugin_generator('core_question');
$qcat = $this->qgen->create_question_category(['contextid' => $context->id]);
$this->question1data = ['category' => $qcat->id, 'idnumber' => 'q1'];
$this->question2data = ['category' => $qcat->id, 'idnumber' => 'q2'];
}
/**
* Makes a backup of the course.
*
* @param \stdClass $course The course object.
* @return string Unique identifier for this backup.
*/
protected function backup_course(\stdClass $course): string {
global $CFG, $USER;
// Turn off file logging, otherwise it can't delete the file (Windows).
$CFG->backup_file_logger_level = \backup::LOG_NONE;
// Do backup with default settings. MODE_IMPORT means it will just
// create the directory and not zip it.
$bc = new \backup_controller(\backup::TYPE_1COURSE, $course->id,
\backup::FORMAT_MOODLE, \backup::INTERACTIVE_NO, \backup::MODE_IMPORT,
$USER->id);
$backupid = $bc->get_backupid();
$bc->execute_plan();
$bc->destroy();
return $backupid;
}
/**
* Restores a backup that has been made earlier.
*
* @param string $backupid The unique identifier of the backup.
* @param string $fullname Full name of the new course that is going to be created.
* @param string $shortname Short name of the new course that is going to be created.
* @param int $categoryid The course category the backup is going to be restored in.
* @return int The new course id.
*/
protected function restore_course(string $backupid, string $fullname, string $shortname, int $categoryid): int {
global $CFG, $USER;
// Turn off file logging, otherwise it can't delete the file (Windows).
$CFG->backup_file_logger_level = \backup::LOG_NONE;
// Do restore to new course with default settings.
$newcourseid = \restore_dbops::create_new_course($fullname, $shortname, $categoryid);
$rc = new \restore_controller($backupid, $newcourseid,
\backup::INTERACTIVE_NO, \backup::MODE_GENERAL, $USER->id,
\backup::TARGET_NEW_COURSE);
$rc->execute_precheck();
$rc->execute_plan();
$rc->destroy();
return $newcourseid;
}
/**
* Test comments attached to questions persist
* across the backup and restore process.
*/
public function test_backup_restore(): void {
global $DB, $CFG;
require_once($CFG->dirroot . '/comment/lib.php');
$this->resetAfterTest();
$this->setAdminUser();
$courseshortname = $this->course->shortname;
$coursefullname = $this->course->fullname;
// Create 2 questions.
$question1 = $this->qgen->create_question('shortanswer', null, $this->question1data);
$question2 = $this->qgen->create_question('shortanswer', null, $this->question2data);
// Add comments to the questions.
$args = new \stdClass;
$args->context = \context_system::instance();
$args->course = $this->course;
$args->area = 'question';
$args->itemid = $question1->id;
$args->component = 'qbank_comment';
$args->linktext = get_string('commentheader', 'qbank_comment');
$args->notoggle = true;
$args->autostart = true;
$args->displaycancel = false;
// Two comments for question 1.
$commentobj1 = new \comment($args);
$commentobj1->add('new \comment for question 1 _ 1');
$comment1 = $commentobj1->add('new \comment for question 1 _ 2');
// One comment for question 2.
$args->itemid = $question2->id;
$commentobj2 = new \comment($args);
$comment2 = $commentobj2->add('new \comment for question 2');
// Create a quiz and the questions to that.
$quiz = $this->getDataGenerator()->create_module(
'quiz', ['course' => $this->course->id, 'name' => 'restored_quiz']);
quiz_add_quiz_question($question1->id, $quiz);
quiz_add_quiz_question($question2->id, $quiz);
// Backup the course.
$backupid = $this->backup_course($this->course);
// Now delete everything.
delete_course($this->course, false);
question_delete_question($question1->id);
question_delete_question($question2->id);
// Check the comment data for the questions has also gone.
$DB->record_exists('comments', ['id' => $comment1->id]);
$this->assertFalse($DB->record_exists('comments', ['id' => $comment1->id]));
$this->assertFalse($DB->record_exists('comments', ['id' => $comment2->id]));
// Restore the backup we had made earlier into a new course.
$newcategory = $this->getDataGenerator()->create_category();
$this->restore_course($backupid, $coursefullname, $courseshortname . '_2', $newcategory->id);
// The questions and their associated comments should have been restored.
$sql =
'SELECT q.*
FROM {question} q
JOIN {question_versions} qv ON qv.questionid = q.id
JOIN {question_bank_entries} qbe ON qbe.id = qv.questionbankentryid
WHERE qbe.idnumber = ?';
$newquestion1 = $DB->get_record_sql($sql, ['idnumber' => 'q1']);
$args->itemid = $newquestion1->id;
$commentobj = new \comment($args);
$this->assertEquals($commentobj->count(), 2);
$newquestion2 = $DB->get_record_sql($sql, ['idnumber' => 'q2']);
$args->itemid = $newquestion2->id;
$commentobj = new \comment($args);
$this->assertEquals($commentobj->count(), 1);
}
}
@@ -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/>.
/**
* Commenting system steps definitions for question.
*
* @package qbank_comment
* @copyright 2021 Catalyst IT Australia Pty Ltd
* @author Safat Shahin <safatshahin@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
require_once(__DIR__ . '/../../../../../lib/behat/behat_base.php');
require_once(__DIR__ . '/../../../../tests/behat/behat_question_base.php');
use Behat\Mink\Exception\ExpectationException as ExpectationException,
Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException;
/**
* Steps definitions to deal with the commenting system in question.
*
* @package qbank_comment
* @copyright 2021 Catalyst IT Australia Pty Ltd
* @author Safat Shahin <safatshahin@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_qbank_comment extends behat_question_base {
/**
* Looks for a table, then looks for a row that contains the given text.
* Once it finds the right row, it clicks a link in that row.
*
* @When I click :arg1 on the row on the comments column
* @param string $linkname
* @param string $rowtext
*/
public function i_click_on_the_row_containing($linkname) {
$exception = new ElementNotFoundException($this->getSession(),
'Cannot find any row on the page containing the text ' . $linkname);
$row = $this->find('css', sprintf('table tbody tr td.commentcount a:contains("%s")', $linkname), $exception);
$row->click();
}
/**
* Looks for the appropriate comment count in the column.
*
* @Then I should see :arg1 on the comments column
* @param string $linkdata
*/
public function i_should_see_on_the_column($linkdata) {
$exception = new ElementNotFoundException($this->getSession(),
'Cannot find any row with the comment count of ' . $linkdata . ' on the column named Comments');
$this->find('css', sprintf('table tbody tr td.commentcount a:contains("%s")', $linkdata), $exception);
}
/**
* Adds the specified option to the question comments of the current modal.
*
* @Then I add :arg1 comment to question
* @param string $comment
*/
public function i_add_comment_to_question($comment) {
// Getting the textarea and setting the provided value.
$exception = new ElementNotFoundException($this->getSession(), 'Question ');
if ($this->running_javascript()) {
$commentstextarea = $this->find('css',
'.modal-dialog .question-comment-view .comment-area textarea', $exception);
$commentstextarea->setValue($comment);
// We delay 1 second which is all we need.
$this->getSession()->wait(1000);
} else {
throw new ExpectationException('JavaScript not running', $this->getSession());
}
}
/**
* Adds the specified option to the question comments of the question preview.
*
* @Then I add :arg1 comment to question preview
* @param string $comment
*/
public function i_add_comment_to_question_preview($comment) {
// Getting the textarea and setting the provided value.
$exception = new ElementNotFoundException($this->getSession(), 'Question ');
if ($this->running_javascript()) {
$commentstextarea = $this->find('css',
'.comment-area textarea', $exception);
$commentstextarea->setValue($comment);
// We delay 1 second which is all we need.
$this->getSession()->wait(1000);
} else {
throw new ExpectationException('JavaScript not running', $this->getSession());
}
}
/**
* Deletes the specified comment from the current question comment preview.
*
* @Then I delete :arg comment from question preview
* @param string $comment
*/
public function i_delete_comment_from_question_preview($comment) {
$exception = new ElementNotFoundException($this->getSession(), '"' . $comment . '" comment ');
// Using xpath liternal to avoid possible problems with comments containing quotes.
$commentliteral = behat_context_helper::escape($comment);
$commentxpath = "//*[contains(concat(' ', normalize-space(@class), ' '), ' comment-ctrl ')]" .
"/descendant::div[@class='comment-message'][contains(., $commentliteral)]";
// Click on delete icon.
$this->execute('behat_general::i_click_on_in_the',
["Delete comment posted by", "icon", $this->escape($commentxpath), "xpath_element"]
);
// Wait for the animation to finish, in theory is just 1 sec, adding 4 just in case.
$this->getSession()->wait(4 * 1000);
}
/**
* Deletes the specified comment from the current question comment modal.
*
* @Then I delete :arg comment from question
* @param string $comment
*/
public function i_delete_comment_from_question($comment) {
$exception = new ElementNotFoundException($this->getSession(), '"' . $comment . '" comment ');
// Using xpath liternal to avoid possible problems with comments containing quotes.
$commentliteral = behat_context_helper::escape($comment);
$commentxpath = "//*[contains(concat(' ', normalize-space(@class), ' '), ' question-comment-view ')]" .
"/descendant::div[@class='comment-message'][contains(., $commentliteral)]";
// Click on delete icon.
$this->execute('behat_general::i_click_on_in_the',
["Delete comment posted by", "icon", $this->escape($commentxpath), "xpath_element"]
);
// Wait for the animation to finish, in theory is just 1 sec, adding 4 just in case.
$this->getSession()->wait(4 * 1000);
}
}
@@ -0,0 +1,151 @@
@qbank @qbank_comment @javascript
Feature: A Teacher can comment in a question
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | T1 | Teacher1 | teacher1@example.com |
| teacher2 | T2 | Teacher2 | teacher2@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| teacher2 | C1 | editingteacher |
And the following "activities" exist:
| activity | name | course | idnumber |
| quiz | Test quiz | C1 | quiz1 |
And the following "question categories" exist:
| contextlevel | reference | name |
| Course | C1 | Test questions |
And the following "questions" exist:
| questioncategory | qtype | name | questiontext |
| Test questions | truefalse | First question | Answer the first question |
@javascript
Scenario: Add a comment in question
Given I am on the "Test quiz" "mod_quiz > question bank" page logged in as "teacher1"
And I apply question bank filter "Category" with value "Test questions"
And I should see "0" on the comments column
When I click "0" on the row on the comments column
And I add "Super test comment 01" comment to question
And I click on "Add comment" "button" in the ".modal-dialog" "css_element"
And I should see "Super test comment 01"
And I click on "Close" "button" in the ".modal-dialog" "css_element"
Then I should see "1" on the comments column
@javascript
Scenario: Delete a comment from question
Given I am on the "Test quiz" "mod_quiz > question bank" page logged in as "teacher1"
And I apply question bank filter "Category" with value "Test questions"
And I should see "0" on the comments column
When I click "0" on the row on the comments column
And I add "Super test comment 01 to be deleted" comment to question
And I click on "Add comment" "button" in the ".modal-dialog" "css_element"
And I should see "Super test comment 01 to be deleted"
And I click on "Close" "button" in the ".modal-dialog" "css_element"
Then I should see "1" on the comments column
And I click "1" on the row on the comments column
And I delete "Super test comment 01 to be deleted" comment from question
And I should not see "Super test comment 01 to be deleted"
And I click on "Close" "button" in the ".modal-dialog" "css_element"
But I should see "0" on the comments column
@javascript
Scenario: Preview question with comments
Given I am on the "Test quiz" "mod_quiz > question bank" page logged in as "teacher1"
And I apply question bank filter "Category" with value "Test questions"
And I choose "Preview" action for "First question" in the question bank
And I click on "Comments" "link"
Then I should see "Save comment"
And I add "Super test comment 01" comment to question preview
And I click on "Save comment" "link"
And I wait "1" seconds
Then I should see "Super test comment 01"
And I click on "Close preview" "button"
Then I should see "1" on the comments column
And I choose "Preview" action for "First question" in the question bank
And I click on "Comments" "link"
And I delete "Super test comment 01" comment from question preview
And I should not see "Super test comment 01"
And I click on "Close preview" "button"
Then I should see "0" on the comments column
@javascript
Scenario: Teacher with comment permissions for their own questions but not others questions
Given the following "role capability" exists:
| role | editingteacher |
| moodle/question:commentmine | allow |
| moodle/question:commentall | prevent |
And I am on the "Test quiz" "mod_quiz > question bank" page logged in as "teacher1"
And I apply question bank filter "Category" with value "Test questions"
And I choose "Preview" action for "First question" in the question bank
Then I should not see "Save comment"
And I click on "Close preview" "button"
Then I click on "Create a new question ..." "button"
And I set the field "item_qtype_essay" to "1"
And I press "submitbutton"
Then I should see "Adding an Essay question"
And I set the field "Question name" to "Essay 01 new"
And I set the field "Question text" to "Please write 200 words about Essay 01"
And I press "id_submitbutton"
Then I should see "Essay 01 new"
And I choose "Preview" action for "Essay 01 new" in the question bank
And I click on "Comments" "link"
Then I should see "Save comment"
And I log out
And I am on the "Test quiz" "mod_quiz > question bank" page logged in as "teacher2"
And I apply question bank filter "Category" with value "Test questions"
And I choose "Preview" action for "First question" in the question bank
Then I should not see "Save comment"
And I click on "Close preview" "button"
And I choose "Preview" action for "Essay 01 new" in the question bank
Then I should not see "Save comment"
And I click on "Close preview" "button"
@javascript
Scenario: Comments added from the quiz page are visible
Given I am on the "Test quiz" "mod_quiz > edit" page logged in as "teacher1"
And I press "Add"
And I follow "from question bank"
And I click on "Select" "checkbox" in the "First question" "table_row"
And I click on "Add selected questions to the quiz" "button"
And I click on "Preview question" "link"
And I switch to "questionpreview" window
And I press "Comments"
And I set the field "content" to "Some new comment"
And I click on "Save comment" "link"
And I should see "Some new comment"
And I switch to the main window
And I am on the "Test quiz" "mod_quiz > question bank" page
And I choose "Preview" action for "First question" in the question bank
And I click on "Comments" "link"
And I should see "Some new comment"
And I should see "T1 Teacher1"
And I delete "Some new comment" comment from question preview
And I should not see "Some new comment"
And I am on the "Test quiz" "mod_quiz > edit" page
And I click on "Preview question" "link"
And I switch to "questionpreview" window
And I press "Comments"
Then I should not see "Some new comment"
@javascript
Scenario: Comments modal can change the version using dropdown
Given I log in as "teacher1"
And I am on the "Test quiz" "quiz activity" page
When I navigate to "Question bank" in current page administration
And I should see "First question"
And I choose "Edit question" action for "First question" in the question bank
And I set the field "id_name" to "Renamed question v2"
And I set the field "id_questiontext" to "edited question"
And I press "id_submitbutton"
And I should not see "First question"
And I should see "Renamed question v2"
And I click "0" on the row on the comments column
And I should see "Version 2"
Then I should see "edited question"
And I should see "Version 1"
And I set the field "question_version_dropdown" to "Version 1"
And I should see "Answer the first question"
@@ -0,0 +1,30 @@
@qbank @qbank_comment
Feature: Use the qbank plugin manager page for comment
In order to check the plugin behaviour with enable and disable
Background:
Given the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "activities" exist:
| activity | name | course | idnumber |
| quiz | Test quiz | C1 | quiz1 |
And the following "question categories" exist:
| contextlevel | reference | name |
| Course | C1 | Test questions |
And the following "questions" exist:
| questioncategory | qtype | name | questiontext |
| Test questions | truefalse | First question | Answer the first question |
@javascript
Scenario: Enable/disable comment column from the base view
Given I log in as "admin"
When I navigate to "Plugins > Question bank plugins > Manage question bank plugins" in site administration
And I should see "Question comments"
And I click on "Disable" "link" in the "Question comments" "table_row"
And I am on the "Test quiz" "mod_quiz > question bank" page
Then "#categoryquestions .header.commentcount" "css_element" should not be visible
And I navigate to "Plugins > Question bank plugins > Manage question bank plugins" in site administration
And I click on "Enable" "link" in the "Question comments" "table_row"
And I am on the "Test quiz" "mod_quiz > question bank" page
And "#categoryquestions .header.commentcount" "css_element" should be visible
@@ -0,0 +1,127 @@
<?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 qbank_comment\event;
use advanced_testcase;
use cache;
use comment;
use context;
use context_course;
use core_question_generator;
use stdClass;
/**
* Event tests for question comments.
*
* @package qbank_comment
* @copyright 2021 Catalyst IT Australia Pty Ltd
* @author Safat Shahin <safatshahin@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class comment_created_deleted_test extends advanced_testcase {
/** @var stdClass Keeps course object */
private $course;
/** @var context Keeps context */
private $context;
/** @var stdClass Keeps question object */
private $questiondata;
/** @var stdClass Keeps comment object */
private $comment;
/**
* Setup test data.
*/
public function setUp(): void {
global $CFG;
require_once($CFG->dirroot . '/comment/lib.php');
$this->resetAfterTest();
$this->setAdminUser();
$generator = $this->getDataGenerator();
/** @var core_question_generator $questiongenerator */
$questiongenerator = $generator->get_plugin_generator('core_question');
// Create a course.
$this->course = $generator->create_course();
$this->context = context_course::instance($this->course->id);
// Create a question in the default category.
$contexts = new \core_question\local\bank\question_edit_contexts($this->context);
$cat = question_make_default_categories($contexts->all());
$this->questiondata = $questiongenerator->create_question('numerical', null,
['name' => 'Example question', 'category' => $cat->id]);
// Ensure the question is not in the cache.
$cache = cache::make('core', 'questiondata');
$cache->delete($this->questiondata->id);
// Comment on question.
$args = new stdClass;
$args->context = $this->context;
$args->course = $this->course;
$args->area = 'question';
$args->itemid = $this->questiondata->id;
$args->component = 'qbank_comment';
$args->linktext = get_string('commentheader', 'qbank_comment');
$args->notoggle = true;
$args->autostart = true;
$args->displaycancel = false;
$this->comment = new comment($args);
}
/**
* Test comment_created event.
*/
public function test_comment_created(): void {
// Triggering and capturing the event.
$sink = $this->redirectEvents();
$this->comment->add('New comment');
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\qbank_comment\event\comment_created', $event);
$this->assertEquals($this->context, $event->get_context());
$this->assertStringContainsString('\'qbank_comment\' for the question with ID \''.$this->questiondata->id.'\'',
$event->get_description());
}
/**
* Test comment_created event.
*/
public function test_comment_deleted(): void {
// Triggering and capturing the event.
$newcomment = $this->comment->add('New comment to delete');
$sink = $this->redirectEvents();
$this->comment->delete($newcomment->id);
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\qbank_comment\event\comment_deleted', $event);
$this->assertEquals($this->context, $event->get_context());
$this->assertStringContainsString('\'qbank_comment\' for the question with ID \''.$this->questiondata->id.'\'',
$event->get_description());
}
}
@@ -0,0 +1,66 @@
<?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 qbank_comment\event;
/**
* Tests for question_deleted_observer
*
* @package qbank_comment
* @copyright 2023 onwards Catalyst IT EU {@link https://catalyst-eu.net}
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \qbank_comment\event\question_deleted_observer
*/
class question_deleted_observer_test extends \advanced_testcase {
/**
* Deleting a question with comments should also delete the comments
*
* @return void
*/
public function test_delete_question_with_comments(): void {
$this->resetAfterTest();
$this->setAdminUser();
$questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
[, , , $questions] = $questiongenerator->setup_course_and_questions();
$question = reset($questions);
$context = \context_system::instance();
$commentgenerator = $this->getDataGenerator()->get_plugin_generator('core_comment');
/** @var \comment $comment */
$comment = $commentgenerator->create_comment([
'context' => $context,
'component' => 'qbank_comment',
'area' => 'question',
'itemid' => $question->id,
'content' => random_string(),
]);
$this->assertEquals(1, $comment->count());
question_delete_question($question->id);
$newcomment = new \comment((object)[
'context' => $context,
'component' => 'qbank_comment',
'area' => 'question',
'itemid' => $question->id,
]);
$this->assertEquals(0, $newcomment->count());
}
}
+128
View File
@@ -0,0 +1,128 @@
<?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 qbank_comment;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/question/bank/comment/lib.php');
/**
* Comment lib unit tests.
*
* @package qbank_comment
* @copyright 2021 Catalyst IT Australia Pty Ltd
* @author Matt Porritt <mattp@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class lib_test extends \advanced_testcase {
/**
* Test the comment validation callback.
*/
public function test_qbank_comment_comment_validate(): void {
$commentparams = new \stdClass();
$commentparams->commentarea = 'question';
$commentparams->component = 'qbank_comment';
$isvalid = qbank_comment_comment_validate($commentparams);
$this->assertTrue($isvalid);
$this->expectException('comment_exception');
$commentparams->commentarea = 'core_comment';
$commentparams->component = 'blog_comment';
qbank_comment_comment_validate($commentparams);
}
/**
* Test the comment display callback.
*/
public function test_qbank_comment_comment_display(): void {
$comment = new \stdClass();
$comment->text = 'test';
$comments = [$comment];
$commentparams = new \stdClass();
$commentparams->commentarea = 'question';
$commentparams->component = 'qbank_comment';
$responses = qbank_comment_comment_display($comments, $commentparams);
$this->assertEquals($comment->text, $responses[0]->text);
$this->expectException('comment_exception');
$commentparams->commentarea = 'core_comment';
$commentparams->component = 'blog_comment';
qbank_comment_comment_display($comments, $commentparams);
}
/**
* Test the comment preview callback.
*/
public function test_qbank_comment_preview_display(): void {
$this->resetAfterTest();
global $PAGE;
$PAGE->set_url('/');
// Make a test question.
$category = $this->getDataGenerator()->create_category();
$course = $this->getDataGenerator()->create_course(['category' => $category->id]);
$qgen = $this->getDataGenerator()->get_plugin_generator('core_question');
$context = \context_coursecat::instance($category->id);
$qcat = $qgen->create_question_category(['contextid' => $context->id]);
$question = $qgen->create_question('shortanswer', null, ['category' => $qcat->id, 'idnumber' => 'q1']);
$result = qbank_comment_preview_display($question, $course->id);
// User doesn't have perms so expecting no output.
$this->assertEmpty($result);
// Expect output.
$this->setAdminUser();
$result = qbank_comment_preview_display($question, $course->id);
$this->assertStringContainsString('comment-action-post', $result);
}
/**
* Test the comment preview callback.
*/
public function test_qbank_comment_output_fragment_question_comment(): void {
$this->resetAfterTest();
$this->setAdminUser();
global $PAGE;
$PAGE->set_url('/');
// Make a test question.
$category = $this->getDataGenerator()->create_category();
$course = $this->getDataGenerator()->create_course(['category' => $category->id]);
$qgen = $this->getDataGenerator()->get_plugin_generator('core_question');
$context = \context_coursecat::instance($category->id);
$qcat = $qgen->create_question_category(['contextid' => $context->id]);
$question = $qgen->create_question('shortanswer', null, ['category' => $qcat->id, 'idnumber' => 'q1']);
$args = [
'questionid' => $question->id,
'courseid' => $course->id,
];
$result = qbank_comment_output_fragment_question_comment($args);
// Expect output.
$this->assertStringContainsString('comment-action-post', $result);
}
}
@@ -0,0 +1,358 @@
<?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 qbank_comment\privacy;
use comment;
use context;
use context_course;
use core_privacy\local\metadata\collection;
use qbank_comment\privacy\provider;
use core_privacy\local\request\approved_userlist;
use stdClass;
/**
* Privacy api tests.
*
* @package qbank_comment
* @copyright 2021 Catalyst IT Australia Pty Ltd
* @author Safat Shahin <safatshahin@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider_test extends \core_privacy\tests\provider_testcase {
/** @var stdClass A teacher who is only enrolled in course1. */
protected $teacher1;
/** @var stdClass A teacher who is only enrolled in course2. */
protected $teacher2;
/** @var stdClass A teacher who is enrolled in both course1 and course2. */
protected $teacher3;
/** @var stdClass A test course. */
protected $course1;
/** @var stdClass A test course. */
protected $course2;
/**
* Set up function for tests in this class.
*/
protected function setUp(): void {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
// Create courses.
$generator = $this->getDataGenerator();
$this->course1 = $generator->create_course();
$this->course2 = $generator->create_course();
// Create and enrol teachers.
$this->teacher1 = $generator->create_user();
$this->teacher2 = $generator->create_user();
$this->teacher3 = $generator->create_user();
$studentrole = $DB->get_record('role', ['shortname' => 'editingteacher']);
$generator->enrol_user($this->teacher1->id, $this->course1->id, $studentrole->id);
$generator->enrol_user($this->teacher2->id, $this->course2->id, $studentrole->id);
$generator->enrol_user($this->teacher3->id, $this->course1->id, $studentrole->id);
$generator->enrol_user($this->teacher3->id, $this->course2->id, $studentrole->id);
}
/**
* Posts a comment on a given context.
*
* @param string $text The comment's text.
* @param context $context The context on which we want to put the comment.
*/
protected function add_comment($text, context $context) {
$args = new stdClass;
$args->context = $context;
$args->area = 'question';
$args->itemid = 0;
$args->component = 'qbank_comment';
$args->linktext = get_string('commentheader', 'qbank_comment');
$args->notoggle = true;
$args->autostart = true;
$args->displaycancel = false;
$comment = new comment($args);
$comment->add($text);
}
/**
* Test for provider::get_metadata().
*/
public function test_get_metadata(): void {
$collection = new collection('qbank_comment');
$newcollection = provider::get_metadata($collection);
$itemcollection = $newcollection->get_collection();
$this->assertCount(1, $itemcollection);
$link = reset($itemcollection);
$this->assertEquals('core_comment', $link->get_name());
$this->assertEmpty($link->get_privacy_fields());
$this->assertEquals('privacy:metadata:core_comment', $link->get_summary());
}
/**
* Test for provider::get_contexts_for_userid() when user had not posted any comments..
*/
public function test_get_contexts_for_userid_no_comment(): void {
$this->setUser($this->teacher1);
$coursecontext1 = context_course::instance($this->course1->id);
$this->add_comment('New comment', $coursecontext1);
$this->setUser($this->teacher2);
$contextlist = provider::get_contexts_for_userid($this->teacher2->id);
$this->assertCount(0, $contextlist);
}
/**
* Test for provider::get_contexts_for_userid().
*/
public function test_get_contexts_for_userid(): void {
$coursecontext1 = context_course::instance($this->course1->id);
$coursecontext2 = context_course::instance($this->course2->id);
$this->setUser($this->teacher3);
$this->add_comment('New comment', $coursecontext1);
$this->add_comment('New comment', $coursecontext1);
$this->add_comment('New comment', $coursecontext2);
$contextlist = provider::get_contexts_for_userid($this->teacher3->id);
$this->assertCount(2, $contextlist);
$contextids = $contextlist->get_contextids();
$this->assertEqualsCanonicalizing([$coursecontext1->id, $coursecontext2->id], $contextids);
}
/**
* Test for provider::export_user_data() when the user has not posted any comments.
*/
public function test_export_for_context_no_comment(): void {
$coursecontext1 = context_course::instance($this->course1->id);
$coursecontext2 = context_course::instance($this->course2->id);
$this->setUser($this->teacher1);
$this->add_comment('New comment', $coursecontext1);
$this->setUser($this->teacher2);
$this->setUser($this->teacher2);
$this->export_context_data_for_user($this->teacher1->id, $coursecontext2, 'qbank_comment');
$writer = \core_privacy\local\request\writer::with_context($coursecontext2);
$this->assertFalse($writer->has_any_data());
}
/**
* Test for provider::export_user_data().
*/
public function test_export_for_context(): void {
$coursecontext1 = context_course::instance($this->course1->id);
$coursecontext2 = context_course::instance($this->course2->id);
$this->setUser($this->teacher3);
$this->add_comment('New comment', $coursecontext1);
$this->add_comment('New comment', $coursecontext1);
$this->add_comment('New comment', $coursecontext2);
// Export all of the data for the context.
$this->export_context_data_for_user($this->teacher3->id, $coursecontext1, 'qbank_comment');
$writer = \core_privacy\local\request\writer::with_context($coursecontext1);
$this->assertTrue($writer->has_any_data());
}
/**
* Test for provider::delete_data_for_all_users_in_context().
*/
public function test_delete_data_for_all_users_in_context(): void {
global $DB;
$coursecontext1 = context_course::instance($this->course1->id);
$coursecontext2 = context_course::instance($this->course2->id);
$this->setUser($this->teacher1);
$this->add_comment('New comment', $coursecontext1);
$this->setUser($this->teacher2);
$this->add_comment('New comment', $coursecontext2);
$this->setUser($this->teacher3);
$this->add_comment('New comment', $coursecontext1);
$this->add_comment('New comment', $coursecontext1);
$this->add_comment('New comment', $coursecontext2);
// Before deletion, we should have 3 comments in $coursecontext1 and 2 comments in $coursecontext2.
$this->assertEquals(
3,
$DB->count_records('comments', ['component' => 'qbank_comment', 'contextid' => $coursecontext1->id])
);
$this->assertEquals(
2,
$DB->count_records('comments', ['component' => 'qbank_comment', 'contextid' => $coursecontext2->id])
);
// Delete data based on context.
provider::delete_data_for_all_users_in_context($coursecontext1);
// After deletion, the comments for $coursecontext1 should have been deleted.
$this->assertEquals(
0,
$DB->count_records('comments', ['component' => 'qbank_comment', 'contextid' => $coursecontext1->id])
);
$this->assertEquals(
2,
$DB->count_records('comments', ['component' => 'qbank_comment', 'contextid' => $coursecontext2->id])
);
}
/**
* Test for provider::delete_data_for_user().
*/
public function test_delete_data_for_user(): void {
global $DB;
$coursecontext1 = context_course::instance($this->course1->id);
$coursecontext2 = context_course::instance($this->course2->id);
$this->setUser($this->teacher1);
$this->add_comment('New comment', $coursecontext1);
$this->setUser($this->teacher2);
$this->add_comment('New comment', $coursecontext2);
$this->setUser($this->teacher3);
$this->add_comment('New comment', $coursecontext1);
$this->add_comment('New comment', $coursecontext1);
$this->add_comment('New comment', $coursecontext2);
// Before deletion, we should have 3 comments in $coursecontext1 and 2 comments in $coursecontext2,
// and 3 comments by student12 in $coursecontext1 and $coursecontext2 combined.
$this->assertEquals(
3,
$DB->count_records('comments', ['component' => 'qbank_comment', 'contextid' => $coursecontext1->id])
);
$this->assertEquals(
2,
$DB->count_records('comments', ['component' => 'qbank_comment', 'contextid' => $coursecontext2->id])
);
$this->assertEquals(
3,
$DB->count_records('comments', ['component' => 'qbank_comment', 'userid' => $this->teacher3->id])
);
$contextlist = new \core_privacy\local\request\approved_contextlist($this->teacher3, 'qbank_comment',
[$coursecontext1->id, $coursecontext2->id]);
provider::delete_data_for_user($contextlist);
// After deletion, the comments for the student12 should have been deleted.
$this->assertEquals(
1,
$DB->count_records('comments', ['component' => 'qbank_comment', 'contextid' => $coursecontext1->id])
);
$this->assertEquals(
1,
$DB->count_records('comments', ['component' => 'qbank_comment', 'contextid' => $coursecontext2->id])
);
$this->assertEquals(
0,
$DB->count_records('comments', ['component' => 'qbank_comment', 'userid' => $this->teacher3->id])
);
}
/**
* Test that only users within a course context are fetched.
*/
public function test_get_users_in_context(): void {
$component = 'qbank_comment';
$coursecontext1 = context_course::instance($this->course1->id);
$coursecontext2 = context_course::instance($this->course2->id);
$userlist1 = new \core_privacy\local\request\userlist($coursecontext1, $component);
provider::get_users_in_context($userlist1);
$this->assertCount(0, $userlist1);
$userlist2 = new \core_privacy\local\request\userlist($coursecontext2, $component);
provider::get_users_in_context($userlist2);
$this->assertCount(0, $userlist2);
$this->setUser($this->teacher3);
$this->add_comment('New comment', $coursecontext1);
$this->add_comment('New comment', $coursecontext2);
$this->setUser($this->teacher1);
$this->add_comment('New comment', $coursecontext1);
// The list of users should contain teacher3 and user1.
provider::get_users_in_context($userlist1);
$this->assertCount(2, $userlist1);
$this->assertTrue(in_array($this->teacher1->id, $userlist1->get_userids()));
$this->assertTrue(in_array($this->teacher3->id, $userlist1->get_userids()));
// The list of users should contain teacher3.
provider::get_users_in_context($userlist2);
$this->assertCount(1, $userlist2);
$expected = [$this->teacher3->id];
$actual = $userlist2->get_userids();
$this->assertEquals($expected, $actual);
}
/**
* Test that data for users in approved userlist is deleted.
*/
public function test_delete_data_for_users(): void {
$component = 'qbank_comment';
$coursecontext1 = context_course::instance($this->course1->id);
$coursecontext2 = context_course::instance($this->course2->id);
$this->setUser($this->teacher3);
$this->add_comment('New comment', $coursecontext1);
$this->add_comment('New comment', $coursecontext2);
$this->setUser($this->teacher1);
$this->add_comment('New comment', $coursecontext1);
$userlist1 = new \core_privacy\local\request\userlist($coursecontext1, $component);
provider::get_users_in_context($userlist1);
$this->assertCount(2, $userlist1);
$userlist2 = new \core_privacy\local\request\userlist($coursecontext2, $component);
provider::get_users_in_context($userlist2);
$this->assertCount(1, $userlist2);
// Convert $userlist1 into an approved_contextlist.
$approvedlist1 = new approved_userlist($coursecontext1, $component, $userlist1->get_userids());
// Delete using delete_data_for_user.
provider::delete_data_for_users($approvedlist1);
// Re-fetch users in coursecontext1.
$userlist1 = new \core_privacy\local\request\userlist($coursecontext1, $component);
provider::get_users_in_context($userlist1);
// The user data in coursecontext1 should be deleted.
$this->assertCount(0, $userlist1);
// Re-fetch users in coursecontext2.
$userlist2 = new \core_privacy\local\request\userlist($coursecontext2, $component);
provider::get_users_in_context($userlist2);
// The user data in coursecontext2 should be still present.
$this->assertCount(1, $userlist2);
}
}
+31
View File
@@ -0,0 +1,31 @@
<?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/>.
/**
* Version information for qbank_comment.
*
* @package qbank_comment
* @copyright 2021 Catalyst IT Australia Pty Ltd
* @author Safat Shahin <safatshahin@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$plugin->component = 'qbank_comment';
$plugin->version = 2024042200;
$plugin->requires = 2024041600;
$plugin->maturity = MATURITY_STABLE;