mirror of
https://github.com/moodle/moodle.git
synced 2025-01-17 21:49:15 +01:00
MDL-71642 qbank_comment: Add question comment plugin to core
This implementation will introduce a qbank plugin "comment" which will allow users with the capability to comment in a question. It also implements a callback for the question preview page to view and add comments from the preview page. Comment plugin is implemented using the existing comments API from the core. Co-Authored-By: Guillermo Gomez Arias <guillermogomez@catalyst-au.net> Co-Authored-By: Safat Shahin <safatshahin@catalyst-au.net> Co-Authored-By: Matt Porritt <mattp@catalyst-au.net>
This commit is contained in:
parent
70073fdc74
commit
3be2b123e5
@ -36,6 +36,7 @@ require_once($CFG->dirroot . '/backup/moodle2/backup_block_task.class.php');
|
||||
require_once($CFG->dirroot . '/backup/moodle2/backup_default_block_task.class.php');
|
||||
require_once($CFG->dirroot . '/backup/moodle2/backup_xml_transformer.class.php');
|
||||
require_once($CFG->dirroot . '/backup/moodle2/backup_plugin.class.php');
|
||||
require_once($CFG->dirroot . '/backup/moodle2/backup_qbank_plugin.class.php');
|
||||
require_once($CFG->dirroot . '/backup/moodle2/backup_qtype_plugin.class.php');
|
||||
require_once($CFG->dirroot . '/backup/moodle2/backup_qtype_extrafields_plugin.class.php');
|
||||
require_once($CFG->dirroot . '/backup/moodle2/backup_gradingform_plugin.class.php');
|
||||
|
38
backup/moodle2/backup_qbank_plugin.class.php
Normal file
38
backup/moodle2/backup_qbank_plugin.class.php
Normal file
@ -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/>.
|
||||
|
||||
/**
|
||||
* Defines backup_qbank_plugin class.
|
||||
*
|
||||
* @package core_backup
|
||||
* @subpackage moodle2
|
||||
* @category backup
|
||||
* @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
|
||||
*/
|
||||
|
||||
/**
|
||||
* Base class for qbank backup plugins.
|
||||
*
|
||||
* @package core_backup
|
||||
* @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
|
||||
*/
|
||||
abstract class backup_qbank_plugin extends backup_plugin {
|
||||
// Use default parent behaviour.
|
||||
}
|
@ -787,34 +787,28 @@ class backup_filters_structure_step extends backup_structure_step {
|
||||
}
|
||||
|
||||
/**
|
||||
* structure step in charge of constructing the comments.xml file for all the comments found
|
||||
* in a given context
|
||||
* Structure step in charge of constructing the comments.xml file for all the comments found in a given context.
|
||||
*/
|
||||
class backup_comments_structure_step extends backup_structure_step {
|
||||
|
||||
protected function define_structure() {
|
||||
|
||||
// Define each element separated
|
||||
|
||||
// Define each element separated.
|
||||
$comments = new backup_nested_element('comments');
|
||||
|
||||
$comment = new backup_nested_element('comment', array('id'), array(
|
||||
'commentarea', 'itemid', 'content', 'format',
|
||||
'component', 'commentarea', 'itemid', 'content', 'format',
|
||||
'userid', 'timecreated'));
|
||||
|
||||
// Build the tree
|
||||
|
||||
// Build the tree.
|
||||
$comments->add_child($comment);
|
||||
|
||||
// Define sources
|
||||
|
||||
// Define sources.
|
||||
$comment->set_source_table('comments', array('contextid' => backup::VAR_CONTEXTID));
|
||||
|
||||
// Define id annotations
|
||||
|
||||
// Define id annotations.
|
||||
$comment->annotate_ids('user', 'userid');
|
||||
|
||||
// Return the root element (comments)
|
||||
// Return the root element (comments).
|
||||
return $comments;
|
||||
}
|
||||
}
|
||||
@ -2356,6 +2350,9 @@ class backup_questions_structure_step extends backup_structure_step {
|
||||
// attach qtype plugin structure to $question element, only one allowed
|
||||
$this->add_plugin_structure('qtype', $question, false);
|
||||
|
||||
// Attach qbank plugin stucture to $question element, multiple allowed.
|
||||
$this->add_plugin_structure('qbank', $question, true);
|
||||
|
||||
// attach local plugin stucture to $question element, multiple allowed
|
||||
$this->add_plugin_structure('local', $question, true);
|
||||
|
||||
|
@ -35,6 +35,7 @@ require_once($CFG->dirroot . '/backup/moodle2/restore_final_task.class.php');
|
||||
require_once($CFG->dirroot . '/backup/moodle2/restore_block_task.class.php');
|
||||
require_once($CFG->dirroot . '/backup/moodle2/restore_default_block_task.class.php');
|
||||
require_once($CFG->dirroot . '/backup/moodle2/restore_plugin.class.php');
|
||||
require_once($CFG->dirroot . '/backup/moodle2/restore_qbank_plugin.class.php');
|
||||
require_once($CFG->dirroot . '/backup/moodle2/restore_qtype_plugin.class.php');
|
||||
require_once($CFG->dirroot . '/backup/moodle2/restore_qtype_extrafields_plugin.class.php');
|
||||
require_once($CFG->dirroot . '/backup/moodle2/restore_format_plugin.class.php');
|
||||
@ -46,6 +47,7 @@ require_once($CFG->dirroot . '/backup/moodle2/restore_plagiarism_plugin.class.ph
|
||||
require_once($CFG->dirroot . '/backup/moodle2/restore_gradingform_plugin.class.php');
|
||||
require_once($CFG->dirroot . '/backup/moodle2/restore_enrol_plugin.class.php');
|
||||
require_once($CFG->dirroot . '/backup/moodle2/backup_plugin.class.php');
|
||||
require_once($CFG->dirroot . '/backup/moodle2/backup_qbank_plugin.class.php');
|
||||
require_once($CFG->dirroot . '/backup/moodle2/backup_qtype_plugin.class.php');
|
||||
require_once($CFG->dirroot . '/backup/moodle2/backup_qtype_extrafields_plugin.class.php');
|
||||
require_once($CFG->dirroot . '/backup/moodle2/backup_format_plugin.class.php');
|
||||
|
39
backup/moodle2/restore_qbank_plugin.class.php
Normal file
39
backup/moodle2/restore_qbank_plugin.class.php
Normal file
@ -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/>.
|
||||
|
||||
/**
|
||||
* Defines restore_qbank_plugin class.
|
||||
*
|
||||
* @package core_backup
|
||||
* @subpackage moodle2
|
||||
* @category backup
|
||||
* @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
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Base class for qbank backup plugins.
|
||||
*
|
||||
* @package core_backup
|
||||
* @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
|
||||
*/
|
||||
abstract class restore_qbank_plugin extends restore_plugin {
|
||||
// Use default parent behaviour.
|
||||
}
|
@ -4750,10 +4750,13 @@ class restore_create_categories_and_questions extends restore_structure_step {
|
||||
// Apply for 'qtype' plugins optional paths at question level
|
||||
$this->add_plugin_structure('qtype', $question);
|
||||
|
||||
// Apply for 'qbank' plugins optional paths at question level.
|
||||
$this->add_plugin_structure('qbank', $question);
|
||||
|
||||
// Apply for 'local' plugins optional paths at question level
|
||||
$this->add_plugin_structure('local', $question);
|
||||
|
||||
return array($category, $question, $hint, $tag);
|
||||
return [$category, $question, $hint, $tag];
|
||||
}
|
||||
|
||||
protected function process_question_category($data) {
|
||||
|
@ -365,6 +365,8 @@ $string['question:viewall'] = 'View all questions';
|
||||
$string['question:viewmine'] = 'View your own questions';
|
||||
$string['question:tagall'] = 'Tag all questions';
|
||||
$string['question:tagmine'] = 'Tag your own questions';
|
||||
$string['question:commentall'] = 'Comment all questions';
|
||||
$string['question:commentmine'] = 'Comment your own questions';
|
||||
$string['rating:rate'] = 'Add ratings to items';
|
||||
$string['rating:view'] = 'View the total rating you received';
|
||||
$string['rating:viewany'] = 'View total ratings that anyone received';
|
||||
|
@ -1944,6 +1944,7 @@ class core_plugin_manager {
|
||||
),
|
||||
|
||||
'qbank' => [
|
||||
'comment',
|
||||
'deletequestion',
|
||||
'editquestion',
|
||||
'exporttoxml',
|
||||
|
@ -387,6 +387,9 @@ function question_delete_question($questionid) {
|
||||
}
|
||||
}
|
||||
|
||||
// Delete question comments.
|
||||
$DB->delete_records('comments', ['itemid' => $questionid, 'component' => 'qbank_comment',
|
||||
'commentarea' => 'question']);
|
||||
// Finally delete the question record itself
|
||||
$DB->delete_records('question', array('id' => $questionid));
|
||||
question_bank::notify_question_edited($questionid);
|
||||
@ -1569,7 +1572,7 @@ function question_has_capability_on($questionorid, $cap, $notused = -1) {
|
||||
|
||||
// These are existing questions capabilities that are set per category.
|
||||
// Each of these has a 'mine' and 'all' version that is appended to the capability name.
|
||||
$capabilitieswithallandmine = ['edit' => 1, 'view' => 1, 'use' => 1, 'move' => 1, 'tag' => 1];
|
||||
$capabilitieswithallandmine = ['edit' => 1, 'view' => 1, 'use' => 1, 'move' => 1, 'tag' => 1, 'comment' => 1];
|
||||
|
||||
if (!isset($capabilitieswithallandmine[$cap])) {
|
||||
return has_capability('moodle/question:' . $cap, $context);
|
||||
@ -1742,6 +1745,8 @@ function question_get_question_capabilities() {
|
||||
'moodle/question:moveall',
|
||||
'moodle/question:tagmine',
|
||||
'moodle/question:tagall',
|
||||
'moodle/question:commentmine',
|
||||
'moodle/question:commentall',
|
||||
);
|
||||
}
|
||||
|
||||
|
2
question/bank/comment/amd/build/comment.min.js
vendored
Normal file
2
question/bank/comment/amd/build/comment.min.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
function _typeof(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(a){return typeof a}}else{_typeof=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof(a)}define ("qbank_comment/comment",["exports","core/fragment","core/str","core/modal_events","core/modal_factory","core/notification"],function(a,b,c,d,e,f){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;b=i(b);c=h(c);d=i(d);e=i(e);f=i(f);function g(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;g=function(){return a};return a}function h(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=g();if(b&&b.has(a)){return b.get(a)}var c={},d=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var e in a){if(Object.prototype.hasOwnProperty.call(a,e)){var f=d?Object.getOwnPropertyDescriptor(a,e):null;if(f&&(f.get||f.set)){Object.defineProperty(c,e,f)}else{c[e]=a[e]}}}c.default=a;if(b){b.set(a,c)}return c}function i(a){return a&&a.__esModule?a:{default:a}}var j=function(a,g,h){var i=b.default.loadFragment("qbank_comment","question_comment",h,{questionid:a,courseid:g});e.default.create({type:e.default.types.SAVE_CANCEL,title:c.get_string("commentheader","qbank_comment"),body:i,large:!0}).then(function(a){var b=a.getRoot();b.on(d.default.bodyRendered,function(){var a=document.querySelectorAll("div.comment-area a")[0];a.style.display="none"});c.get_strings([{key:"addcomment",component:"qbank_comment"},{key:"close",component:"qbank_comment"}]).then(function(b){a.setButtonText("save",b[0]);a.setButtonText("cancel",b[1])}).fail(f.default.exception);b.on(d.default.cancel,function(){location.reload();a.hide()});b.on(d.default.save,function(a){a.preventDefault();var b=document.querySelectorAll("div.comment-area a")[0],c=document.querySelectorAll("div.comment-area textarea")[0];if(c.value!=c.getAttribute("aria-label")&&""!=c.value){b.click()}});b.on("click","button[data-action=\"hide\"]",function(){location.reload();a.hide()});a.show();return a}).fail(f.default.exception)};a.init=function init(a){var b=document.querySelector(a),c=b.getAttribute("data-questionid"),d=b.getAttribute("data-courseid");b.addEventListener("click",function(){j(c,d,1)})}});
|
||||
//# sourceMappingURL=comment.min.js.map
|
1
question/bank/comment/amd/build/comment.min.js.map
Normal file
1
question/bank/comment/amd/build/comment.min.js.map
Normal file
File diff suppressed because one or more lines are too long
110
question/bank/comment/amd/src/comment.js
Normal file
110
question/bank/comment/amd/src/comment.js
Normal file
@ -0,0 +1,110 @@
|
||||
// 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.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
|
||||
import Fragment from 'core/fragment';
|
||||
import * as Str from 'core/str';
|
||||
import ModalEvents from 'core/modal_events';
|
||||
import ModalFactory from 'core/modal_factory';
|
||||
import Notification from 'core/notification';
|
||||
|
||||
/**
|
||||
* Event listeners for the module.
|
||||
*
|
||||
* @method clickEvent
|
||||
* @param {int} questionId
|
||||
* @param {int} courseID
|
||||
* @param {int} contextId
|
||||
*/
|
||||
const commentEvent = (questionId, courseID, contextId) => {
|
||||
let args = {
|
||||
questionid: questionId,
|
||||
courseid: courseID
|
||||
};
|
||||
let commentFragment = Fragment.loadFragment('qbank_comment', 'question_comment', contextId, args);
|
||||
ModalFactory.create({
|
||||
type: ModalFactory.types.SAVE_CANCEL,
|
||||
title: Str.get_string('commentheader', 'qbank_comment'),
|
||||
body: commentFragment,
|
||||
large: true,
|
||||
}).then((modal) => {
|
||||
let 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';
|
||||
});
|
||||
|
||||
// Get the required strings and updated the modal button text labels.
|
||||
Str.get_strings([
|
||||
{key: 'addcomment', component: 'qbank_comment'},
|
||||
{key: 'close', component: 'qbank_comment'},
|
||||
]).then((strings) => {
|
||||
modal.setButtonText('save', strings[0]);
|
||||
modal.setButtonText('cancel', strings[1]);
|
||||
return;
|
||||
}).fail(Notification.exception);
|
||||
|
||||
root.on(ModalEvents.cancel, function() {
|
||||
location.reload();
|
||||
modal.hide();
|
||||
});
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
});
|
||||
root.on('click', 'button[data-action="hide"]', () => {
|
||||
location.reload();
|
||||
modal.hide();
|
||||
});
|
||||
modal.show();
|
||||
return modal;
|
||||
}).fail(Notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Entrypoint of the js.
|
||||
*
|
||||
* @method init
|
||||
* @param {string} questionSelector the question comment identifier.
|
||||
*/
|
||||
export const init = (questionSelector) => {
|
||||
let target = document.querySelector(questionSelector);
|
||||
let contextId = 1;
|
||||
let questionId = target.getAttribute('data-questionid'),
|
||||
courseID = target.getAttribute('data-courseid');
|
||||
target.addEventListener('click', () => {
|
||||
// Call for the event listener to listed for clicks in any comment count row.
|
||||
commentEvent(questionId, courseID, contextId);
|
||||
});
|
||||
};
|
@ -0,0 +1,59 @@
|
||||
<?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.commentarea = 'question'
|
||||
AND c.component = 'qbank_comment'
|
||||
AND c.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);
|
||||
}
|
||||
}
|
||||
}
|
80
question/bank/comment/classes/comment_count_column.php
Normal file
80
question/bank/comment/classes/comment_count_column.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?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 {
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
protected 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, $PAGE;
|
||||
$args = [
|
||||
'component' => 'qbank_comment',
|
||||
'commentarea' => 'question',
|
||||
'itemid' => $question->id,
|
||||
'contextid' => 1
|
||||
];
|
||||
$commentcount = $DB->count_records('comments', $args);
|
||||
$attributes = [];
|
||||
if (question_has_capability_on($question, 'comment')) {
|
||||
$target = 'questioncommentpreview_' . $question->id;
|
||||
$datatarget = '[data-target="' . $target . '"]';
|
||||
$PAGE->requires->js_call_amd('qbank_comment/comment', 'init', [$datatarget]);
|
||||
$attributes = [
|
||||
'data-target' => $target,
|
||||
'data-questionid' => $question->id,
|
||||
'data-courseid' => $this->qbank->course->id,
|
||||
'class' => 'link-primary comment-pointer'
|
||||
];
|
||||
}
|
||||
echo \html_writer::tag('a', $commentcount, $attributes);
|
||||
}
|
||||
|
||||
}
|
51
question/bank/comment/classes/event/comment_created.php
Normal file
51
question/bank/comment/classes/event/comment_created.php
Normal file
@ -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);
|
||||
}
|
||||
}
|
51
question/bank/comment/classes/event/comment_deleted.php
Normal file
51
question/bank/comment/classes/event/comment_deleted.php
Normal file
@ -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);
|
||||
}
|
||||
}
|
38
question/bank/comment/classes/output/renderer.php
Normal file
38
question/bank/comment/classes/output/renderer.php
Normal file
@ -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);
|
||||
}
|
||||
}
|
40
question/bank/comment/classes/plugin_feature.php
Normal file
40
question/bank/comment/classes/plugin_feature.php
Normal file
@ -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)
|
||||
];
|
||||
}
|
||||
}
|
140
question/bank/comment/classes/privacy/provider.php
Normal file
140
question/bank/comment/classes/privacy/provider.php
Normal file
@ -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
question/bank/comment/db/access.php
Normal file
50
question/bank/comment/db/access.php
Normal 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'
|
||||
],
|
||||
];
|
41
question/bank/comment/lang/en/qbank_comment.php
Normal file
41
question/bank/comment/lang/en/qbank_comment.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?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 comment';
|
||||
$string['privacy:metadata:core_comment'] = 'Question comment plugin helps users with permission to comment in a question.';
|
||||
// Column.
|
||||
$string['comment'] = 'Comment';
|
||||
$string['commentplural'] = 'Comments';
|
||||
// Modal.
|
||||
$string['addcomment'] = 'Add comment';
|
||||
$string['close'] = 'Close';
|
||||
$string['commentheader'] = 'Question comments';
|
||||
$string['commentdisabled'] = 'Comment feature is disabled "sitewide",
|
||||
please ask your "Site administrator" to enable "usecomments" from "Advanced settings" in order to comment in this question.';
|
||||
// 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}\'
|
||||
to the \'{$a->component}\' for the question with id \'{$a->itemid}\'.';
|
138
question/bank/comment/lib.php
Normal file
138
question/bank/comment/lib.php
Normal file
@ -0,0 +1,138 @@
|
||||
<?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();
|
||||
|
||||
/**
|
||||
* 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 = 1; // 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
|
||||
* @todo cleanup after class renaming to remove check for previewlib.php MDL-71679
|
||||
*/
|
||||
function qbank_comment_output_fragment_question_comment($args): string {
|
||||
global $USER, $PAGE, $CFG;
|
||||
$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));
|
||||
|
||||
if (class_exists('\\qbank_previewquestion\\question_preview_options')) {
|
||||
$options = new \qbank_previewquestion\question_preview_options($question);
|
||||
} else {
|
||||
require_once($CFG->dirroot . '/question/previewlib.php');
|
||||
$options = new question_preview_options($question);
|
||||
}
|
||||
|
||||
$options->load_user_defaults();
|
||||
$options->set_from_request();
|
||||
$quba->set_preferred_behaviour($options->behaviour);
|
||||
$slot = $quba->add_question($question, $options->maxmark);
|
||||
$quba->start_question($slot, $options->variant);
|
||||
$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;
|
||||
}
|
||||
|
||||
return $PAGE->get_renderer('qbank_comment')->render_comment_fragment($displaydata);
|
||||
}
|
9
question/bank/comment/styles.css
Normal file
9
question/bank/comment/styles.css
Normal file
@ -0,0 +1,9 @@
|
||||
/* Comment text area size to maximum */
|
||||
.question-comment-view .comment-ctrl .comment-area {
|
||||
max-width: none;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.comment-pointer {
|
||||
cursor: pointer;
|
||||
}
|
47
question/bank/comment/templates/comment_modal.mustache
Normal file
47
question/bank/comment/templates/comment_modal.mustache
Normal file
@ -0,0 +1,47 @@
|
||||
{{!
|
||||
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"
|
||||
}
|
||||
]
|
||||
}
|
||||
}}
|
||||
|
||||
<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>
|
209
question/bank/comment/tests/backup_test.php
Normal file
209
question/bank/comment/tests/backup_test.php
Normal file
@ -0,0 +1,209 @@
|
||||
<?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('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');
|
||||
|
||||
|
||||
/**
|
||||
* 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 qbank_comment_backup_restore_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() {
|
||||
global $DB;
|
||||
|
||||
$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.
|
||||
$coursecontext = \context_course::instance($this->course->id);
|
||||
$args = new stdClass;
|
||||
$args->context = $coursecontext;
|
||||
$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.
|
||||
$newquestion1 = $DB->get_record('question', ['idnumber' => 'q1']);
|
||||
$args->itemid = $newquestion1->id;
|
||||
$commentobj = new \comment($args);
|
||||
$this->assertEquals($commentobj->count(), 2);
|
||||
|
||||
$newquestion2 = $DB->get_record('question', ['idnumber' => 'q2']);
|
||||
$args->itemid = $newquestion2->id;
|
||||
$commentobj = new \comment($args);
|
||||
$this->assertEquals($commentobj->count(), 1);
|
||||
}
|
||||
}
|
143
question/bank/comment/tests/behat/behat_qbank_comment.php
Normal file
143
question/bank/comment/tests/behat/behat_qbank_comment.php
Normal file
@ -0,0 +1,143 @@
|
||||
<?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',
|
||||
'.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());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
}
|
114
question/bank/comment/tests/behat/question_comment.feature
Normal file
114
question/bank/comment/tests/behat/question_comment.feature
Normal file
@ -0,0 +1,114 @@
|
||||
@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 log in as "teacher1"
|
||||
And I am on the "Test quiz" "quiz activity" page
|
||||
And I navigate to "Question bank > Questions" in current page administration
|
||||
And I set the field "Select a category" to "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 log in as "teacher1"
|
||||
And I am on the "Test quiz" "quiz activity" page
|
||||
And I navigate to "Question bank > Questions" in current page administration
|
||||
And I set the field "Select a category" to "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 log in as "teacher1"
|
||||
And I am on the "Test quiz" "quiz activity" page
|
||||
And I navigate to "Question bank > Questions" in current page administration
|
||||
And I set the field "Select a category" to "Test questions"
|
||||
And I choose "Preview" action for "First question" in the question bank
|
||||
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 delete "Super test comment 01" comment from question
|
||||
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 I log in as "admin"
|
||||
And I set the following system permissions of "Teacher" role:
|
||||
| capability | permission |
|
||||
| moodle/question:commentmine | Allow |
|
||||
| moodle/question:commentall | Prevent |
|
||||
And I log out
|
||||
Then I log in as "teacher1"
|
||||
And I am on the "Test quiz" "quiz activity" page
|
||||
And I navigate to "Question bank > Questions" in current page administration
|
||||
And I set the field "Select a category" to "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
|
||||
Then I should see "Save comment"
|
||||
And I log out
|
||||
Then I log in as "teacher2"
|
||||
And I am on the "Test quiz" "quiz activity" page
|
||||
And I navigate to "Question bank > Questions" in current page administration
|
||||
And I set the field "Select a category" to "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"
|
@ -0,0 +1,32 @@
|
||||
@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 comment"
|
||||
And I click on "Disable" "link" in the "Question comment" "table_row"
|
||||
And I am on the "Test quiz" "quiz activity" page
|
||||
And I navigate to "Question bank > Questions" in current page administration
|
||||
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 comment" "table_row"
|
||||
And I am on the "Test quiz" "quiz activity" page
|
||||
And I navigate to "Question bank > Questions" in current page administration
|
||||
And "#categoryquestions .header.commentcount" "css_element" should be visible
|
@ -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\event;
|
||||
|
||||
use advanced_testcase;
|
||||
use cache;
|
||||
use comment;
|
||||
use context;
|
||||
use context_course;
|
||||
use core_question_generator;
|
||||
use question_edit_contexts;
|
||||
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 qbank_comment_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 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() {
|
||||
// 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() {
|
||||
// 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());
|
||||
}
|
||||
}
|
126
question/bank/comment/tests/lib_test.php
Normal file
126
question/bank/comment/tests/lib_test.php
Normal file
@ -0,0 +1,126 @@
|
||||
<?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('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 qbank_comment_lib_test extends \advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test the comment validation callback.
|
||||
*/
|
||||
public function test_qbank_comment_comment_validate() {
|
||||
$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() {
|
||||
$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() {
|
||||
$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() {
|
||||
$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);
|
||||
}
|
||||
}
|
358
question/bank/comment/tests/privacy/provider_test.php
Normal file
358
question/bank/comment/tests/privacy/provider_test.php
Normal file
@ -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 qbank_comment_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() {
|
||||
$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() {
|
||||
$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() {
|
||||
$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() {
|
||||
$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() {
|
||||
$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() {
|
||||
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() {
|
||||
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() {
|
||||
$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() {
|
||||
$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
question/bank/comment/version.php
Normal file
31
question/bank/comment/version.php
Normal 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 = 2021090100;
|
||||
$plugin->requires = 2021052500;
|
||||
$plugin->maturity = MATURITY_STABLE;
|
@ -27,7 +27,7 @@ use core\plugininfo\qbank;
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @coversDefaultClass \qbank_previewquestion\helper
|
||||
*/
|
||||
class helper_test extends \advanced_testcase {
|
||||
class qbank_preview_helper_test extends \advanced_testcase {
|
||||
|
||||
/**
|
||||
* @var bool|\context|\context_course $context
|
||||
@ -148,10 +148,13 @@ class helper_test extends \advanced_testcase {
|
||||
* @covers ::get_preview_extra_elements
|
||||
*/
|
||||
public function test_get_preview_extra_elements() {
|
||||
global $PAGE;
|
||||
$PAGE->set_url('/');
|
||||
|
||||
$question = \question_bank::load_question($this->questiondata->id);
|
||||
list($comment, $extraelements) = helper::get_preview_extra_elements($question, $this->context->instanceid);
|
||||
if (qbank::is_plugin_enabled('qbank_comment')) {
|
||||
$this->assertEquals("<div class='comment-area'>", $comment);
|
||||
$this->assertStringContainsString("comment-area", $comment);
|
||||
} else {
|
||||
$this->assertEquals('', $comment);
|
||||
}
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$version = 2021100600.00; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
$version = 2021100600.01; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
// RR = release increments - 00 in DEV branches.
|
||||
// .XX = incremental changes.
|
||||
$release = '4.0dev+ (Build: 20211006)'; // Human-friendly version name
|
||||
|
Loading…
x
Reference in New Issue
Block a user