mirror of
https://github.com/moodle/moodle.git
synced 2025-03-14 20:50:21 +01:00
MDL-61864 tool_policy: user agreement reports
This commit is contained in:
parent
3d9571d5f0
commit
cf398020d5
65
admin/tool/policy/accept.php
Normal file
65
admin/tool/policy/accept.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Accept policies on behalf of users (non-JS version)
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require(__DIR__.'/../../../config.php');
|
||||
require_once($CFG->dirroot.'/user/editlib.php');
|
||||
|
||||
$userids = optional_param_array('userids', null, PARAM_INT);
|
||||
$versionids = optional_param_array('versionids', null, PARAM_INT);
|
||||
$returnurl = optional_param('returnurl', null, PARAM_LOCALURL);
|
||||
|
||||
require_login();
|
||||
if (isguestuser()) {
|
||||
print_error('noguest');
|
||||
}
|
||||
$context = context_system::instance();
|
||||
|
||||
$PAGE->set_context($context);
|
||||
$PAGE->set_url(new moodle_url('/admin/tool/policy/accept.php'));
|
||||
|
||||
if ($returnurl) {
|
||||
$returnurl = new moodle_url($returnurl);
|
||||
} else if (count($userids) == 1) {
|
||||
$userid = reset($userids);
|
||||
$returnurl = new moodle_url('/admin/tool/policy/user.php', ['userid' => $userid]);
|
||||
} else {
|
||||
$returnurl = new moodle_url('/admin/tool/policy/acceptances.php');
|
||||
}
|
||||
// Initialise the form, this will also validate users, versions and check permission to accept policies.
|
||||
$form = new \tool_policy\form\accept_policy(null,
|
||||
['versionids' => $versionids, 'userids' => $userids, 'showbuttons' => true]);
|
||||
$form->set_data(['returnurl' => $returnurl]);
|
||||
|
||||
if ($form->is_cancelled()) {
|
||||
redirect($returnurl);
|
||||
} else if ($form->get_data()) {
|
||||
$form->process();
|
||||
redirect($returnurl);
|
||||
}
|
||||
|
||||
$output = $PAGE->get_renderer('tool_policy');
|
||||
echo $output->header();
|
||||
echo $output->heading(get_string('consentdetails', 'tool_policy'));
|
||||
$form->display();
|
||||
echo $output->footer();
|
65
admin/tool/policy/acceptances.php
Normal file
65
admin/tool/policy/acceptances.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* View user acceptances to the policies
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require(__DIR__.'/../../../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
|
||||
use core\output\notification;
|
||||
|
||||
$policyid = optional_param('policyid', null, PARAM_INT);
|
||||
$versionid = optional_param('versionid', null, PARAM_INT);
|
||||
$versionid = optional_param('versionid', null, PARAM_INT);
|
||||
$filtersapplied = optional_param_array('unified-filters', [], PARAM_NOTAGS);
|
||||
|
||||
$acceptancesfilter = new \tool_policy\output\acceptances_filter($policyid, $versionid, $filtersapplied);
|
||||
$policyid = $acceptancesfilter->get_policy_id_filter();
|
||||
$versionid = $acceptancesfilter->get_version_id_filter();
|
||||
|
||||
// Set up the page as an admin page 'tool_policy_managedocs'.
|
||||
$urlparams = ($policyid ? ['policyid' => $policyid] : []) + ($versionid ? ['versionid' => $versionid] : []);
|
||||
admin_externalpage_setup('tool_policy_acceptances', '', $urlparams,
|
||||
new moodle_url('/admin/tool/policy/acceptances.php'));
|
||||
|
||||
$acceptancesfilter->validate_ids();
|
||||
$output = $PAGE->get_renderer('tool_policy');
|
||||
if ($acceptancesfilter->get_versions()) {
|
||||
$acceptances = new \tool_policy\acceptances_table('tool_policy_user_acceptances', $acceptancesfilter, $output);
|
||||
if ($acceptances->is_downloading()) {
|
||||
$acceptances->download();
|
||||
}
|
||||
}
|
||||
|
||||
echo $output->header();
|
||||
echo $output->heading(get_string('useracceptances', 'tool_policy'));
|
||||
echo $output->render($acceptancesfilter);
|
||||
if (!empty($acceptances)) {
|
||||
$acceptances->display();
|
||||
} else if ($acceptancesfilter->get_avaliable_policies()) {
|
||||
// There are no non-guest policies.
|
||||
echo $output->notification(get_string('selectpolicyandversion', 'tool_policy'), notification::NOTIFY_INFO);
|
||||
} else {
|
||||
// There are no non-guest policies.
|
||||
echo $output->notification(get_string('nopolicies', 'tool_policy'), notification::NOTIFY_INFO);
|
||||
}
|
||||
echo $output->footer();
|
1
admin/tool/policy/amd/build/acceptances_filter.min.js
vendored
Normal file
1
admin/tool/policy/amd/build/acceptances_filter.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
define(["jquery","core/form-autocomplete","core/str","core/notification"],function(a,b,c,d){var e={UNIFIED_FILTERS:"#unified-filters"},f=function(){var f=[{key:"filterplaceholder",component:"tool_policy"},{key:"nofiltersapplied",component:"tool_policy"}];M.util.js_pending("acceptances_filter_datasource"),c.get_strings(f).done(function(a){var c=a[0],f=a[1];b.enhance(e.UNIFIED_FILTERS,!0,"tool_policy/acceptances_filter_datasource",c,!1,!0,f,!0).then(function(){M.util.js_complete("acceptances_filter_datasource")}).fail(d.exception)}).fail(d.exception);var g=a(e.UNIFIED_FILTERS).val();a(e.UNIFIED_FILTERS).on("change",function(){var b=a(this).val(),c=[],d=[],e=!1;if(a.each(b,function(a,b){var f=b.split(":",2);if(2!==f.length)return d.push(b),!0;var g=f[0],h=f[1];return"undefined"!=typeof c[g]&&(e=!0),c[g]=h,!0}),e){var f=[];for(var h in c)f.push(h+":"+c[h]);f=f.concat(d),a(this).val(f)}g.join(",")!=b.join(",")&&this.form.submit()})},g=function(){return a(e.UNIFIED_FILTERS).closest("form")};return{init:function(){f()},getForm:function(){return g()}}});
|
1
admin/tool/policy/amd/build/acceptances_filter_datasource.min.js
vendored
Normal file
1
admin/tool/policy/amd/build/acceptances_filter_datasource.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
define(["jquery","core/ajax","core/notification"],function(a,b,c){return{list:function(b,c){var d=[],e=a(b),f=a(b).data("originaloptionsjson"),g=e.val();a.each(f,function(b,e){return""!==a.trim(c)&&e.label.toLocaleLowerCase().indexOf(c.toLocaleLowerCase())===-1||(a.inArray(e.value,g)>-1||(d.push(e),!0))});var h=new a.Deferred;return h.resolve(d),h.promise()},processResults:function(b,c){var d=[];return a.each(c,function(a,b){d.push({value:b.value,label:b.label})}),d},transport:function(a,b,d){this.list(a,b).then(d)["catch"](c.exception)}}});
|
1
admin/tool/policy/amd/build/acceptmodal.min.js
vendored
Normal file
1
admin/tool/policy/amd/build/acceptmodal.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
define(["jquery","core/str","core/modal_factory","core/modal_events","core/notification","core/fragment","core/ajax","core/yui"],function(a,b,c,d,e,f,g,h){"use strict";var i=function(a){this.contextid=a,this.init()};return i.prototype.modal=null,i.prototype.contextid=-1,i.prototype.stringKeys=[{key:"consentdetails",component:"tool_policy"},{key:"iagreetothepolicy",component:"tool_policy"},{key:"selectusersforconsent",component:"tool_policy"},{key:"ok"}],i.prototype.init=function(){var c=a("a[data-action=acceptmodal]");c.on("click",function(b){b.preventDefault();var c=a(b.currentTarget).attr("href"),d=c.slice(c.indexOf("?")+1);this.showFormModal(d)}.bind(this)),c=a("form[data-action=acceptmodal]"),c.on("submit",function(d){if(d.preventDefault(),a(d.currentTarget).find('input[type=checkbox][name="userids[]"]:checked').length){var f=a(d.currentTarget).serialize();this.showFormModal(f,c)}else b.get_strings(this.stringKeys).done(function(a){e.alert("",a[2],a[3])})}.bind(this))},i.prototype.showFormModal=function(a,d){b.get_strings(this.stringKeys).done(function(b){c.create({type:c.types.SAVE_CANCEL,title:b[0],body:""},d).done(function(c){this.modal=c,this.setupFormModal(a,b[1])}.bind(this))}.bind(this)).fail(e.exception)},i.prototype.setupFormModal=function(a,b){var c=this.modal;c.setLarge(),c.setSaveButtonText(b),c.getRoot().on(d.hidden,this.destroy.bind(this)),c.setBody(this.getBody(a)),c.getRoot().on(d.save,this.submitForm.bind(this)),c.getRoot().on("submit","form",this.submitFormAjax.bind(this)),c.show()},i.prototype.getBody=function(a){"undefined"==typeof a&&(a={});var b={jsonformdata:JSON.stringify(a)};return f.loadFragment("tool_policy","accept_on_behalf",this.contextid,b)},i.prototype.submitFormAjax=function(a){a.preventDefault();var b=this.modal.getRoot().find("form").serialize(),c=g.call([{methodname:"tool_policy_submit_accept_on_behalf",args:{jsonformdata:JSON.stringify(b)}}]);c[0].done(function(a){a.validationerrors?this.modal.setBody(this.getBody(b)):this.close()}.bind(this)).fail(e.exception)},i.prototype.submitForm=function(a){a.preventDefault(),this.modal.getRoot().find("form").submit()},i.prototype.close=function(){this.destroy(),document.location.reload()},i.prototype.destroy=function(){h.use("moodle-core-formchangechecker",function(){M.core_formchangechecker.reset_form_dirty_state()}),this.modal.destroy()},{getInstance:function(a){new i(a)}}});
|
144
admin/tool/policy/amd/src/acceptances_filter.js
Normal file
144
admin/tool/policy/amd/src/acceptances_filter.js
Normal file
@ -0,0 +1,144 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* Unified filter page JS module for the course participants page.
|
||||
*
|
||||
* @module tool_policy/acceptances_filter
|
||||
* @package tool_policy
|
||||
* @copyright 2017 Jun Pataleta
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery', 'core/form-autocomplete', 'core/str', 'core/notification'],
|
||||
function($, Autocomplete, Str, Notification) {
|
||||
|
||||
/**
|
||||
* Selectors.
|
||||
*
|
||||
* @access private
|
||||
* @type {{UNIFIED_FILTERS: string}}
|
||||
*/
|
||||
var SELECTORS = {
|
||||
UNIFIED_FILTERS: '#unified-filters'
|
||||
};
|
||||
|
||||
/**
|
||||
* Init function.
|
||||
*
|
||||
* @method init
|
||||
* @private
|
||||
*/
|
||||
var init = function() {
|
||||
var stringkeys = [{
|
||||
key: 'filterplaceholder',
|
||||
component: 'tool_policy'
|
||||
}, {
|
||||
key: 'nofiltersapplied',
|
||||
component: 'tool_policy'
|
||||
}];
|
||||
|
||||
M.util.js_pending('acceptances_filter_datasource');
|
||||
Str.get_strings(stringkeys).done(function(langstrings) {
|
||||
var placeholder = langstrings[0];
|
||||
var noSelectionString = langstrings[1];
|
||||
Autocomplete.enhance(SELECTORS.UNIFIED_FILTERS, true, 'tool_policy/acceptances_filter_datasource', placeholder,
|
||||
false, true, noSelectionString, true)
|
||||
.then(function() {
|
||||
M.util.js_complete('acceptances_filter_datasource');
|
||||
|
||||
return;
|
||||
})
|
||||
.fail(Notification.exception);
|
||||
}).fail(Notification.exception);
|
||||
|
||||
var last = $(SELECTORS.UNIFIED_FILTERS).val();
|
||||
$(SELECTORS.UNIFIED_FILTERS).on('change', function() {
|
||||
var current = $(this).val();
|
||||
var listoffilters = [];
|
||||
var textfilters = [];
|
||||
var updatedselectedfilters = false;
|
||||
|
||||
$.each(current, function(index, catoption) {
|
||||
var catandoption = catoption.split(':', 2);
|
||||
if (catandoption.length !== 2) {
|
||||
textfilters.push(catoption);
|
||||
return true; // Text search filter.
|
||||
}
|
||||
|
||||
var category = catandoption[0];
|
||||
var option = catandoption[1];
|
||||
|
||||
// The last option (eg. 'Teacher') out of a category (eg. 'Role') in this loop is the one that was last
|
||||
// selected, so we want to use that if there are multiple options from the same category. Eg. The user
|
||||
// may have chosen to filter by the 'Student' role, then wanted to filter by the 'Teacher' role - the
|
||||
// last option in the category to be selected (in this case 'Teacher') will come last, so will overwrite
|
||||
// 'Student' (after this if). We want to let the JS know that the filters have been updated.
|
||||
if (typeof listoffilters[category] !== 'undefined') {
|
||||
updatedselectedfilters = true;
|
||||
}
|
||||
|
||||
listoffilters[category] = option;
|
||||
return true;
|
||||
});
|
||||
|
||||
// Check if we have something to remove from the list of filters.
|
||||
if (updatedselectedfilters) {
|
||||
// Go through and put the list into something we can use to update the list of filters.
|
||||
var updatefilters = [];
|
||||
for (var category in listoffilters) {
|
||||
updatefilters.push(category + ":" + listoffilters[category]);
|
||||
}
|
||||
updatefilters = updatefilters.concat(textfilters);
|
||||
$(this).val(updatefilters);
|
||||
}
|
||||
|
||||
// Prevent form from submitting unnecessarily, eg. on blur when no filter is selected.
|
||||
if (last.join(',') != current.join(',')) {
|
||||
this.form.submit();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the unified user filter form.
|
||||
*
|
||||
* @method getForm
|
||||
* @return {DOMElement}
|
||||
*/
|
||||
var getForm = function() {
|
||||
return $(SELECTORS.UNIFIED_FILTERS).closest('form');
|
||||
};
|
||||
|
||||
return /** @alias module:core/form-autocomplete */ {
|
||||
/**
|
||||
* Initialise the unified user filter.
|
||||
*
|
||||
* @method init
|
||||
*/
|
||||
init: function() {
|
||||
init();
|
||||
},
|
||||
|
||||
/**
|
||||
* Return the unified user filter form.
|
||||
*
|
||||
* @method getForm
|
||||
* @return {DOMElement}
|
||||
*/
|
||||
getForm: function() {
|
||||
return getForm();
|
||||
}
|
||||
};
|
||||
});
|
93
admin/tool/policy/amd/src/acceptances_filter_datasource.js
Normal file
93
admin/tool/policy/amd/src/acceptances_filter_datasource.js
Normal file
@ -0,0 +1,93 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* Datasource for the tool_policy/acceptances_filter.
|
||||
*
|
||||
* This module is compatible with core/form-autocomplete.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2017 Jun Pataleta
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define(['jquery', 'core/ajax', 'core/notification'], function($, Ajax, Notification) {
|
||||
|
||||
return /** @alias module:tool_policy/acceptances_filter_datasource */ {
|
||||
/**
|
||||
* List filter options.
|
||||
*
|
||||
* @param {String} selector The select element selector.
|
||||
* @param {String} query The query string.
|
||||
* @return {Promise}
|
||||
*/
|
||||
list: function(selector, query) {
|
||||
var filteredOptions = [];
|
||||
|
||||
var el = $(selector);
|
||||
var originalOptions = $(selector).data('originaloptionsjson');
|
||||
var selectedFilters = el.val();
|
||||
$.each(originalOptions, function(index, option) {
|
||||
// Skip option if it does not contain the query string.
|
||||
if ($.trim(query) !== '' && option.label.toLocaleLowerCase().indexOf(query.toLocaleLowerCase()) === -1) {
|
||||
return true;
|
||||
}
|
||||
// Skip filters that have already been selected.
|
||||
if ($.inArray(option.value, selectedFilters) > -1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
filteredOptions.push(option);
|
||||
return true;
|
||||
});
|
||||
|
||||
var deferred = new $.Deferred();
|
||||
deferred.resolve(filteredOptions);
|
||||
|
||||
return deferred.promise();
|
||||
},
|
||||
|
||||
/**
|
||||
* Process the results for auto complete elements.
|
||||
*
|
||||
* @param {String} selector The selector of the auto complete element.
|
||||
* @param {Array} results An array or results.
|
||||
* @return {Array} New array of results.
|
||||
*/
|
||||
processResults: function(selector, results) {
|
||||
var options = [];
|
||||
$.each(results, function(index, data) {
|
||||
options.push({
|
||||
value: data.value,
|
||||
label: data.label
|
||||
});
|
||||
});
|
||||
return options;
|
||||
},
|
||||
|
||||
/**
|
||||
* Source of data for Ajax element.
|
||||
*
|
||||
* @param {String} selector The selector of the auto complete element.
|
||||
* @param {String} query The query string.
|
||||
* @param {Function} callback A callback function receiving an array of results.
|
||||
*/
|
||||
/* eslint-disable promise/no-callback-in-promise */
|
||||
transport: function(selector, query, callback) {
|
||||
this.list(selector, query).then(callback).catch(Notification.exception);
|
||||
}
|
||||
};
|
||||
|
||||
});
|
244
admin/tool/policy/amd/src/acceptmodal.js
Normal file
244
admin/tool/policy/amd/src/acceptmodal.js
Normal file
@ -0,0 +1,244 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* Add policy consent modal to the page
|
||||
*
|
||||
* @module tool_policy/acceptmodal
|
||||
* @class AcceptOnBehalf
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery', 'core/str', 'core/modal_factory', 'core/modal_events', 'core/notification', 'core/fragment',
|
||||
'core/ajax', 'core/yui'],
|
||||
function($, Str, ModalFactory, ModalEvents, Notification, Fragment, Ajax, Y) {
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param {int} contextid
|
||||
*
|
||||
* Each call to init gets it's own instance of this class.
|
||||
*/
|
||||
var AcceptOnBehalf = function(contextid) {
|
||||
this.contextid = contextid;
|
||||
this.init();
|
||||
};
|
||||
|
||||
/**
|
||||
* @var {Modal} modal
|
||||
* @private
|
||||
*/
|
||||
AcceptOnBehalf.prototype.modal = null;
|
||||
|
||||
/**
|
||||
* @var {int} contextid
|
||||
* @private
|
||||
*/
|
||||
AcceptOnBehalf.prototype.contextid = -1;
|
||||
|
||||
/**
|
||||
* @var {Array} strings
|
||||
* @private
|
||||
*/
|
||||
AcceptOnBehalf.prototype.stringKeys = [
|
||||
{
|
||||
key: 'consentdetails',
|
||||
component: 'tool_policy'
|
||||
},
|
||||
{
|
||||
key: 'iagreetothepolicy',
|
||||
component: 'tool_policy'
|
||||
},
|
||||
{
|
||||
key: 'selectusersforconsent',
|
||||
component: 'tool_policy'
|
||||
},
|
||||
{
|
||||
key: 'ok'
|
||||
}
|
||||
];
|
||||
|
||||
/**
|
||||
* Initialise the class.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
AcceptOnBehalf.prototype.init = function() {
|
||||
// Initialise for links accepting policies for individual users.
|
||||
var triggers = $('a[data-action=acceptmodal]');
|
||||
triggers.on('click', function(e) {
|
||||
e.preventDefault();
|
||||
var href = $(e.currentTarget).attr('href'),
|
||||
formData = href.slice(href.indexOf('?') + 1);
|
||||
this.showFormModal(formData);
|
||||
}.bind(this));
|
||||
|
||||
// Initialise for multiple users acceptance form.
|
||||
triggers = $('form[data-action=acceptmodal]');
|
||||
triggers.on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
if ($(e.currentTarget).find('input[type=checkbox][name="userids[]"]:checked').length) {
|
||||
var formData = $(e.currentTarget).serialize();
|
||||
this.showFormModal(formData, triggers);
|
||||
} else {
|
||||
Str.get_strings(this.stringKeys).done(function (strings) {
|
||||
Notification.alert('', strings[2], strings[3]);
|
||||
});
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Show modal with a form
|
||||
*
|
||||
* @param {String} formData
|
||||
* @param {object} triggerElement The trigger HTML jQuery object
|
||||
*/
|
||||
AcceptOnBehalf.prototype.showFormModal = function(formData, triggerElement) {
|
||||
// Fetch the title string.
|
||||
Str.get_strings(this.stringKeys).done(function(strings) {
|
||||
// Create the modal.
|
||||
ModalFactory.create({
|
||||
type: ModalFactory.types.SAVE_CANCEL,
|
||||
title: strings[0],
|
||||
body: ''
|
||||
}, triggerElement).done(function(modal) {
|
||||
this.modal = modal;
|
||||
this.setupFormModal(formData, strings[1]);
|
||||
}.bind(this));
|
||||
}.bind(this))
|
||||
.fail(Notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Setup form inside a modal
|
||||
*
|
||||
* @param {String} formData
|
||||
* @param {String} saveText
|
||||
*/
|
||||
AcceptOnBehalf.prototype.setupFormModal = function(formData, saveText) {
|
||||
var modal = this.modal;
|
||||
|
||||
modal.setLarge();
|
||||
|
||||
modal.setSaveButtonText(saveText);
|
||||
|
||||
// We want to reset the form every time it is opened.
|
||||
modal.getRoot().on(ModalEvents.hidden, this.destroy.bind(this));
|
||||
|
||||
modal.setBody(this.getBody(formData));
|
||||
|
||||
// We catch the modal save event, and use it to submit the form inside the modal.
|
||||
// Triggering a form submission will give JS validation scripts a chance to check for errors.
|
||||
modal.getRoot().on(ModalEvents.save, this.submitForm.bind(this));
|
||||
// We also catch the form submit event and use it to submit the form with ajax.
|
||||
modal.getRoot().on('submit', 'form', this.submitFormAjax.bind(this));
|
||||
|
||||
modal.show();
|
||||
};
|
||||
|
||||
/**
|
||||
* Load the body of the modal (contains the form)
|
||||
*
|
||||
* @method getBody
|
||||
* @private
|
||||
* @param {String} formData
|
||||
* @return {Promise}
|
||||
*/
|
||||
AcceptOnBehalf.prototype.getBody = function(formData) {
|
||||
if (typeof formData === "undefined") {
|
||||
formData = {};
|
||||
}
|
||||
// Get the content of the modal.
|
||||
var params = {jsonformdata: JSON.stringify(formData)};
|
||||
return Fragment.loadFragment('tool_policy', 'accept_on_behalf', this.contextid, params);
|
||||
};
|
||||
|
||||
/**
|
||||
* Submit the form inside the modal via AJAX request
|
||||
*
|
||||
* @method submitFormAjax
|
||||
* @private
|
||||
* @param {Event} e Form submission event.
|
||||
*/
|
||||
AcceptOnBehalf.prototype.submitFormAjax = function(e) {
|
||||
// We don't want to do a real form submission.
|
||||
e.preventDefault();
|
||||
|
||||
// Convert all the form elements values to a serialised string.
|
||||
var formData = this.modal.getRoot().find('form').serialize();
|
||||
|
||||
var requests = Ajax.call([{
|
||||
methodname: 'tool_policy_submit_accept_on_behalf',
|
||||
args: {jsonformdata: JSON.stringify(formData)}
|
||||
}]);
|
||||
requests[0].done(function(data) {
|
||||
if (data.validationerrors) {
|
||||
this.modal.setBody(this.getBody(formData));
|
||||
} else {
|
||||
this.close();
|
||||
}
|
||||
}.bind(this)).fail(Notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* This triggers a form submission, so that any mform elements can do final tricks before the form submission is processed.
|
||||
*
|
||||
* @method submitForm
|
||||
* @param {Event} e Form submission event.
|
||||
* @private
|
||||
*/
|
||||
AcceptOnBehalf.prototype.submitForm = function(e) {
|
||||
e.preventDefault();
|
||||
this.modal.getRoot().find('form').submit();
|
||||
};
|
||||
|
||||
/**
|
||||
* Close the modal
|
||||
*/
|
||||
AcceptOnBehalf.prototype.close = function() {
|
||||
this.destroy();
|
||||
document.location.reload();
|
||||
};
|
||||
|
||||
/**
|
||||
* Destroy the modal
|
||||
*/
|
||||
AcceptOnBehalf.prototype.destroy = function() {
|
||||
Y.use('moodle-core-formchangechecker', function() {
|
||||
M.core_formchangechecker.reset_form_dirty_state();
|
||||
});
|
||||
this.modal.destroy();
|
||||
};
|
||||
|
||||
return /** @alias module:tool_policy/acceptmodal */ {
|
||||
// Public variables and functions.
|
||||
/**
|
||||
* Attach event listeners to initialise this module.
|
||||
*
|
||||
* @method init
|
||||
* @param {string} selector The CSS selector used to find nodes that will trigger this module.
|
||||
* @param {int} contextid The contextid for the course.
|
||||
* @return {Promise}
|
||||
*/
|
||||
getInstance: function(contextid) {
|
||||
new AcceptOnBehalf(contextid);
|
||||
}
|
||||
};
|
||||
});
|
648
admin/tool/policy/classes/acceptances_table.php
Normal file
648
admin/tool/policy/classes/acceptances_table.php
Normal file
@ -0,0 +1,648 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* View user acceptances to the policies
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_policy;
|
||||
|
||||
use tool_policy\output\acceptances_filter;
|
||||
use tool_policy\output\renderer;
|
||||
use tool_policy\output\user_agreement;
|
||||
use core_user;
|
||||
use stdClass;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once($CFG->dirroot.'/lib/tablelib.php');
|
||||
|
||||
/**
|
||||
* Class acceptances_table
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class acceptances_table extends \table_sql {
|
||||
|
||||
/** @var array */
|
||||
protected $versionids;
|
||||
|
||||
/** @var acceptances_filter */
|
||||
protected $acceptancesfilter;
|
||||
|
||||
/** @var renderer */
|
||||
protected $output;
|
||||
|
||||
/**
|
||||
* @var string[] The list of countries.
|
||||
*/
|
||||
protected $countries;
|
||||
|
||||
/** @var bool are there any users that this user can agree on behalf of */
|
||||
protected $canagreeany = false;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $uniqueid Table identifier.
|
||||
* @param acceptances_filter $acceptancesfilter
|
||||
* @param renderer $output
|
||||
*/
|
||||
public function __construct($uniqueid, acceptances_filter $acceptancesfilter, renderer $output) {
|
||||
global $CFG;
|
||||
parent::__construct($uniqueid);
|
||||
$this->set_attribute('id', 'acceptancetable');
|
||||
$this->acceptancesfilter = $acceptancesfilter;
|
||||
$this->is_downloading(optional_param('download', 0, PARAM_ALPHA), 'user_acceptances');
|
||||
$this->baseurl = $acceptancesfilter->get_url();
|
||||
$this->output = $output;
|
||||
|
||||
$this->versionids = [];
|
||||
$versions = $acceptancesfilter->get_versions();
|
||||
if (count($versions) > 1) {
|
||||
foreach ($versions as $version) {
|
||||
$this->versionids[$version->id] = $version->name;
|
||||
}
|
||||
} else {
|
||||
$version = reset($versions);
|
||||
$this->versionids[$version->id] = $version->name;
|
||||
if ($version->status != policy_version::STATUS_ACTIVE) {
|
||||
$this->versionids[$version->id] .= '<br>' . $version->revision;
|
||||
}
|
||||
}
|
||||
|
||||
$extrafields = get_extra_user_fields(\context_system::instance());
|
||||
$userfields = \user_picture::fields('u', $extrafields);
|
||||
|
||||
$this->set_sql("$userfields",
|
||||
"{user} u",
|
||||
'u.id <> :siteguestid AND u.deleted = 0',
|
||||
['siteguestid' => $CFG->siteguest]);
|
||||
if (!$this->is_downloading()) {
|
||||
$this->add_column_header('select', get_string('select'), false, 'colselect');
|
||||
}
|
||||
$this->add_column_header('fullname', get_string('fullnameuser', 'core'));
|
||||
foreach ($extrafields as $field) {
|
||||
$this->add_column_header($field, get_user_field_name($field));
|
||||
}
|
||||
|
||||
if (!$this->is_downloading() && !has_capability('tool/policy:acceptbehalf', \context_system::instance())) {
|
||||
// We will need to check capability to accept on behalf in each user's context, preload users contexts.
|
||||
$this->sql->fields .= ',' . \context_helper::get_preload_record_columns_sql('ctx');
|
||||
$this->sql->from .= ' JOIN {context} ctx ON ctx.contextlevel = :usercontextlevel AND ctx.instanceid = u.id';
|
||||
$this->sql->params['usercontextlevel'] = CONTEXT_USER;
|
||||
}
|
||||
|
||||
if ($this->acceptancesfilter->get_single_version()) {
|
||||
$this->configure_for_single_version();
|
||||
} else {
|
||||
$this->configure_for_multiple_versions();
|
||||
}
|
||||
|
||||
$this->build_sql_for_search_string($extrafields);
|
||||
$this->build_sql_for_capability_filter();
|
||||
$this->build_sql_for_roles_filter();
|
||||
|
||||
$this->sortable(true, 'firstname');
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove randomness from the list by always sorting by user id in the end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_sort_columns() {
|
||||
$c = parent::get_sort_columns();
|
||||
$c['u.id'] = SORT_ASC;
|
||||
return $c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to add only one column name and header to the table (parent class methods only allow to set all).
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $label
|
||||
* @param bool $sortable
|
||||
* @param string $columnclass
|
||||
*/
|
||||
protected function add_column_header($key, $label, $sortable = true, $columnclass = '') {
|
||||
if (empty($this->columns)) {
|
||||
$this->define_columns([$key]);
|
||||
$this->define_headers([$label]);
|
||||
} else {
|
||||
$this->columns[$key] = count($this->columns);
|
||||
$this->column_style[$key] = array();
|
||||
$this->column_class[$key] = $columnclass;
|
||||
$this->column_suppress[$key] = false;
|
||||
$this->headers[] = $label;
|
||||
}
|
||||
if ($columnclass !== null) {
|
||||
$this->column_class($key, $columnclass);
|
||||
}
|
||||
if (!$sortable) {
|
||||
$this->no_sorting($key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper configuration method.
|
||||
*/
|
||||
protected function configure_for_single_version() {
|
||||
$userfieldsmod = get_all_user_name_fields(true, 'm', null, 'mod');
|
||||
$v = key($this->versionids);
|
||||
$this->sql->fields .= ", $userfieldsmod, a{$v}.status AS status{$v}, a{$v}.note, ".
|
||||
"a{$v}.timemodified, a{$v}.usermodified AS usermodified{$v}";
|
||||
|
||||
$join = "JOIN {tool_policy_acceptances} a{$v} ON a{$v}.userid = u.id AND a{$v}.policyversionid=:versionid{$v}";
|
||||
$filterstatus = $this->acceptancesfilter->get_status_filter();
|
||||
if ($filterstatus == 1) {
|
||||
$this->sql->from .= " $join AND a{$v}.status=1";
|
||||
} else {
|
||||
$this->sql->from .= " LEFT $join";
|
||||
}
|
||||
|
||||
$this->sql->from .= " LEFT JOIN {user} m ON m.id = a{$v}.usermodified AND m.id <> u.id AND a{$v}.status = 1";
|
||||
|
||||
$this->sql->params['versionid' . $v] = $v;
|
||||
|
||||
if ($filterstatus === 0) {
|
||||
$this->sql->where .= " AND (a{$v}.status IS NULL OR a{$v}.status = 0)";
|
||||
}
|
||||
|
||||
$this->add_column_header('status' . $v, get_string('agreed', 'tool_policy'), true, 'mdl-align');
|
||||
$this->add_column_header('timemodified', get_string('agreedon', 'tool_policy'));
|
||||
$this->add_column_header('usermodified' . $v, get_string('agreedby', 'tool_policy'));
|
||||
$this->add_column_header('note', get_string('acceptancenote', 'tool_policy'), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper configuration method.
|
||||
*/
|
||||
protected function configure_for_multiple_versions() {
|
||||
$this->add_column_header('statusall', get_string('acceptancestatusoverall', 'tool_policy'));
|
||||
$filterstatus = $this->acceptancesfilter->get_status_filter();
|
||||
$statusall = [];
|
||||
foreach ($this->versionids as $v => $versionname) {
|
||||
$this->sql->fields .= ", a{$v}.status AS status{$v}, a{$v}.usermodified AS usermodified{$v}";
|
||||
$join = "JOIN {tool_policy_acceptances} a{$v} ON a{$v}.userid = u.id AND a{$v}.policyversionid=:versionid{$v}";
|
||||
if ($filterstatus == 1) {
|
||||
$this->sql->from .= " {$join} AND a{$v}.status=1";
|
||||
} else {
|
||||
$this->sql->from .= " LEFT {$join}";
|
||||
}
|
||||
$this->sql->params['versionid' . $v] = $v;
|
||||
$this->add_column_header('status' . $v, $versionname, true, 'mdl-align');
|
||||
$statusall[] = "COALESCE(a{$v}.status, 0)";
|
||||
}
|
||||
$this->sql->fields .= ",".join('+', $statusall)." AS statusall";
|
||||
|
||||
if ($filterstatus === 0) {
|
||||
$statussql = [];
|
||||
foreach ($this->versionids as $v => $versionname) {
|
||||
$statussql[] = "a{$v}.status IS NULL OR a{$v}.status = 0";
|
||||
}
|
||||
$this->sql->where .= " AND (u.policyagreed = 0 OR ".join(" OR ", $statussql).")";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Download the data.
|
||||
*/
|
||||
public function download() {
|
||||
\core\session\manager::write_close();
|
||||
$this->out(0, false);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get sql to add to where statement.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_sql_where() {
|
||||
list($where, $params) = parent::get_sql_where();
|
||||
$where = preg_replace('/firstname/', 'u.firstname', $where);
|
||||
$where = preg_replace('/lastname/', 'u.lastname', $where);
|
||||
return [$where, $params];
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper SQL query builder.
|
||||
*
|
||||
* @param array $userfields
|
||||
*/
|
||||
protected function build_sql_for_search_string($userfields) {
|
||||
global $DB, $USER;
|
||||
|
||||
$search = $this->acceptancesfilter->get_search_strings();
|
||||
if (empty($search)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$wheres = [];
|
||||
$params = [];
|
||||
foreach ($search as $index => $keyword) {
|
||||
$searchkey1 = 'search' . $index . '1';
|
||||
$searchkey2 = 'search' . $index . '2';
|
||||
$searchkey3 = 'search' . $index . '3';
|
||||
$searchkey4 = 'search' . $index . '4';
|
||||
$searchkey5 = 'search' . $index . '5';
|
||||
$searchkey6 = 'search' . $index . '6';
|
||||
$searchkey7 = 'search' . $index . '7';
|
||||
|
||||
$conditions = array();
|
||||
// Search by fullname.
|
||||
$fullname = $DB->sql_fullname('u.firstname', 'u.lastname');
|
||||
$conditions[] = $DB->sql_like($fullname, ':' . $searchkey1, false, false);
|
||||
|
||||
// Search by email.
|
||||
$email = $DB->sql_like('u.email', ':' . $searchkey2, false, false);
|
||||
if (!in_array('email', $userfields)) {
|
||||
$maildisplay = 'maildisplay' . $index;
|
||||
$userid1 = 'userid' . $index . '1';
|
||||
// Prevent users who hide their email address from being found by others
|
||||
// who aren't allowed to see hidden email addresses.
|
||||
$email = "(". $email ." AND (" .
|
||||
"u.maildisplay <> :$maildisplay " .
|
||||
"OR u.id = :$userid1". // User can always find himself.
|
||||
"))";
|
||||
$params[$maildisplay] = core_user::MAILDISPLAY_HIDE;
|
||||
$params[$userid1] = $USER->id;
|
||||
}
|
||||
$conditions[] = $email;
|
||||
|
||||
// Search by idnumber.
|
||||
$idnumber = $DB->sql_like('u.idnumber', ':' . $searchkey3, false, false);
|
||||
if (!in_array('idnumber', $userfields)) {
|
||||
$userid2 = 'userid' . $index . '2';
|
||||
// Users who aren't allowed to see idnumbers should at most find themselves
|
||||
// when searching for an idnumber.
|
||||
$idnumber = "(". $idnumber . " AND u.id = :$userid2)";
|
||||
$params[$userid2] = $USER->id;
|
||||
}
|
||||
$conditions[] = $idnumber;
|
||||
|
||||
// Search by middlename.
|
||||
$middlename = $DB->sql_like('u.middlename', ':' . $searchkey4, false, false);
|
||||
$conditions[] = $middlename;
|
||||
|
||||
// Search by alternatename.
|
||||
$alternatename = $DB->sql_like('u.alternatename', ':' . $searchkey5, false, false);
|
||||
$conditions[] = $alternatename;
|
||||
|
||||
// Search by firstnamephonetic.
|
||||
$firstnamephonetic = $DB->sql_like('u.firstnamephonetic', ':' . $searchkey6, false, false);
|
||||
$conditions[] = $firstnamephonetic;
|
||||
|
||||
// Search by lastnamephonetic.
|
||||
$lastnamephonetic = $DB->sql_like('u.lastnamephonetic', ':' . $searchkey7, false, false);
|
||||
$conditions[] = $lastnamephonetic;
|
||||
|
||||
$wheres[] = "(". implode(" OR ", $conditions) .") ";
|
||||
$params[$searchkey1] = "%$keyword%";
|
||||
$params[$searchkey2] = "%$keyword%";
|
||||
$params[$searchkey3] = "%$keyword%";
|
||||
$params[$searchkey4] = "%$keyword%";
|
||||
$params[$searchkey5] = "%$keyword%";
|
||||
$params[$searchkey6] = "%$keyword%";
|
||||
$params[$searchkey7] = "%$keyword%";
|
||||
}
|
||||
|
||||
$this->sql->where .= ' AND '.join(' AND ', $wheres);
|
||||
$this->sql->params += $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* If there is a filter to find users who can/cannot accept on their own behalf add it to the SQL query
|
||||
*/
|
||||
protected function build_sql_for_capability_filter() {
|
||||
global $CFG;
|
||||
$hascapability = $this->acceptancesfilter->get_capability_accept_filter();
|
||||
if ($hascapability === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
list($neededroles, $forbiddenroles) = get_roles_with_cap_in_context(\context_system::instance(), 'tool/policy:accept');
|
||||
|
||||
if (empty($neededroles)) {
|
||||
// There are no roles that allow to accept agreement on one own's behalf.
|
||||
$this->sql->where .= $hascapability ? ' AND 1=0' : '';
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($forbiddenroles)) {
|
||||
// There are no roles that prohibit to accept agreement on one own's behalf.
|
||||
$this->sql->where .= ' AND ' . $this->sql_has_role($neededroles, $hascapability);
|
||||
return;
|
||||
}
|
||||
|
||||
$defaultuserroleid = isset($CFG->defaultuserroleid) ? $CFG->defaultuserroleid : 0;
|
||||
if (!empty($neededroles[$defaultuserroleid])) {
|
||||
// Default role allows to accept agreement. Make sure user has/does not have one of the roles prohibiting it.
|
||||
$this->sql->where .= ' AND ' . $this->sql_has_role($forbiddenroles, !$hascapability);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($hascapability) {
|
||||
// User has at least one role allowing to accept and no roles prohibiting.
|
||||
$this->sql->where .= ' AND ' . $this->sql_has_role($neededroles);
|
||||
$this->sql->where .= ' AND ' . $this->sql_has_role($forbiddenroles, false);
|
||||
} else {
|
||||
// Option 1: User has one of the roles prohibiting to accept.
|
||||
$this->sql->where .= ' AND (' . $this->sql_has_role($forbiddenroles);
|
||||
// Option 2: User has none of the roles allowing to accept.
|
||||
$this->sql->where .= ' OR ' . $this->sql_has_role($neededroles, false) . ")";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns SQL snippet for users that have (do not have) one of the given roles in the system context
|
||||
*
|
||||
* @param array $roles list of roles indexed by role id
|
||||
* @param bool $positive true: return users who HAVE roles; false: return users who DO NOT HAVE roles
|
||||
* @return string
|
||||
*/
|
||||
protected function sql_has_role($roles, $positive = true) {
|
||||
global $CFG;
|
||||
if (empty($roles)) {
|
||||
return $positive ? '1=0' : '1=1';
|
||||
}
|
||||
$defaultuserroleid = isset($CFG->defaultuserroleid) ? $CFG->defaultuserroleid : 0;
|
||||
if (!empty($roles[$defaultuserroleid])) {
|
||||
// No need to query, everybody has the default role.
|
||||
return $positive ? '1=1' : '1=0';
|
||||
}
|
||||
return "u.id " . ($positive ? "" : "NOT") . " IN (
|
||||
SELECT userid
|
||||
FROM {role_assignments}
|
||||
WHERE contextid = " . SYSCONTEXTID . " AND roleid IN (" . implode(',', array_keys($roles)) . ")
|
||||
)";
|
||||
}
|
||||
|
||||
/**
|
||||
* If there is a filter by user roles add it to the SQL query.
|
||||
*/
|
||||
protected function build_sql_for_roles_filter() {
|
||||
foreach ($this->acceptancesfilter->get_role_filters() as $roleid) {
|
||||
$this->sql->where .= ' AND ' . $this->sql_has_role([$roleid => $roleid]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook that can be overridden in child classes to wrap a table in a form
|
||||
* for example. Called only when there is data to display and not
|
||||
* downloading.
|
||||
*/
|
||||
public function wrap_html_start() {
|
||||
echo \html_writer::start_tag('form',
|
||||
['action' => new \moodle_url('/admin/tool/policy/accept.php'), 'data-action' => 'acceptmodal']);
|
||||
echo \html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()]);
|
||||
echo \html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'returnurl',
|
||||
'value' => $this->get_return_url()]);
|
||||
foreach (array_keys($this->versionids) as $versionid) {
|
||||
echo \html_writer::empty_tag('input', ['type' => 'hidden', 'name' => "versionids[{$versionid}]",
|
||||
'value' => $versionid]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook that can be overridden in child classes to wrap a table in a form
|
||||
* for example. Called only when there is data to display and not
|
||||
* downloading.
|
||||
*/
|
||||
public function wrap_html_finish() {
|
||||
global $PAGE;
|
||||
if ($this->canagreeany) {
|
||||
echo \html_writer::empty_tag('input', ['type' => 'submit',
|
||||
'value' => get_string('consentbulk', 'tool_policy'), 'class' => 'btn btn-primary']);
|
||||
$PAGE->requires->js_call_amd('tool_policy/acceptmodal', 'getInstance', [\context_system::instance()->id]);
|
||||
}
|
||||
echo "</form>\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the table.
|
||||
*/
|
||||
public function display() {
|
||||
$this->out(100, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call appropriate methods on this table class to perform any processing on values before displaying in table.
|
||||
* Takes raw data from the database and process it into human readable format, perhaps also adding html linking when
|
||||
* displaying table as html, adding a div wrap, etc.
|
||||
*
|
||||
* See for example col_fullname below which will be called for a column whose name is 'fullname'.
|
||||
*
|
||||
* @param array|object $row row of data from db used to make one row of the table.
|
||||
* @return array one row for the table, added using add_data_keyed method.
|
||||
*/
|
||||
public function format_row($row) {
|
||||
\context_helper::preload_from_record($row);
|
||||
$row->canaccept = false;
|
||||
$row->user = \user_picture::unalias($row, [], $this->useridfield);
|
||||
$row->select = null;
|
||||
if (!$this->is_downloading()) {
|
||||
if (has_capability('tool/policy:acceptbehalf', \context_system::instance()) ||
|
||||
has_capability('tool/policy:acceptbehalf', \context_user::instance($row->id))) {
|
||||
$row->canaccept = true;
|
||||
$row->select = \html_writer::empty_tag('input',
|
||||
['type' => 'checkbox', 'name' => 'userids[]', 'value' => $row->id, 'class' => 'usercheckbox',
|
||||
'id' => 'selectuser' . $row->id]) .
|
||||
\html_writer::tag('label', get_string('selectuser', 'tool_policy', $this->username($row->user, false)),
|
||||
['for' => 'selectuser' . $row->id, 'class' => 'accesshide']);
|
||||
$this->canagreeany = true;
|
||||
}
|
||||
}
|
||||
return parent::format_row($row);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column fullname value.
|
||||
*
|
||||
* @param stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
public function col_fullname($row) {
|
||||
global $OUTPUT;
|
||||
$userpic = $this->is_downloading() ? '' : $OUTPUT->user_picture($row->user);
|
||||
return $userpic . $this->username($row->user, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* User name with a link to profile
|
||||
*
|
||||
* @param stdClass $user
|
||||
* @param bool $profilelink show link to profile (when we are downloading never show links)
|
||||
* @return string
|
||||
*/
|
||||
protected function username($user, $profilelink = true) {
|
||||
$canviewfullnames = has_capability('moodle/site:viewfullnames', \context_system::instance()) ||
|
||||
has_capability('moodle/site:viewfullnames', \context_user::instance($user->id));
|
||||
$name = fullname($user, $canviewfullnames);
|
||||
if (!$this->is_downloading() && $profilelink) {
|
||||
$profileurl = new \moodle_url('/user/profile.php', array('id' => $user->id));
|
||||
return \html_writer::link($profileurl, $name);
|
||||
}
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper.
|
||||
*/
|
||||
protected function get_return_url() {
|
||||
$pageurl = $this->baseurl;
|
||||
if ($this->currpage) {
|
||||
$pageurl = new \moodle_url($pageurl, [$this->request[TABLE_VAR_PAGE] => $this->currpage]);
|
||||
}
|
||||
return $pageurl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return agreement status
|
||||
*
|
||||
* @param int $versionid either id of an individual version or empty for overall status
|
||||
* @param stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
protected function status($versionid, $row) {
|
||||
$onbehalf = false;
|
||||
$versions = $versionid ? [$versionid => $this->versionids[$versionid]] : $this->versionids; // List of versions.
|
||||
$accepted = []; // List of versionids that user has accepted.
|
||||
|
||||
foreach ($versions as $v => $name) {
|
||||
if (!empty($row->{'status' . $v})) {
|
||||
$accepted[] = $v;
|
||||
$agreedby = $row->{'usermodified' . $v};
|
||||
if ($agreedby && $agreedby != $row->id) {
|
||||
$onbehalf = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($versionid) {
|
||||
$str = new \lang_string($accepted ? 'yes' : 'no');
|
||||
} else {
|
||||
$str = new \lang_string('acceptancecount', 'tool_policy', (object)[
|
||||
'agreedcount' => count($accepted),
|
||||
'policiescount' => count($versions)
|
||||
]);
|
||||
}
|
||||
|
||||
if ($this->is_downloading()) {
|
||||
return $str->out();
|
||||
} else {
|
||||
$s = $this->output->render(new user_agreement($row->id, $accepted, $this->get_return_url(),
|
||||
$versions, $onbehalf, $row->canaccept));
|
||||
if (!$versionid) {
|
||||
$s .= '<br>' . \html_writer::link(new \moodle_url('/admin/tool/policy/user.php',
|
||||
['userid' => $row->id, 'returnurl' => $this->get_return_url()]), $str);
|
||||
}
|
||||
return $s;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column timemodified value.
|
||||
*
|
||||
* @param stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
public function col_timemodified($row) {
|
||||
if ($row->timemodified) {
|
||||
if ($this->is_downloading()) {
|
||||
// Use timestamp format readable for both machines and humans.
|
||||
return date_format_string($row->timemodified, '%Y-%m-%d %H:%M:%S %Z');
|
||||
} else {
|
||||
// Use localised calendar format.
|
||||
return userdate($row->timemodified, get_string('strftimedatetime'));
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column note value.
|
||||
*
|
||||
* @param stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
public function col_note($row) {
|
||||
if ($this->is_downloading()) {
|
||||
return $row->note;
|
||||
} else {
|
||||
return format_text($row->note, FORMAT_MOODLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column statusall value.
|
||||
*
|
||||
* @param stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
public function col_statusall($row) {
|
||||
return $this->status(0, $row);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the country column.
|
||||
*
|
||||
* @param \stdClass $data
|
||||
* @return string
|
||||
*/
|
||||
public function col_country($data) {
|
||||
if ($data->country && $this->countries === null) {
|
||||
$this->countries = get_string_manager()->get_list_of_countries();
|
||||
}
|
||||
if (!empty($this->countries[$data->country])) {
|
||||
return $this->countries[$data->country];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* You can override this method in a child class. See the description of
|
||||
* build_table which calls this method.
|
||||
*
|
||||
* @param string $column
|
||||
* @param stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
public function other_cols($column, $row) {
|
||||
if (preg_match('/^status([\d]+)$/', $column, $matches)) {
|
||||
$versionid = $matches[1];
|
||||
return $this->status($versionid, $row);
|
||||
}
|
||||
if (preg_match('/^usermodified([\d]+)$/', $column, $matches)) {
|
||||
if ($row->$column && $row->$column != $row->id) {
|
||||
$user = (object)['id' => $row->$column];
|
||||
username_load_fields_from_object($user, $row, 'mod');
|
||||
return $this->username($user, true);
|
||||
}
|
||||
return ''; // User agreed by themselves.
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
117
admin/tool/policy/classes/event/acceptance_base.php
Normal file
117
admin/tool/policy/classes/event/acceptance_base.php
Normal file
@ -0,0 +1,117 @@
|
||||
<?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 {@link tool_policy\event\acceptance_base} class.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_policy\event;
|
||||
|
||||
use core\event\base;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Base class for acceptance_created and acceptance_updated events.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
abstract class acceptance_base extends base {
|
||||
|
||||
/**
|
||||
* Initialise the event.
|
||||
*/
|
||||
protected function init() {
|
||||
$this->data['objecttable'] = 'tool_policy_acceptances';
|
||||
$this->data['edulevel'] = self::LEVEL_OTHER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create event from record.
|
||||
*
|
||||
* @param stdClass $record
|
||||
* @return acceptance_created
|
||||
*/
|
||||
public static function create_from_record($record) {
|
||||
$event = static::create([
|
||||
'objectid' => $record->id,
|
||||
'relateduserid' => $record->userid,
|
||||
'context' => \context_user::instance($record->userid),
|
||||
'other' => [
|
||||
'policyversionid' => $record->policyversionid,
|
||||
'note' => $record->note,
|
||||
'status' => $record->status,
|
||||
],
|
||||
]);
|
||||
$event->add_record_snapshot($event->objecttable, $record);
|
||||
return $event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get URL related to the action.
|
||||
*
|
||||
* @return \moodle_url
|
||||
*/
|
||||
public function get_url() {
|
||||
return new \moodle_url('/admin/tool/policy/acceptance.php', array('userid' => $this->relateduserid,
|
||||
'versionid' => $this->other['policyversionid']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the object ID mapping.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_objectid_mapping() {
|
||||
return array('db' => 'tool_policy', 'restore' => \core\event\base::NOT_MAPPED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom validation.
|
||||
*
|
||||
* @throws \coding_exception
|
||||
*/
|
||||
protected function validate_data() {
|
||||
parent::validate_data();
|
||||
|
||||
if (empty($this->other['policyversionid'])) {
|
||||
throw new \coding_exception('The \'policyversionid\' value must be set');
|
||||
}
|
||||
|
||||
if (!isset($this->other['status'])) {
|
||||
throw new \coding_exception('The \'status\' value must be set');
|
||||
}
|
||||
|
||||
if (empty($this->relateduserid)) {
|
||||
throw new \coding_exception('The \'relateduserid\' must be set.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* No mapping required for this event because this event is not backed up.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function get_other_mapping() {
|
||||
return false;
|
||||
}
|
||||
}
|
73
admin/tool/policy/classes/event/acceptance_created.php
Normal file
73
admin/tool/policy/classes/event/acceptance_created.php
Normal file
@ -0,0 +1,73 @@
|
||||
<?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 {@link tool_policy\event\acceptance_created} class.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_policy\event;
|
||||
|
||||
use core\event\base;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Event acceptance_created
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class acceptance_created extends acceptance_base {
|
||||
|
||||
/**
|
||||
* Initialise the event.
|
||||
*/
|
||||
protected function init() {
|
||||
parent::init();
|
||||
$this->data['crud'] = 'c';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns event name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_name() {
|
||||
return get_string('event_acceptance_created', 'tool_policy');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the event description.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
if ($this->other['status'] == 1) {
|
||||
$action = 'added consent to';
|
||||
} else if ($this->other['status'] == -1) {
|
||||
$action = 'revoked consent to';
|
||||
} else {
|
||||
$action = 'created an empty consent record for';
|
||||
}
|
||||
return "The user with id '{$this->userid}' $action the policy with revision {$this->other['policyversionid']} ".
|
||||
"for the user with id '{$this->relateduserid}'";
|
||||
}
|
||||
}
|
73
admin/tool/policy/classes/event/acceptance_updated.php
Normal file
73
admin/tool/policy/classes/event/acceptance_updated.php
Normal file
@ -0,0 +1,73 @@
|
||||
<?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 {@link tool_policy\event\acceptance_updated} class.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_policy\event;
|
||||
|
||||
use core\event\base;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Event acceptance_updated
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class acceptance_updated extends acceptance_base {
|
||||
|
||||
/**
|
||||
* Initialise the event.
|
||||
*/
|
||||
protected function init() {
|
||||
parent::init();
|
||||
$this->data['crud'] = 'u';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns event name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_name() {
|
||||
return get_string('event_acceptance_updated', 'tool_policy');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the event description.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
if ($this->other['status'] == 1) {
|
||||
$action = 'added consent to';
|
||||
} else if ($this->other['status'] == -1) {
|
||||
$action = 'revoked consent to';
|
||||
} else {
|
||||
$action = 'updated consent to';
|
||||
}
|
||||
return "The user with id '{$this->userid}' $action the policy with revision {$this->other['policyversionid']} ".
|
||||
"for the user with id '{$this->relateduserid}'";
|
||||
}
|
||||
}
|
161
admin/tool/policy/classes/form/accept_policy.php
Normal file
161
admin/tool/policy/classes/form/accept_policy.php
Normal file
@ -0,0 +1,161 @@
|
||||
<?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 {@link tool_policy\form\accept_policy} class.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_policy\form;
|
||||
|
||||
use tool_policy\api;
|
||||
use tool_policy\policy_version;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->dirroot.'/lib/formslib.php');
|
||||
|
||||
/**
|
||||
* Represents the form for accepting a policy.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class accept_policy extends \moodleform {
|
||||
|
||||
/**
|
||||
* Defines the form fields.
|
||||
*/
|
||||
public function definition() {
|
||||
global $PAGE;
|
||||
$mform = $this->_form;
|
||||
|
||||
if (empty($this->_customdata['userids']) || !is_array($this->_customdata['userids'])) {
|
||||
throw new \moodle_exception('missingparam', 'error', '', 'userids');
|
||||
}
|
||||
if (empty($this->_customdata['versionids']) || !is_array($this->_customdata['versionids'])) {
|
||||
throw new \moodle_exception('missingparam', '', '', 'versionids');
|
||||
}
|
||||
$userids = clean_param_array($this->_customdata['userids'], PARAM_INT);
|
||||
$versionids = clean_param_array($this->_customdata['versionids'], PARAM_INT);
|
||||
$usernames = $this->validate_and_get_users($userids);
|
||||
$versionnames = $this->validate_and_get_versions($versionids);
|
||||
|
||||
foreach ($usernames as $userid => $name) {
|
||||
$mform->addElement('hidden', 'userids['.$userid.']', $userid);
|
||||
$mform->setType('userids['.$userid.']', PARAM_INT);
|
||||
}
|
||||
|
||||
foreach ($versionnames as $versionid => $name) {
|
||||
$mform->addElement('hidden', 'versionids['.$versionid.']', $versionid);
|
||||
$mform->setType('versionids['.$versionid.']', PARAM_INT);
|
||||
}
|
||||
|
||||
$mform->addElement('hidden', 'returnurl');
|
||||
$mform->setType('returnurl', PARAM_LOCALURL);
|
||||
|
||||
$mform->addElement('static', 'user', get_string('acceptanceusers', 'tool_policy'), join(', ', $usernames));
|
||||
$mform->addElement('static', 'policy', get_string('acceptancepolicies', 'tool_policy'),
|
||||
join(', ', $versionnames));
|
||||
|
||||
$mform->addElement('static', 'ack', '', get_string('acceptanceacknowledgement', 'tool_policy'));
|
||||
|
||||
$mform->addElement('textarea', 'note', get_string('acceptancenote', 'tool_policy'));
|
||||
$mform->setType('note', PARAM_NOTAGS);
|
||||
|
||||
if (!empty($this->_customdata['showbuttons'])) {
|
||||
$this->add_action_buttons(true, get_string('iagreetothepolicy', 'tool_policy'));
|
||||
}
|
||||
|
||||
$PAGE->requires->js_call_amd('tool_policy/policyactions', 'init');
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate userids and return usernames
|
||||
*
|
||||
* @param array $userids
|
||||
* @return array (userid=>username)
|
||||
*/
|
||||
protected function validate_and_get_users($userids) {
|
||||
global $DB, $USER;
|
||||
$usernames = [];
|
||||
list($sql, $params) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
|
||||
$params['usercontextlevel'] = CONTEXT_USER;
|
||||
$users = $DB->get_records_sql("SELECT u.id, " . get_all_user_name_fields(true, 'u') . ", " .
|
||||
\context_helper::get_preload_record_columns_sql('ctx') .
|
||||
" FROM {user} u JOIN {context} ctx ON ctx.contextlevel=:usercontextlevel AND ctx.instanceid = u.id
|
||||
WHERE u.id " . $sql, $params);
|
||||
|
||||
$acceptany = has_capability('tool/policy:acceptbehalf', \context_system::instance());
|
||||
foreach ($userids as $userid) {
|
||||
if (!isset($users[$userid])) {
|
||||
throw new \dml_missing_record_exception('user', 'id=?', [$userid]);
|
||||
}
|
||||
$user = $users[$userid];
|
||||
if (isguestuser($user)) {
|
||||
throw new \moodle_exception('noguest');
|
||||
}
|
||||
if ($userid == $USER->id) {
|
||||
require_capability('tool/policy:accept', \context_system::instance());
|
||||
} else if (!$acceptany) {
|
||||
\context_helper::preload_from_record($user);
|
||||
require_capability('tool/policy:acceptbehalf', \context_user::instance($userid));
|
||||
}
|
||||
$usernames[$userid] = fullname($user);
|
||||
}
|
||||
return $usernames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate versionids and return their names
|
||||
*
|
||||
* @param array $versionids
|
||||
* @return array (versionid=>name)
|
||||
*/
|
||||
protected function validate_and_get_versions($versionids) {
|
||||
$versionnames = [];
|
||||
$policies = api::list_policies();
|
||||
foreach ($versionids as $versionid) {
|
||||
$version = api::get_policy_version($versionid, $policies);
|
||||
if ($version->audience == policy_version::AUDIENCE_GUESTS) {
|
||||
throw new \moodle_exception('errorpolicyversionnotfound', 'tool_policy');
|
||||
}
|
||||
$url = new \moodle_url('/admin/tool/policy/view.php', ['versionid' => $version->id]);
|
||||
$policyname = $version->name;
|
||||
if ($version->status != policy_version::STATUS_ACTIVE) {
|
||||
$policyname .= ' ' . $version->revision;
|
||||
}
|
||||
$versionnames[$version->id] = \html_writer::link($url, $policyname,
|
||||
['data-action' => 'view', 'data-versionid' => $version->id]);
|
||||
}
|
||||
return $versionnames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process form submission
|
||||
*/
|
||||
public function process() {
|
||||
if ($data = $this->get_data()) {
|
||||
foreach ($data->userids as $userid) {
|
||||
\tool_policy\api::accept_policies($data->versionids, $userid, $data->note);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
132
admin/tool/policy/classes/output/acceptances.php
Normal file
132
admin/tool/policy/classes/output/acceptances.php
Normal file
@ -0,0 +1,132 @@
|
||||
<?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 {@link tool_policy\output\acceptances} class.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @category output
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_policy\output;
|
||||
|
||||
use tool_policy\api;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use moodle_url;
|
||||
use renderable;
|
||||
use renderer_base;
|
||||
use single_button;
|
||||
use templatable;
|
||||
use tool_policy\policy_version;
|
||||
|
||||
/**
|
||||
* List of users and their acceptances
|
||||
*
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class acceptances implements renderable, templatable {
|
||||
|
||||
/** @var id */
|
||||
protected $userid;
|
||||
|
||||
/** @var moodle_url */
|
||||
protected $returnurl;
|
||||
|
||||
/**
|
||||
* Contructor.
|
||||
*
|
||||
* @param int $userid
|
||||
*/
|
||||
public function __construct($userid, $returnurl = null) {
|
||||
$this->userid = $userid;
|
||||
$this->returnurl = $returnurl ? (new moodle_url($returnurl))->out(false) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the page data for the mustache template.
|
||||
*
|
||||
* @param renderer_base $output renderer to be used to render the page elements.
|
||||
* @return stdClass
|
||||
*/
|
||||
public function export_for_template(renderer_base $output) {
|
||||
$data = (object)[];
|
||||
$data->hasonbehalfagreements = false;
|
||||
$data->pluginbaseurl = (new moodle_url('/admin/tool/policy'))->out(false);
|
||||
$data->returnurl = $this->returnurl;
|
||||
|
||||
// Get the list of policies and versions that current user is able to see
|
||||
// and the respective acceptance records for the selected user.
|
||||
$policies = api::get_policies_with_acceptances($this->userid);
|
||||
|
||||
$canviewfullnames = has_capability('moodle/site:viewfullnames', \context_system::instance());
|
||||
foreach ($policies as $policy) {
|
||||
|
||||
foreach ($policy->versions as $version) {
|
||||
unset($version->summary);
|
||||
unset($version->content);
|
||||
$version->iscurrent = ($version->status == policy_version::STATUS_ACTIVE);
|
||||
$version->name = $version->name;
|
||||
$version->revision = $version->revision;
|
||||
$returnurl = new moodle_url('/admin/tool/policy/user.php', ['userid' => $this->userid]);
|
||||
$version->viewurl = (new moodle_url('/admin/tool/policy/view.php', [
|
||||
'policyid' => $policy->id,
|
||||
'versionid' => $version->id,
|
||||
'returnurl' => $returnurl->out(false),
|
||||
]))->out(false);
|
||||
|
||||
if (!empty($version->acceptance->status)) {
|
||||
$acceptance = $version->acceptance;
|
||||
$version->timeaccepted = userdate($acceptance->timemodified, get_string('strftimedatetime'));
|
||||
$onbehalf = $acceptance->usermodified && $acceptance->usermodified != $this->userid;
|
||||
$version->agreement = new user_agreement($this->userid, [$version->id], $returnurl,
|
||||
[$version->id => $version->name], $onbehalf);
|
||||
if ($onbehalf) {
|
||||
$usermodified = (object)['id' => $acceptance->usermodified];
|
||||
username_load_fields_from_object($usermodified, $acceptance, 'mod');
|
||||
$profileurl = new \moodle_url('/user/profile.php', array('id' => $usermodified->id));
|
||||
$version->acceptedby = \html_writer::link($profileurl, fullname($usermodified, $canviewfullnames ||
|
||||
has_capability('moodle/site:viewfullnames', \context_user::instance($acceptance->usermodified))));
|
||||
$data->hasonbehalfagreements = true;
|
||||
}
|
||||
$version->note = format_text($acceptance->note);
|
||||
} else if ($version->iscurrent) {
|
||||
$version->agreement = new user_agreement($this->userid, [], $returnurl, [$version->id => $version->name]);
|
||||
}
|
||||
if (isset($version->agreement)) {
|
||||
$version->agreement = $version->agreement->export_for_template($output);
|
||||
}
|
||||
}
|
||||
|
||||
if ($policy->versions[0]->status != policy_version::STATUS_ACTIVE) {
|
||||
// Add an empty "currentversion" on top.
|
||||
$policy->versions = [0 => (object)[]] + $policy->versions;
|
||||
}
|
||||
|
||||
$policy->versioncount = count($policy->versions);
|
||||
$policy->versions = array_values($policy->versions);
|
||||
$policy->versions[0]->isfirst = 1;
|
||||
$policy->versions[0]->hasarchived = (count($policy->versions) > 1);
|
||||
}
|
||||
|
||||
$data->policies = array_values($policies);
|
||||
return $data;
|
||||
}
|
||||
}
|
465
admin/tool/policy/classes/output/acceptances_filter.php
Normal file
465
admin/tool/policy/classes/output/acceptances_filter.php
Normal file
@ -0,0 +1,465 @@
|
||||
<?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 {@link tool_policy\output\acceptances_filter} class.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @category output
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_policy\output;
|
||||
|
||||
use tool_policy\api;
|
||||
use tool_policy\policy_version;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Implements the widget allowing to filter the acceptance records.
|
||||
*
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class acceptances_filter implements \templatable, \renderable {
|
||||
|
||||
/** @var array $filtersapplied The list of selected filter options. */
|
||||
protected $filtersapplied;
|
||||
|
||||
/** @var string $searchstring */
|
||||
protected $searchstrings;
|
||||
|
||||
/** @var array list of available versions */
|
||||
protected $versions = null;
|
||||
|
||||
/** @var array list of available roles for the filter */
|
||||
protected $roles;
|
||||
|
||||
/** @var array cached list of all available policies, to retrieve use {@link self::get_avaliable_policies()} */
|
||||
protected $policies;
|
||||
|
||||
/** @var int */
|
||||
const FILTER_SEARCH_STRING = 0;
|
||||
|
||||
/** @var int */
|
||||
const FILTER_POLICYID = 1;
|
||||
|
||||
/** @var int */
|
||||
const FILTER_VERSIONID = 2;
|
||||
|
||||
/** @var int */
|
||||
const FILTER_CAPABILITY_ACCEPT = 3;
|
||||
|
||||
/** @var int */
|
||||
const FILTER_STATUS = 4;
|
||||
|
||||
/** @var int */
|
||||
const FILTER_ROLE = 5;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $policyid Specified policy id
|
||||
* @param array $versionid Specified version id
|
||||
* @param array $filtersapplied The list of selected filter option values.
|
||||
*/
|
||||
public function __construct($policyid, $versionid, $filtersapplied) {
|
||||
$this->filtersapplied = [];
|
||||
$this->roles = get_assignable_roles(\context_system::instance());
|
||||
if ($policyid) {
|
||||
$this->add_filter(self::FILTER_POLICYID, $policyid);
|
||||
}
|
||||
if ($versionid) {
|
||||
$this->add_filter(self::FILTER_VERSIONID, $versionid);
|
||||
}
|
||||
foreach ($filtersapplied as $filter) {
|
||||
if (preg_match('/^([1-9]\d*):(\d+)$/', $filter, $parts)) {
|
||||
// This is a pre-set filter (policy, version, status, etc.).
|
||||
$allowmultiple = false;
|
||||
switch ((int)$parts[1]) {
|
||||
case self::FILTER_POLICYID:
|
||||
case self::FILTER_VERSIONID:
|
||||
$value = (int)$parts[2];
|
||||
break;
|
||||
case self::FILTER_CAPABILITY_ACCEPT:
|
||||
case self::FILTER_STATUS:
|
||||
$value = (int)(bool)$parts[2];
|
||||
break;
|
||||
case self::FILTER_ROLE:
|
||||
$value = (int)$parts[2];
|
||||
if (!array_key_exists($value, $this->roles)) {
|
||||
continue 2;
|
||||
}
|
||||
$allowmultiple = true;
|
||||
break;
|
||||
default:
|
||||
// Unrecognised filter.
|
||||
continue 2;
|
||||
}
|
||||
|
||||
$this->add_filter((int)$parts[1], $value, $allowmultiple);
|
||||
} else if (trim($filter) !== '') {
|
||||
// This is a search string.
|
||||
$this->add_filter(self::FILTER_SEARCH_STRING, trim($filter), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an applied filter
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $value
|
||||
* @param bool $allowmultiple
|
||||
*/
|
||||
protected function add_filter($key, $value, $allowmultiple = false) {
|
||||
if ($allowmultiple || empty($this->get_filter_values($key))) {
|
||||
$this->filtersapplied[] = [$key, $value];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is there a filter by policy
|
||||
*
|
||||
* @return null|int null if there is no filter, otherwise the policy id
|
||||
*/
|
||||
public function get_policy_id_filter() {
|
||||
return $this->get_filter_value(self::FILTER_POLICYID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is there a filter by version
|
||||
*
|
||||
* @return null|int null if there is no filter, otherwise the version id
|
||||
*/
|
||||
public function get_version_id_filter() {
|
||||
return $this->get_filter_value(self::FILTER_VERSIONID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Are there filters by search strings
|
||||
*
|
||||
* @return string[] array of string filters
|
||||
*/
|
||||
public function get_search_strings() {
|
||||
return $this->get_filter_values(self::FILTER_SEARCH_STRING);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is there a filter by status (agreed/not agreed).
|
||||
*
|
||||
* @return null|0|1 null if there is no filter, 0/1 if there is a filter by status
|
||||
*/
|
||||
public function get_status_filter() {
|
||||
return $this->get_filter_value(self::FILTER_STATUS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Are there filters by role
|
||||
*
|
||||
* @return array list of role ids
|
||||
*/
|
||||
public function get_role_filters() {
|
||||
return $this->get_filter_values(self::FILTER_ROLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is there a filter by capability (can accept/cannot accept).
|
||||
*
|
||||
* @return null|0|1 null if there is no filter, 0/1 if there is a filter by capability
|
||||
*/
|
||||
public function get_capability_accept_filter() {
|
||||
return $this->get_filter_value(self::FILTER_CAPABILITY_ACCEPT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all values of the applied filter
|
||||
*
|
||||
* @param string $filtername
|
||||
* @return array
|
||||
*/
|
||||
protected function get_filter_values($filtername) {
|
||||
$values = [];
|
||||
foreach ($this->filtersapplied as $filter) {
|
||||
if ($filter[0] == $filtername) {
|
||||
$values[] = $filter[1];
|
||||
}
|
||||
}
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get one value of the applied filter
|
||||
*
|
||||
* @param string $filtername
|
||||
* @param string $default
|
||||
* @return mixed
|
||||
*/
|
||||
protected function get_filter_value($filtername, $default = null) {
|
||||
if ($values = $this->get_filter_values($filtername)) {
|
||||
$value = reset($values);
|
||||
return $value;
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all policies that have versions with possible acceptances (excl. drafts and guest-only versions)
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public function get_avaliable_policies() {
|
||||
if ($this->policies === null) {
|
||||
$this->policies = [];
|
||||
foreach (\tool_policy\api::list_policies() as $policy) {
|
||||
// Make a list of all versions that are not draft and are not guest-only.
|
||||
$policy->versions = [];
|
||||
if ($policy->currentversion && $policy->currentversion->audience != policy_version::AUDIENCE_GUESTS) {
|
||||
$policy->versions[$policy->currentversion->id] = $policy->currentversion;
|
||||
} else {
|
||||
$policy->currentversion = null;
|
||||
}
|
||||
foreach ($policy->archivedversions as $version) {
|
||||
if ($version->audience != policy_version::AUDIENCE_GUESTS) {
|
||||
$policy->versions[$version->id] = $version;
|
||||
}
|
||||
}
|
||||
if ($policy->versions) {
|
||||
$this->policies[$policy->id] = $policy;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->policies;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of policies that match current filters
|
||||
*
|
||||
* @return array of versions to display indexed by versionid
|
||||
*/
|
||||
public function get_versions() {
|
||||
if ($this->versions === null) {
|
||||
$policyid = $this->get_policy_id_filter();
|
||||
$versionid = $this->get_version_id_filter();
|
||||
$this->versions = [];
|
||||
foreach ($this->get_avaliable_policies() as $policy) {
|
||||
if ($policyid && $policy->id != $policyid) {
|
||||
continue;
|
||||
}
|
||||
if ($versionid) {
|
||||
if (array_key_exists($versionid, $policy->versions)) {
|
||||
$this->versions[$versionid] = $policy->versions[$versionid];
|
||||
break; // No need to keep searching.
|
||||
}
|
||||
} else if ($policy->currentversion) {
|
||||
$this->versions[$policy->currentversion->id] = $policy->currentversion;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->versions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates if policyid and versionid are valid (if specified)
|
||||
*/
|
||||
public function validate_ids() {
|
||||
$policyid = $this->get_policy_id_filter();
|
||||
$versionid = $this->get_version_id_filter();
|
||||
if ($policyid || $versionid) {
|
||||
$found = array_filter($this->get_avaliable_policies(), function($policy) use ($policyid, $versionid) {
|
||||
return (!$policyid || $policy->id == $policyid) &&
|
||||
(!$versionid || array_key_exists($versionid, $policy->versions));
|
||||
});
|
||||
if (!$found) {
|
||||
// Throw exception that policy/version is not found.
|
||||
throw new \moodle_exception('errorpolicyversionnotfound', 'tool_policy');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If policyid or versionid is specified return one single policy that needs to be shown
|
||||
*
|
||||
* If neither policyid nor versionid is specified this method returns null.
|
||||
*
|
||||
* When versionid is specified this method will always return an object (this is validated in {@link self::validate_ids()}
|
||||
* When only policyid is specified this method either returns the current version of the policy or null if there is
|
||||
* no current version (for example, it is an old policy).
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function get_single_version() {
|
||||
if ($this->get_version_id_filter() || $this->get_policy_id_filter()) {
|
||||
$versions = $this->get_versions();
|
||||
return reset($versions);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns URL of the acceptances page with all current filters applied
|
||||
*
|
||||
* @return \moodle_url
|
||||
*/
|
||||
public function get_url() {
|
||||
$urlparams = [];
|
||||
if ($policyid = $this->get_policy_id_filter()) {
|
||||
$urlparams['policyid'] = $policyid;
|
||||
}
|
||||
if ($versionid = $this->get_version_id_filter()) {
|
||||
$urlparams['versionid'] = $versionid;
|
||||
}
|
||||
$i = 0;
|
||||
foreach ($this->filtersapplied as $filter) {
|
||||
if ($filter[0] != self::FILTER_POLICYID && $filter[0] != self::FILTER_VERSIONID) {
|
||||
if ($filter[0] == self::FILTER_SEARCH_STRING) {
|
||||
$urlparams['unified-filters['.($i++).']'] = $filter[1];
|
||||
} else {
|
||||
$urlparams['unified-filters['.($i++).']'] = join(':', $filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new \moodle_url('/admin/tool/policy/acceptances.php', $urlparams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an option name for the smart select for the version
|
||||
*
|
||||
* @param \stdClass $version
|
||||
* @return string
|
||||
*/
|
||||
protected function get_version_option_for_filter($version) {
|
||||
if ($version->status == policy_version::STATUS_ACTIVE) {
|
||||
$a = (object)[
|
||||
'name' => format_string($version->revision),
|
||||
'status' => get_string('status'.policy_version::STATUS_ACTIVE, 'tool_policy'),
|
||||
];
|
||||
return get_string('filterrevisionstatus', 'tool_policy', $a);
|
||||
} else {
|
||||
return get_string('filterrevision', 'tool_policy', $version->revision);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build list of filters available for this page
|
||||
*
|
||||
* @return array [$availablefilters, $selectedoptions]
|
||||
*/
|
||||
protected function build_available_filters() {
|
||||
$selectedoptions = [];
|
||||
$availablefilters = [];
|
||||
|
||||
$versionid = $this->get_version_id_filter();
|
||||
$policyid = $versionid ? $this->get_single_version()->policyid : $this->get_policy_id_filter();
|
||||
|
||||
// Policies.
|
||||
$policies = $this->get_avaliable_policies();
|
||||
if ($policyid) {
|
||||
// If policy is selected, display only the current policy in the selector.
|
||||
$selectedoptions[] = $key = self::FILTER_POLICYID . ':' . $policyid;
|
||||
$version = $versionid ? $policies[$policyid]->versions[$versionid] : reset($policies[$policyid]->versions);
|
||||
$availablefilters[$key] = get_string('filterpolicy', 'tool_policy', $version->name);
|
||||
} else {
|
||||
// If no policy/version is selected display the list of all policies.
|
||||
foreach ($policies as $policy) {
|
||||
$firstversion = reset($policy->versions);
|
||||
$key = self::FILTER_POLICYID . ':' . $policy->id;
|
||||
$availablefilters[$key] = get_string('filterpolicy', 'tool_policy', $firstversion->name);
|
||||
}
|
||||
}
|
||||
|
||||
// Versions.
|
||||
if ($versionid) {
|
||||
$singleversion = $this->get_single_version();
|
||||
$selectedoptions[] = $key = self::FILTER_VERSIONID . ':' . $singleversion->id;
|
||||
$availablefilters[$key] = $this->get_version_option_for_filter($singleversion);
|
||||
} else if ($policyid) {
|
||||
foreach ($policies[$policyid]->versions as $version) {
|
||||
$key = self::FILTER_VERSIONID . ':' . $version->id;
|
||||
$availablefilters[$key] = $this->get_version_option_for_filter($version);
|
||||
}
|
||||
}
|
||||
|
||||
// Permissions.
|
||||
$permissions = [
|
||||
self::FILTER_CAPABILITY_ACCEPT . ':1' => get_string('filtercapabilityyes', 'tool_policy'),
|
||||
self::FILTER_CAPABILITY_ACCEPT . ':0' => get_string('filtercapabilityno', 'tool_policy'),
|
||||
];
|
||||
if (($currentpermission = $this->get_capability_accept_filter()) !== null) {
|
||||
$selectedoptions[] = $key = self::FILTER_CAPABILITY_ACCEPT . ':' . $currentpermission;
|
||||
$permissions = array_intersect_key($permissions, [$key => true]);
|
||||
}
|
||||
$availablefilters += $permissions;
|
||||
|
||||
// Status.
|
||||
$statuses = [
|
||||
self::FILTER_STATUS.':1' => get_string('filterstatusyes', 'tool_policy'),
|
||||
self::FILTER_STATUS.':0' => get_string('filterstatusno', 'tool_policy'),
|
||||
];
|
||||
if (($currentstatus = $this->get_status_filter()) !== null) {
|
||||
$selectedoptions[] = $key = self::FILTER_STATUS . ':' . $currentstatus;
|
||||
$statuses = array_intersect_key($statuses, [$key => true]);
|
||||
}
|
||||
$availablefilters += $statuses;
|
||||
|
||||
// Roles.
|
||||
$currentroles = $this->get_role_filters();
|
||||
foreach ($this->roles as $roleid => $rolename) {
|
||||
$key = self::FILTER_ROLE . ':' . $roleid;
|
||||
$availablefilters[$key] = get_string('filterrole', 'tool_policy', $rolename);
|
||||
if (in_array($roleid, $currentroles)) {
|
||||
$selectedoptions[] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
// Search string.
|
||||
foreach ($this->get_search_strings() as $str) {
|
||||
$selectedoptions[] = $str;
|
||||
$availablefilters[$str] = $str;
|
||||
}
|
||||
|
||||
return [$availablefilters, $selectedoptions];
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to export the renderer data in a format that is suitable for a mustache template.
|
||||
*
|
||||
* @param renderer_base $output Used to do a final render of any components that need to be rendered for export.
|
||||
* @return \stdClass|array
|
||||
*/
|
||||
public function export_for_template(\renderer_base $output) {
|
||||
$data = new \stdClass();
|
||||
$data->action = (new \moodle_url('/admin/tool/policy/acceptances.php'))->out(false);
|
||||
|
||||
$data->filteroptions = [];
|
||||
$originalfilteroptions = [];
|
||||
list($avilablefilters, $selectedoptions) = $this->build_available_filters();
|
||||
foreach ($avilablefilters as $value => $label) {
|
||||
$selected = in_array($value, $selectedoptions);
|
||||
$filteroption = (object)[
|
||||
'value' => $value,
|
||||
'label' => $label
|
||||
];
|
||||
$originalfilteroptions[] = $filteroption;
|
||||
$filteroption->selected = $selected;
|
||||
$data->filteroptions[] = $filteroption;
|
||||
}
|
||||
$data->originaloptionsjson = json_encode($originalfilteroptions);
|
||||
return $data;
|
||||
}
|
||||
}
|
114
admin/tool/policy/classes/output/user_agreement.php
Normal file
114
admin/tool/policy/classes/output/user_agreement.php
Normal file
@ -0,0 +1,114 @@
|
||||
<?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 {@link tool_policy\output\user_agreement} class.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @category output
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_policy\output;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use moodle_url;
|
||||
use renderable;
|
||||
use renderer_base;
|
||||
use single_button;
|
||||
use templatable;
|
||||
|
||||
/**
|
||||
* List of users and their acceptances
|
||||
*
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class user_agreement implements \templatable, \renderable {
|
||||
|
||||
/** @var int */
|
||||
protected $userid;
|
||||
|
||||
/** @var bool */
|
||||
protected $onbehalf;
|
||||
|
||||
/** @var moodle_url */
|
||||
protected $pageurl;
|
||||
|
||||
/** @var array */
|
||||
protected $versions;
|
||||
|
||||
/** @var array */
|
||||
protected $accepted;
|
||||
|
||||
/** @var bool */
|
||||
protected $canaccept;
|
||||
|
||||
/**
|
||||
* user_agreement constructor
|
||||
*
|
||||
* @param int $userid
|
||||
* @param array $accepted list of ids of accepted versions
|
||||
* @param moodle_url $pageurl
|
||||
* @param array $versions list of versions (id=>name)
|
||||
* @param bool $onbehalf whether at least one version was accepted by somebody else on behalf of the user
|
||||
* @param bool $canaccept does the current user have permission to accept the policy on behalf of user $userid
|
||||
*/
|
||||
public function __construct($userid, $accepted, moodle_url $pageurl, $versions, $onbehalf = false, $canaccept = null) {
|
||||
$this->userid = $userid;
|
||||
$this->onbehalf = $onbehalf;
|
||||
$this->pageurl = $pageurl;
|
||||
$this->versions = $versions;
|
||||
$this->accepted = $accepted;
|
||||
$this->canaccept = $canaccept;
|
||||
if (count($this->accepted) < count($this->versions) && $canaccept === null) {
|
||||
$this->canaccept = (has_capability('tool/policy:acceptbehalf', \context_system::instance()) ||
|
||||
has_capability('tool/policy:acceptbehalf', \context_user::instance($this->userid)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Export data to be rendered.
|
||||
*
|
||||
* @param renderer_base $output
|
||||
* @return stdClass
|
||||
*/
|
||||
public function export_for_template(\renderer_base $output) {
|
||||
$data = [
|
||||
'status' => count($this->accepted) == count($this->versions),
|
||||
'onbehalf' => $this->onbehalf,
|
||||
'canaccept' => $this->canaccept,
|
||||
];
|
||||
if (!$data['status'] && $this->canaccept) {
|
||||
$linkparams = ['userids[0]' => $this->userid];
|
||||
foreach (array_diff(array_keys($this->versions), $this->accepted) as $versionid) {
|
||||
$linkparams["versionids[{$versionid}]"] = $versionid;
|
||||
}
|
||||
$linkparams['returnurl'] = $this->pageurl->out_as_local_url(false);
|
||||
$link = new \moodle_url('/admin/tool/policy/accept.php', $linkparams);
|
||||
$data['acceptlink'] = $link->out(false);
|
||||
$data['acceptmodaldata'] = $link->get_query_string(false); // TODO not needed?
|
||||
}
|
||||
$data['singleversion'] = count($this->versions) == 1;
|
||||
if ($data['singleversion']) {
|
||||
$firstversion = reset($this->versions);
|
||||
$data['versionname'] = $firstversion;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
BIN
admin/tool/policy/pix/agreedno.png
Normal file
BIN
admin/tool/policy/pix/agreedno.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 258 B |
3
admin/tool/policy/pix/agreedno.svg
Normal file
3
admin/tool/policy/pix/agreedno.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
|
||||
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
|
||||
]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="-1.6 -0.5 16 16" preserveAspectRatio="xMinYMid meet" overflow="visible"><path d="M12.8 2.7L10.1 0S8.5 1.5 6.4 4C4.3 1.5 2.7 0 2.7 0L0 2.7S1.9 4 4.6 6.4C3 8.7 1.3 11.6 0 14.9c2.2-2.7 4.4-5 6.4-6.9 2 1.9 4.2 4.2 6.4 6.9-1.3-3.3-3-6.2-4.6-8.6 2.7-2.3 4.6-3.6 4.6-3.6z" fill="#FF403C"/></svg>
|
After Width: | Height: | Size: 517 B |
BIN
admin/tool/policy/pix/agreedyes.png
Normal file
BIN
admin/tool/policy/pix/agreedyes.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 234 B |
3
admin/tool/policy/pix/agreedyes.svg
Normal file
3
admin/tool/policy/pix/agreedyes.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
|
||||
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
|
||||
]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="-0.1 0 16 16" preserveAspectRatio="xMinYMid meet" overflow="visible"><path d="M6.4 11.1c-2-2.5-3.7-4-3.7-4L0 9.8C5 13.1 8.1 16 8.1 16s.2-.7.6-1.8c.9-2.7 3.2-8.1 7.1-14.2-4.6 3.7-7.7 8.2-9.4 11.1z" fill="#9C3"/></svg>
|
After Width: | Height: | Size: 445 B |
BIN
admin/tool/policy/pix/agreedyesonbehalf.png
Normal file
BIN
admin/tool/policy/pix/agreedyesonbehalf.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 234 B |
3
admin/tool/policy/pix/agreedyesonbehalf.svg
Normal file
3
admin/tool/policy/pix/agreedyesonbehalf.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
|
||||
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
|
||||
]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="-0.1 0 16 16" preserveAspectRatio="xMinYMid meet" overflow="visible"><path d="M6.4 11.1c-2-2.5-3.7-4-3.7-4L0 9.8C5 13.1 8.1 16 8.1 16s.2-.7.6-1.8c.9-2.7 3.2-8.1 7.1-14.2-4.6 3.7-7.7 8.2-9.4 11.1z" fill="#FFB844"/></svg>
|
After Width: | Height: | Size: 448 B |
149
admin/tool/policy/templates/acceptances.mustache
Normal file
149
admin/tool/policy/templates/acceptances.mustache
Normal file
@ -0,0 +1,149 @@
|
||||
{{!
|
||||
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 tool_policy/acceptances
|
||||
|
||||
Template for the user acceptances page.
|
||||
|
||||
Classes required for JS:
|
||||
-
|
||||
|
||||
Data attributes required for JS:
|
||||
-
|
||||
|
||||
Context variables required for this template:
|
||||
* policies
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"hasonbehalfagreements": true,
|
||||
"policies": [
|
||||
{
|
||||
"versions": [
|
||||
{
|
||||
"isfirst": true,
|
||||
"policyid": 1,
|
||||
"viewurl": "/",
|
||||
"name": "Terms & conditions",
|
||||
"revision": "2.0",
|
||||
"hasarchived": true,
|
||||
"timeaccepted": "1 Mar 2018",
|
||||
"agreement": {
|
||||
"onbehalf": false,
|
||||
"status": false,
|
||||
"canaccept": true,
|
||||
"acceptlink": "#"
|
||||
}
|
||||
},
|
||||
{
|
||||
"isfirst": false,
|
||||
"policyid": 1,
|
||||
"viewurl": "/",
|
||||
"name": "Terms & conditions",
|
||||
"revision": "1.0-beta",
|
||||
"acceptedby": "<a href=\"#\">Mary Smith</a>",
|
||||
"note": "Based on parent's agreement via email",
|
||||
"hasarchived": false,
|
||||
"timeaccepted": "15 Feb 2018",
|
||||
"agreement": {
|
||||
"onbehalf": true,
|
||||
"status": true,
|
||||
"canaccept": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}}
|
||||
<table class="generaltable fullwidth">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{#str}} policydocname, tool_policy {{/str}}</th>
|
||||
<th>{{#str}} policydocrevision, tool_policy {{/str}}</th>
|
||||
<th>{{#str}} agreed, tool_policy {{/str}}</th>
|
||||
<th>{{#str}} agreedon, tool_policy {{/str}}</th>
|
||||
{{#hasonbehalfagreements}}
|
||||
<th>{{#str}} agreedby, tool_policy {{/str}}</th>
|
||||
<th>{{#str}} acceptancenote, tool_policy {{/str}}</th>
|
||||
{{/hasonbehalfagreements}}
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#policies}}
|
||||
{{#versions}}
|
||||
<tr {{^isfirst}}class="archived{{policyid}}" style="display:none"{{/isfirst}}>
|
||||
<td>
|
||||
{{^isfirst}}
|
||||
<div style="float:left">
|
||||
{{#pix}} level, tool_policy {{/pix}}
|
||||
</div>
|
||||
{{/isfirst}}
|
||||
<div {{^isfirst}}style="margin-left: 24px" {{/isfirst}}>
|
||||
<div><a href="{{viewurl}}">{{{name}}}</a></div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<a href="{{viewurl}}">{{{revision}}}</a>
|
||||
{{#iscurrent}}<span class="label label-success">{{#str}} status1, tool_policy {{/str}}{{/iscurrent}}
|
||||
</td>
|
||||
<td>
|
||||
{{#agreement}}
|
||||
{{>tool_policy/user_agreement}}
|
||||
{{/agreement}}
|
||||
|
||||
</td>
|
||||
<td>{{timeaccepted}}</td>
|
||||
{{#hasonbehalfagreements}}
|
||||
<td>{{{acceptedby}}}</td>
|
||||
<td>{{{note}}}</td>
|
||||
{{/hasonbehalfagreements}}
|
||||
<td>
|
||||
{{#hasarchived}}<a class="showarchived" data-target=".archived{{policyid}}" data-status="hidden" href="#">
|
||||
<div class="toggleoff" style="display:none">{{#pix}}t/less, moodle, {{#str}}detailedless, moodle{{/str}}{{/pix}}</div>
|
||||
<div class="toggleon">{{#pix}}t/more, moodle, {{#str}}detailedmore, moodle{{/str}}{{/pix}}</div>
|
||||
</a>{{/hasarchived}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/versions}}
|
||||
{{/policies}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{#returnurl}}
|
||||
<div><a role="button" href="{{returnurl}}" class="btn btn-primary">{{#str}} back {{/str}}</a></div>
|
||||
{{/returnurl}}
|
||||
{{#js}}
|
||||
require(['jquery'], function($) {
|
||||
$('body').on('click', '.showarchived', function(e) {
|
||||
e.preventDefault();
|
||||
var target = $(this).attr('data-target'),
|
||||
status = $(this).attr('data-status');
|
||||
if (status === 'hidden') {
|
||||
$(target).show();
|
||||
$(this).attr('data-status', 'shown');
|
||||
$(this).find('.toggleoff').show();
|
||||
$(this).find('.toggleon').hide();
|
||||
} else {
|
||||
$(target).hide();
|
||||
$(this).attr('data-status', 'hidden');
|
||||
$(this).find('.toggleon').show();
|
||||
$(this).find('.toggleoff').hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
{{/js}}
|
67
admin/tool/policy/templates/acceptances_filter.mustache
Normal file
67
admin/tool/policy/templates/acceptances_filter.mustache
Normal file
@ -0,0 +1,67 @@
|
||||
{{!
|
||||
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 tool_policy/acceptances_filter
|
||||
|
||||
Template for the unified filter element.
|
||||
|
||||
Context variables required for this template:
|
||||
* action string - The action URL for the form.
|
||||
* filteroptions - Array of filter options.
|
||||
* value string - The option value.
|
||||
* label string - The option label.
|
||||
* selected boolean - Whether the option is selected
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"action": "/admin/tool/policy/acceptances.php",
|
||||
"filteroptions": [
|
||||
{
|
||||
"value": "1",
|
||||
"label": "Option 1"
|
||||
},
|
||||
{
|
||||
"value": "2",
|
||||
"label": "Option 2",
|
||||
"selected": true
|
||||
},
|
||||
{
|
||||
"value": "3",
|
||||
"label": "Option 3",
|
||||
"selected": true
|
||||
},
|
||||
{
|
||||
"value": "4",
|
||||
"label": "Option 4"
|
||||
}
|
||||
]
|
||||
}
|
||||
}}
|
||||
<form method="post" action="{{action}}" class="m-b-1" role="search">
|
||||
<label for="unified-filters" class="sr-only">{{#str}}filters , tool_policy{{/str}}</label>
|
||||
<select name="unified-filters[]" id="unified-filters" multiple="multiple" data-originaloptionsjson="{{originaloptionsjson}}" class="form-autocomplete-original-select">
|
||||
{{#filteroptions}}
|
||||
<option value="{{value}}" {{#selected}}selected="selected"{{/selected}}>{{{label}}}</option>
|
||||
{{/filteroptions}}
|
||||
</select>
|
||||
<input type="hidden" name="unified-filter-submitted" value="1">
|
||||
</form>
|
||||
{{#js}}
|
||||
require(['tool_policy/acceptances_filter'], function(Filter) {
|
||||
Filter.init();
|
||||
});
|
||||
{{/js}}
|
65
admin/tool/policy/templates/user_agreement.mustache
Normal file
65
admin/tool/policy/templates/user_agreement.mustache
Normal file
@ -0,0 +1,65 @@
|
||||
{{!
|
||||
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 tool_policy/user_agreement
|
||||
|
||||
Template for the user agreement icon.
|
||||
|
||||
Classes required for JS:
|
||||
-
|
||||
|
||||
Data attributes required for JS:
|
||||
-
|
||||
|
||||
Context variables required for this template:
|
||||
* status
|
||||
* onbehalf
|
||||
* canaccept
|
||||
* acceptlink
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"status": false,
|
||||
"onbehalf": false,
|
||||
"canaccept": true,
|
||||
"acceptlink": "/",
|
||||
"singleversion": false,
|
||||
"versionname": ""
|
||||
}
|
||||
}}
|
||||
{{#status}}
|
||||
|
||||
{{#onbehalf}}
|
||||
<span>{{#pix}}agreedyesonbehalf, tool_policy, {{#str}} agreedyesonbehalf, tool_policy {{/str}}{{/pix}}</span>
|
||||
{{/onbehalf}}
|
||||
{{^onbehalf}}
|
||||
<span>{{#pix}}agreedyes, tool_policy, {{#str}} agreedyes, tool_policy {{/str}}{{/pix}}</span>
|
||||
{{/onbehalf}}
|
||||
{{/status}}
|
||||
{{^status}}
|
||||
{{#canaccept}}
|
||||
{{#singleversion}}
|
||||
<a href="{{acceptlink}}" data-action="acceptmodal">{{#pix}}agreedno, tool_policy, {{#str}} agreednowithlink, tool_policy, {{{versionname}}} {{/str}}{{/pix}}</a>
|
||||
{{/singleversion}}
|
||||
{{^singleversion}}
|
||||
<a href="{{acceptlink}}" data-action="acceptmodal">{{#pix}}agreedno, tool_policy, {{#str}} agreednowithlinkall, tool_policy {{/str}}{{/pix}}</a>
|
||||
{{/singleversion}}
|
||||
{{/canaccept}}
|
||||
{{^canaccept}}
|
||||
<span>{{#pix}}agreedno, tool_policy, {{#str}} agreedno, tool_policy {{/str}}{{/pix}}</span>
|
||||
{{/canaccept}}
|
||||
{{/status}}
|
230
admin/tool/policy/tests/behat/acceptances.feature
Normal file
230
admin/tool/policy/tests/behat/acceptances.feature
Normal file
@ -0,0 +1,230 @@
|
||||
@tool @tool_policy
|
||||
Feature: Viewing acceptances reports and accepting on behalf of other users
|
||||
In order to manage user acceptances
|
||||
As a manager
|
||||
I need to be able to view acceptances and accept on behalf of other users
|
||||
|
||||
Background:
|
||||
Given the following config values are set as admin:
|
||||
| sitepolicyhandler | tool_policy |
|
||||
And the following policies exist:
|
||||
| Name | Revision | Content | Summary | Status |
|
||||
| This site policy | | full text2 | short text2 | active |
|
||||
| This privacy policy | | full text3 | short text3 | draft |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| user1 | User | One | one@example.com |
|
||||
| user2 | User | Two | two@example.com |
|
||||
| manager | Max | Manager | man@example.com |
|
||||
And the following "role assigns" exist:
|
||||
| user | role | contextlevel | reference |
|
||||
| manager | manager | System | |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname |
|
||||
| Course1 | C1 |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| user1 | C1 | student |
|
||||
| user2 | C1 | student |
|
||||
|
||||
Scenario: View acceptances made by users on their own, single policy
|
||||
When I log in as "user1"
|
||||
Then I should see "This site policy"
|
||||
And I should not see "Course overview"
|
||||
And I press "Next"
|
||||
And I set the field "I agree to the This site policy" to "1"
|
||||
And I press "Next"
|
||||
And I should see "Course overview"
|
||||
And I log out
|
||||
And I log in as "manager"
|
||||
And I press "Next"
|
||||
And I set the field "I agree to the This site policy" to "1"
|
||||
And I press "Next"
|
||||
And I navigate to "Privacy and policies > User agreements" in site administration
|
||||
And "Agreed" "icon" should exist in the "User One" "table_row"
|
||||
And "Agreed" "icon" should exist in the "Max Manager" "table_row"
|
||||
And "Not agreed" "icon" should exist in the "User Two" "table_row"
|
||||
|
||||
Scenario: Agree on behalf of another user as a manager, single policy, javascript off
|
||||
Given I log in as "admin"
|
||||
And I set the following system permissions of "Manager" role:
|
||||
| capability | permission |
|
||||
| tool/policy:acceptbehalf | Allow |
|
||||
And I log out
|
||||
When I log in as "manager"
|
||||
And I press "Next"
|
||||
And I set the field "I agree to the This site policy" to "1"
|
||||
And I press "Next"
|
||||
And I navigate to "Privacy and policies > Manage policies" in site administration
|
||||
And I click on "1 of 4 (25%)" "link" in the "This site policy" "table_row"
|
||||
And I click on "Not agreed" "link" in the "User One" "table_row"
|
||||
Then I should see "Consent details"
|
||||
And I should see "User One"
|
||||
And I should see "This site policy"
|
||||
And I should see "I acknowledge that consents to these policies have been acquired"
|
||||
And I set the field "Remarks" to "Consent received from a parent"
|
||||
And I press "I agree to the policy"
|
||||
And "Agreed on behalf of" "icon" should exist in the "User One" "table_row"
|
||||
And "Max Manager" "link" should exist in the "User One" "table_row"
|
||||
And "Consent received from a parent" "text" should exist in the "User One" "table_row"
|
||||
And "Not agreed" "icon" should exist in the "User Two" "table_row"
|
||||
|
||||
@javascript
|
||||
Scenario: Agree on behalf of another user as a manager, single policy, javascript on
|
||||
Given I log in as "admin"
|
||||
And I set the following system permissions of "Manager" role:
|
||||
| capability | permission |
|
||||
| tool/policy:acceptbehalf | Allow |
|
||||
And I log out
|
||||
When I log in as "manager"
|
||||
And I press "Next"
|
||||
And I set the field "I agree to the This site policy" to "1"
|
||||
And I press "Next"
|
||||
And I navigate to "Privacy and policies > Manage policies" in site administration
|
||||
And I click on "1 of 4 (25%)" "link" in the "This site policy" "table_row"
|
||||
And I click on "Not agreed" "link" in the "User One" "table_row"
|
||||
Then I should see "Consent details"
|
||||
And I should see "User One"
|
||||
And I should see "This site policy"
|
||||
And I should see "I acknowledge that consents to these policies have been acquired"
|
||||
And I set the field "Remarks" to "Consent received from a parent"
|
||||
And I press "I agree to the policy"
|
||||
And "Agreed on behalf of" "icon" should exist in the "User One" "table_row"
|
||||
And "Max Manager" "link" should exist in the "User One" "table_row"
|
||||
And "Consent received from a parent" "text" should exist in the "User One" "table_row"
|
||||
And "Not agreed" "icon" should exist in the "User Two" "table_row"
|
||||
|
||||
Scenario: View acceptances made by users on their own, multiple policies
|
||||
Given I log in as "admin"
|
||||
And I navigate to "Privacy and policies > Manage policies" in site administration
|
||||
And I open the action menu in "This privacy policy" "table_row"
|
||||
And I click on "Set status to \"Active\"" "link" in the "This privacy policy" "table_row"
|
||||
And I press "Continue"
|
||||
And I log out
|
||||
When I log in as "user1"
|
||||
Then I should see "This site policy"
|
||||
And I press "Next"
|
||||
And I should see "This privacy policy"
|
||||
And I press "Next"
|
||||
And I set the field "I agree to the This site policy" to "1"
|
||||
And I set the field "I agree to the This privacy policy" to "1"
|
||||
And I press "Next"
|
||||
And I should see "Course overview"
|
||||
And I log out
|
||||
And I log in as "manager"
|
||||
And I press "Next"
|
||||
And I press "Next"
|
||||
And I set the field "I agree to the This site policy" to "1"
|
||||
And I set the field "I agree to the This privacy policy" to "1"
|
||||
And I press "Next"
|
||||
And I navigate to "Privacy and policies > User agreements" in site administration
|
||||
And "Agreed" "icon" should exist in the "User One" "table_row"
|
||||
And "Not agreed" "icon" should not exist in the "User One" "table_row"
|
||||
And "Agreed" "icon" should exist in the "Max Manager" "table_row"
|
||||
And "Not agreed" "icon" should exist in the "User Two" "table_row"
|
||||
And "Agreed" "icon" should not exist in the "User Two" "table_row"
|
||||
And I click on "2 of 2" "link" in the "User One" "table_row"
|
||||
And "Agreed" "icon" should exist in the "This site policy" "table_row"
|
||||
And "Agreed" "icon" should exist in the "This privacy policy" "table_row"
|
||||
And I am on site homepage
|
||||
And I navigate to "Privacy and policies > User agreements" in site administration
|
||||
And I click on "0 of 2" "link" in the "User Two" "table_row"
|
||||
And "Not agreed" "icon" should exist in the "This site policy" "table_row"
|
||||
And "Not agreed" "icon" should exist in the "This privacy policy" "table_row"
|
||||
|
||||
Scenario: Agree on behalf of another user as a manager, multiple policies, javascript off
|
||||
Given I log in as "admin"
|
||||
And I navigate to "Privacy and policies > Manage policies" in site administration
|
||||
And I open the action menu in "This privacy policy" "table_row"
|
||||
And I click on "Set status to \"Active\"" "link" in the "This privacy policy" "table_row"
|
||||
And I press "Continue"
|
||||
And I set the following system permissions of "Manager" role:
|
||||
| capability | permission |
|
||||
| tool/policy:acceptbehalf | Allow |
|
||||
And I log out
|
||||
When I log in as "manager"
|
||||
And I press "Next"
|
||||
And I press "Next"
|
||||
And I set the field "I agree to the This site policy" to "1"
|
||||
And I set the field "I agree to the This privacy policy" to "1"
|
||||
And I press "Next"
|
||||
And I navigate to "Privacy and policies > User agreements" in site administration
|
||||
And I click on "Not agreed, click to agree to \"This site policy\"" "link" in the "User One" "table_row"
|
||||
Then I should see "Consent details"
|
||||
And I should see "User One"
|
||||
And I should see "This site policy"
|
||||
And I should see "I acknowledge that consents to these policies have been acquired"
|
||||
And I set the field "Remarks" to "Consent received from a parent"
|
||||
And I press "I agree to the policy"
|
||||
And "Agreed on behalf of" "icon" should exist in the "User One" "table_row"
|
||||
And "Not agreed, click to agree to \"This privacy policy\"" "icon" should exist in the "User One" "table_row"
|
||||
And I click on "1 of 2" "link" in the "User One" "table_row"
|
||||
And "Agreed on behalf of" "icon" should exist in the "This site policy" "table_row"
|
||||
And "Max Manager" "link" should exist in the "This site policy" "table_row"
|
||||
And "Consent received from a parent" "text" should exist in the "This site policy" "table_row"
|
||||
And "Not agreed" "icon" should exist in the "This privacy policy" "table_row"
|
||||
|
||||
@javascript
|
||||
Scenario: Agree on behalf of another user as a manager, multiple policies, javascript on
|
||||
Given I log in as "admin"
|
||||
And I navigate to "Privacy and policies > Manage policies" in site administration
|
||||
And I open the action menu in "This privacy policy" "table_row"
|
||||
And I click on "Set status to \"Active\"" "link" in the "This privacy policy" "table_row"
|
||||
And I press "Activate"
|
||||
And I set the following system permissions of "Manager" role:
|
||||
| capability | permission |
|
||||
| tool/policy:acceptbehalf | Allow |
|
||||
And I log out
|
||||
When I log in as "manager"
|
||||
And I press "Next"
|
||||
And I press "Next"
|
||||
And I set the field "I agree to the This site policy" to "1"
|
||||
And I set the field "I agree to the This privacy policy" to "1"
|
||||
And I press "Next"
|
||||
And I navigate to "Privacy and policies > User agreements" in site administration
|
||||
And I click on "Not agreed, click to agree to \"This site policy\"" "link" in the "User One" "table_row"
|
||||
Then I should see "Consent details"
|
||||
And I should see "User One"
|
||||
And I should see "This site policy"
|
||||
And I should see "I acknowledge that consents to these policies have been acquired"
|
||||
And I set the field "Remarks" to "Consent received from a parent"
|
||||
And I press "I agree to the policy"
|
||||
And "Agreed on behalf of" "icon" should exist in the "User One" "table_row"
|
||||
And "Not agreed, click to agree to \"This privacy policy\"" "icon" should exist in the "User One" "table_row"
|
||||
And I click on "1 of 2" "link" in the "User One" "table_row"
|
||||
And "Agreed on behalf of" "icon" should exist in the "This site policy" "table_row"
|
||||
And "Max Manager" "link" should exist in the "This site policy" "table_row"
|
||||
And "Consent received from a parent" "text" should exist in the "This site policy" "table_row"
|
||||
And "Not agreed" "icon" should exist in the "This privacy policy" "table_row"
|
||||
|
||||
Scenario: Policies and agreements profile link visible for current user
|
||||
Given I log in as "user1"
|
||||
And I press "Next"
|
||||
And I set the field "I agree to the This site policy" to "1"
|
||||
And I press "Next"
|
||||
When I follow "Profile" in the user menu
|
||||
# User can see his own agreements link in the profile.
|
||||
Then I should see "Policies and agreements"
|
||||
And I follow "Policies and agreements"
|
||||
And "Agreed" "icon" should exist in the "This site policy" "table_row"
|
||||
# User can't see agreements link in other user profiles.
|
||||
And I am on "Course1" course homepage
|
||||
And I navigate to course participants
|
||||
And I follow "User Two"
|
||||
And I should not see "Policies and agreements"
|
||||
|
||||
Scenario: Policies and agreements profile link visible also for users who can access on behaf of others
|
||||
Given I log in as "admin"
|
||||
And I set the following system permissions of "Manager" role:
|
||||
| capability | permission |
|
||||
| tool/policy:acceptbehalf | Allow |
|
||||
And I log out
|
||||
And I log in as "manager"
|
||||
And I press "Next"
|
||||
And I set the field "I agree to the This site policy" to "1"
|
||||
And I press "Next"
|
||||
# User can see agreements link in other user profiles because has the capability for accepting on behalf of them.
|
||||
When I am on "Course1" course homepage
|
||||
And I navigate to course participants
|
||||
And I follow "User Two"
|
||||
Then I should see "Policies and agreements"
|
111
admin/tool/policy/tests/behat/behat_tool_policy.php
Normal file
111
admin/tool/policy/tests/behat/behat_tool_policy.php
Normal file
@ -0,0 +1,111 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Step definition for tool_policy
|
||||
*
|
||||
* @package tool_policy
|
||||
* @category test
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once(__DIR__ . '/../../../../../lib/behat/behat_base.php');
|
||||
|
||||
use Behat\Gherkin\Node\TableNode as TableNode;
|
||||
|
||||
/**
|
||||
* Step definition for tool_policy
|
||||
*
|
||||
* @package tool_policy
|
||||
* @category test
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class behat_tool_policy extends behat_base {
|
||||
|
||||
/**
|
||||
* Click on an entry in the edit menu.
|
||||
*
|
||||
* @Given /^the following policies exist:$/
|
||||
*
|
||||
* @param TableNode $data
|
||||
*/
|
||||
public function the_following_policies_exist(TableNode $data) {
|
||||
global $CFG;
|
||||
if (empty($CFG->sitepolicyhandler) || $CFG->sitepolicyhandler !== 'tool_policy') {
|
||||
throw new Exception('Site policy handler is not set to "tool_policy"');
|
||||
}
|
||||
|
||||
$fields = [
|
||||
'name', // Policy name (required).
|
||||
'revision', // Revision name.
|
||||
'policy', // Any policy identifier, can be used to generate multiple versions of the same policy.
|
||||
'status', // Version status: 'draft', 'active', 'archived'. By default 'active'.
|
||||
'audience', // Audience: 'guest', 'all', 'loggedin' (by default 'all').
|
||||
'type', // 0 (default) - Site policy, 1 - Privacy policy, 2 - Third party policy, 99 - Other .
|
||||
'content',
|
||||
'summary',
|
||||
];
|
||||
|
||||
// Associative array "policy identifier" => id in the database .
|
||||
$policies = [];
|
||||
|
||||
foreach ($data->getHash() as $elementdata) {
|
||||
$data = (object)[
|
||||
'audience' => \tool_policy\policy_version::AUDIENCE_ALL,
|
||||
'archived' => 0,
|
||||
'type' => 0
|
||||
];
|
||||
$elementdata = array_change_key_case($elementdata, CASE_LOWER);
|
||||
foreach ($elementdata as $key => $value) {
|
||||
if ($key === 'policy') {
|
||||
if (array_key_exists($value, $policies)) {
|
||||
$data->policyid = $policies[$value];
|
||||
}
|
||||
} else if ($key === 'status') {
|
||||
$data->archived = ($value === 'archived');
|
||||
} else if ($key === 'audience') {
|
||||
if ($value === 'guest') {
|
||||
$data->audience = \tool_policy\policy_version::AUDIENCE_GUESTS;
|
||||
} else if ($value === 'loggedin') {
|
||||
$data->audience = \tool_policy\policy_version::AUDIENCE_LOGGEDIN;
|
||||
}
|
||||
} else if (($key === 'summary' || $key === 'content') && !empty($value)) {
|
||||
$data->{$key.'_editor'} = ['text' => $value, 'format' => FORMAT_MOODLE];
|
||||
} else if (in_array($key, $fields) && $value !== '') {
|
||||
$data->$key = $value;
|
||||
}
|
||||
}
|
||||
if (empty($data->name) || empty($data->content_editor) || empty($data->summary_editor)) {
|
||||
throw new Exception('Policy is missing at least one of the required fields: name, content, summary');
|
||||
}
|
||||
|
||||
if (!empty($data->policyid)) {
|
||||
$version = tool_policy\api::form_policydoc_update_new($data);
|
||||
} else {
|
||||
$version = \tool_policy\api::form_policydoc_add($data);
|
||||
}
|
||||
|
||||
if (!empty($elementdata['policy'])) {
|
||||
$policies[$elementdata['policy']] = $version->get('policyid');
|
||||
}
|
||||
if (empty($elementdata['status']) || $elementdata['status'] === 'active') {
|
||||
\tool_policy\api::make_current($version->get('id'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
261
admin/tool/policy/tests/behat/managepolicies.feature
Normal file
261
admin/tool/policy/tests/behat/managepolicies.feature
Normal file
@ -0,0 +1,261 @@
|
||||
@tool @tool_policy
|
||||
Feature: Manage policies
|
||||
In order to manage policies
|
||||
As a manager
|
||||
I need to be able to create and edit site policies
|
||||
|
||||
Background:
|
||||
Given the following config values are set as admin:
|
||||
| sitepolicyhandler | tool_policy |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| user1 | User | One | one@example.com |
|
||||
| user2 | User | Two | two@example.com |
|
||||
| manager | Max | Manager | man@example.com |
|
||||
And the following "role assigns" exist:
|
||||
| user | role | contextlevel | reference |
|
||||
| manager | manager | System | |
|
||||
|
||||
Scenario: Create new policy and save as draft
|
||||
When I log in as "manager"
|
||||
And I navigate to "Privacy and policies > Manage policies" in site administration
|
||||
And I follow "New policy"
|
||||
And I set the following fields to these values:
|
||||
| Name | Policy1 |
|
||||
| Version | v1 |
|
||||
| Summary | Policy summary |
|
||||
| Full policy | Full text |
|
||||
And the field "Type" matches value "Site policy"
|
||||
And the field "User consent" matches value "All users"
|
||||
And the field "status" matches value "0"
|
||||
And "Draft" "field" should exist
|
||||
And "Active" "field" should exist
|
||||
And "Minor change" "field" should not exist
|
||||
And I should not see "Minor change"
|
||||
And "Save as draft" "button" should not exist
|
||||
And I press "Save"
|
||||
Then the following should exist in the "tool-policy-managedocs-wrapper" table:
|
||||
| Name | Policy status | Version | Agreements |
|
||||
| Policy1 Site policy, All users | Draft | v1 | N/A |
|
||||
And I log out
|
||||
|
||||
Scenario: Create new policy and save as active
|
||||
When I log in as "admin"
|
||||
# TODO MDL-61844 change to manager!
|
||||
And I navigate to "Privacy and policies > Manage policies" in site administration
|
||||
And I follow "New policy"
|
||||
And I set the following fields to these values:
|
||||
| Name | Policy1 |
|
||||
| Version | v1 |
|
||||
| Summary | Policy summary |
|
||||
| Full policy | Full text |
|
||||
| Active | 1 |
|
||||
And I press "Save"
|
||||
Then the following should exist in the "tool-policy-managedocs-wrapper" table:
|
||||
| Name | Policy status | Version | Agreements |
|
||||
| Policy1 Site policy, All users | Active | v1 | 0 of 4 (0%) |
|
||||
And I log out
|
||||
|
||||
Scenario: Edit active policy and save as minor change
|
||||
Given the following policies exist:
|
||||
| Name | Revision | Content | Summary | Status |
|
||||
| Policy1 | v1 | full text2 | short text2 | active |
|
||||
And I log in as "manager"
|
||||
And I press "Next"
|
||||
And I set the field "I agree to the Policy1" to "1"
|
||||
And I press "Next"
|
||||
And I navigate to "Privacy and policies > Manage policies" in site administration
|
||||
And I open the action menu in "Policy1" "table_row"
|
||||
And I click on "Edit" "link" in the "Policy1" "table_row"
|
||||
And "Draft" "field" should not exist
|
||||
And "Active" "field" should not exist
|
||||
And "Minor change" "field" should exist
|
||||
And "Save as draft" "button" should exist
|
||||
And I set the field "Version" to "v1 amended"
|
||||
And I set the field "Minor change" to "1"
|
||||
And I press "Save"
|
||||
Then the following should exist in the "tool-policy-managedocs-wrapper" table:
|
||||
| Name | Policy status | Version | Agreements |
|
||||
| Policy1 Site policy, All users | Active | v1 amended | 1 of 4 (25%) |
|
||||
And I log out
|
||||
|
||||
Scenario: Edit active policy and save as draft
|
||||
Given the following policies exist:
|
||||
| Name | Revision | Content | Summary | Status |
|
||||
| Policy1 | v1 | full text2 | short text2 | active |
|
||||
And I log in as "manager"
|
||||
And I press "Next"
|
||||
And I set the field "I agree to the Policy1" to "1"
|
||||
And I press "Next"
|
||||
And I navigate to "Privacy and policies > Manage policies" in site administration
|
||||
And I open the action menu in "Policy1" "table_row"
|
||||
And I click on "Edit" "link" in the "Policy1" "table_row"
|
||||
And I set the field "Version" to "v2"
|
||||
And I press "Save as draft"
|
||||
Then the following should exist in the "tool-policy-managedocs-wrapper" table:
|
||||
| Name | Policy status | Version | Agreements |
|
||||
| Policy1 Site policy, All users | Active | v1 | 1 of 4 (25%) |
|
||||
| Policy1 Site policy, All users | Draft | v2 | N/A |
|
||||
And I log out
|
||||
|
||||
Scenario: Edit active policy and save as new active version
|
||||
Given the following policies exist:
|
||||
| Name | Revision | Content | Summary | Status |
|
||||
| Policy1 | v1 | full text2 | short text2 | active |
|
||||
And I log in as "manager"
|
||||
And I press "Next"
|
||||
And I set the field "I agree to the Policy1" to "1"
|
||||
And I press "Next"
|
||||
And I navigate to "Privacy and policies > Manage policies" in site administration
|
||||
And I open the action menu in "Policy1" "table_row"
|
||||
And I click on "Edit" "link" in the "Policy1" "table_row"
|
||||
And I set the field "Name" to "Policy2"
|
||||
And I set the field "Version" to "v2"
|
||||
And I press "Save"
|
||||
Then the following should exist in the "tool-policy-managedocs-wrapper" table:
|
||||
| Name | Policy status | Version | Agreements |
|
||||
| Policy2 Site policy, All users | Active | v2 | 0 of 4 (0%) |
|
||||
And I should not see "Policy1"
|
||||
And I should not see "v1"
|
||||
And I open the action menu in "Policy2" "table_row"
|
||||
And I click on "View previous versions" "link" in the "Policy2" "table_row"
|
||||
And I should see "Policy2 previous versions"
|
||||
And I should not see "v2"
|
||||
Then the following should exist in the "tool-policy-managedocs-wrapper" table:
|
||||
| Name | Policy status | Version | Agreements |
|
||||
| Policy1 Site policy, All users | Inactive | v1 | 1 of 4 (25%) |
|
||||
And I log out
|
||||
|
||||
Scenario: Edit draft policy and save as draft
|
||||
Given the following policies exist:
|
||||
| Name | Revision | Content | Summary | Status |
|
||||
| Policy1 | v1 | full text2 | short text2 | draft |
|
||||
And I log in as "manager"
|
||||
And I navigate to "Privacy and policies > Manage policies" in site administration
|
||||
And I open the action menu in "Policy1" "table_row"
|
||||
And I click on "Edit" "link" in the "Policy1" "table_row"
|
||||
And I set the field "Version" to "v2"
|
||||
And "Draft" "field" should exist
|
||||
And "Active" "field" should exist
|
||||
And "Minor change" "field" should not exist
|
||||
And I should not see "Minor change"
|
||||
And "Save as draft" "button" should not exist
|
||||
And I press "Save"
|
||||
Then the following should exist in the "tool-policy-managedocs-wrapper" table:
|
||||
| Name | Policy status | Version | Agreements |
|
||||
| Policy1 Site policy, All users | Draft | v2 | N/A |
|
||||
And I should not see "v1"
|
||||
And I open the action menu in "Policy1" "table_row"
|
||||
And "View previous versions" "link" should not exist
|
||||
And I log out
|
||||
|
||||
Scenario: Edit draft policy and save as active
|
||||
Given the following policies exist:
|
||||
| Name | Revision | Content | Summary | Status |
|
||||
| Policy1 | v1 | full text2 | short text2 | draft |
|
||||
And I log in as "admin"
|
||||
# TODO MDL-61844 change to manager!
|
||||
And I navigate to "Privacy and policies > Manage policies" in site administration
|
||||
And I open the action menu in "Policy1" "table_row"
|
||||
And I click on "Edit" "link" in the "Policy1" "table_row"
|
||||
And I set the field "Version" to "v2"
|
||||
And I set the field "Active" to "1"
|
||||
And I press "Save"
|
||||
Then the following should exist in the "tool-policy-managedocs-wrapper" table:
|
||||
| Name | Policy status | Version | Agreements |
|
||||
| Policy1 Site policy, All users | Active | v2 | 0 of 4 (0%) |
|
||||
And I should not see "v1"
|
||||
And I open the action menu in "Policy1" "table_row"
|
||||
And "View previous versions" "link" should not exist
|
||||
And I log out
|
||||
|
||||
Scenario: Activate draft policy
|
||||
Given the following policies exist:
|
||||
| Name | Revision | Content | Summary | Status |
|
||||
| Policy1 | v1 | full text2 | short text2 | draft |
|
||||
And I log in as "admin"
|
||||
# TODO MDL-61844 change to manager!
|
||||
And I navigate to "Privacy and policies > Manage policies" in site administration
|
||||
And I open the action menu in "Policy1" "table_row"
|
||||
And I click on "Set status to \"Active\"" "link" in the "Policy1" "table_row"
|
||||
Then I should see "All users will be required to accept this new policy version to be able to use the site"
|
||||
And I press "Continue"
|
||||
And the following should exist in the "tool-policy-managedocs-wrapper" table:
|
||||
| Name | Policy status | Version | Agreements |
|
||||
| Policy1 Site policy, All users | Active | v1 | 0 of 4 (0%) |
|
||||
And I open the action menu in "Policy1" "table_row"
|
||||
And "View previous versions" "link" should not exist
|
||||
And I log out
|
||||
|
||||
Scenario: Edit archived policy and save as draft
|
||||
Given the following policies exist:
|
||||
| Name | Revision | Content | Summary | Status |
|
||||
| Policy1 | v1 | full text2 | short text2 | active |
|
||||
And I log in as "manager"
|
||||
And I press "Next"
|
||||
And I set the field "I agree to the Policy1" to "1"
|
||||
And I press "Next"
|
||||
And I navigate to "Privacy and policies > Manage policies" in site administration
|
||||
And I open the action menu in "Policy1" "table_row"
|
||||
And I click on "Set status to \"Inactive\"" "link" in the "Policy1" "table_row"
|
||||
Then I should see "The policy will not apply until some version is made the current one"
|
||||
And I press "Continue"
|
||||
And the following should exist in the "tool-policy-managedocs-wrapper" table:
|
||||
| Name | Policy status | Version | Agreements |
|
||||
| Policy1 Site policy, All users | Inactive | v1 | 1 of 4 (25%) |
|
||||
And I open the action menu in "Policy1" "table_row"
|
||||
And I click on "Create a new \"Draft\"" "link" in the "Policy1" "table_row"
|
||||
And I set the field "Version" to "v2"
|
||||
And I set the field "Name" to "Policy2"
|
||||
And the field "status" matches value "0"
|
||||
And "Draft" "field" should exist
|
||||
And "Active" "field" should exist
|
||||
And "Minor change" "field" should not exist
|
||||
And I should not see "Minor change"
|
||||
And "Save as draft" "button" should not exist
|
||||
And I press "Save"
|
||||
And the following should exist in the "tool-policy-managedocs-wrapper" table:
|
||||
| Name | Policy status | Version | Agreements |
|
||||
| Policy2 Site policy, All users | Draft | v2 | N/A |
|
||||
And I should not see "v1"
|
||||
And I should not see "Policy1"
|
||||
And I open the action menu in "Policy2" "table_row"
|
||||
And I click on "View previous versions" "link" in the "Policy2" "table_row"
|
||||
And I should see "Policy2 previous versions"
|
||||
And the following should exist in the "tool-policy-managedocs-wrapper" table:
|
||||
| Name | Policy status | Version | Agreements |
|
||||
| Policy1 Site policy, All users | Inactive | v1 | 1 of 4 (25%) |
|
||||
And I should not see "v2"
|
||||
And I log out
|
||||
|
||||
Scenario: Edit archived policy and save as active
|
||||
Given the following policies exist:
|
||||
| Name | Revision | Content | Summary | Status |
|
||||
| Policy1 | v1 | full text2 | short text2 | active |
|
||||
And I log in as "manager"
|
||||
And I press "Next"
|
||||
And I set the field "I agree to the Policy1" to "1"
|
||||
And I press "Next"
|
||||
And I navigate to "Privacy and policies > Manage policies" in site administration
|
||||
And I open the action menu in "Policy1" "table_row"
|
||||
And I click on "Set status to \"Inactive\"" "link" in the "Policy1" "table_row"
|
||||
And I press "Continue"
|
||||
And I open the action menu in "Policy1" "table_row"
|
||||
And I click on "Create a new \"Draft\"" "link" in the "Policy1" "table_row"
|
||||
And I set the field "Version" to "v2"
|
||||
And I set the field "Name" to "Policy2"
|
||||
And I set the field "Active" to "1"
|
||||
And I press "Save"
|
||||
And the following should exist in the "tool-policy-managedocs-wrapper" table:
|
||||
| Name | Policy status | Version | Agreements |
|
||||
| Policy2 Site policy, All users | Active | v2 | 0 of 4 (0%) |
|
||||
And I should not see "v1"
|
||||
And I should not see "Policy1"
|
||||
And I open the action menu in "Policy2" "table_row"
|
||||
And I click on "View previous versions" "link" in the "Policy2" "table_row"
|
||||
And I should see "Policy2 previous versions"
|
||||
And the following should exist in the "tool-policy-managedocs-wrapper" table:
|
||||
| Name | Policy status | Version | Agreements |
|
||||
| Policy1 Site policy, All users | Inactive | v1 | 1 of 4 (25%) |
|
||||
And I should not see "v2"
|
||||
And I log out
|
53
admin/tool/policy/user.php
Normal file
53
admin/tool/policy/user.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* View user acceptances to the policies
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require(__DIR__.'/../../../config.php');
|
||||
require_once($CFG->dirroot.'/user/editlib.php');
|
||||
|
||||
$userid = optional_param('userid', null, PARAM_INT);
|
||||
$returnurl = optional_param('returnurl', null, PARAM_LOCALURL);
|
||||
|
||||
require_login();
|
||||
$userid = $userid ?: $USER->id;
|
||||
if (isguestuser() || isguestuser($userid)) {
|
||||
print_error('noguest');
|
||||
}
|
||||
$context = context_user::instance($userid);
|
||||
if ($userid != $USER->id) {
|
||||
// Check capability to view acceptances. No capability is needed to view your own acceptances.
|
||||
if (!has_capability('tool/policy:acceptbehalf', $context)) {
|
||||
require_capability('tool/policy:viewacceptances', $context);
|
||||
}
|
||||
}
|
||||
|
||||
$PAGE->set_context($context);
|
||||
$PAGE->set_url(new moodle_url('/admin/tool/policy/user.php', ['userid' => $userid]));
|
||||
|
||||
$output = $PAGE->get_renderer('tool_policy');
|
||||
echo $output->header();
|
||||
echo $output->heading(get_string('policiesagreements', 'tool_policy'));
|
||||
$acceptances = new \tool_policy\output\acceptances($userid, $returnurl);
|
||||
echo $output->render($acceptances);
|
||||
$PAGE->requires->js_call_amd('tool_policy/acceptmodal', 'getInstance', [context_system::instance()->id]);
|
||||
echo $output->footer();
|
@ -1907,8 +1907,8 @@ class core_plugin_manager {
|
||||
'analytics', 'assignmentupgrade', 'availabilityconditions', 'behat', 'capability', 'cohortroles', 'customlang',
|
||||
'dbtransfer', 'filetypes', 'generator', 'health', 'httpsreplace', 'innodb', 'installaddon',
|
||||
'langimport', 'log', 'lp', 'lpimportcsv', 'lpmigrate', 'messageinbound', 'mobile', 'multilangupgrade',
|
||||
'monitor', 'oauth2', 'phpunit', 'profiling', 'recyclebin', 'replace', 'spamcleaner', 'task', 'templatelibrary',
|
||||
'uploadcourse', 'uploaduser', 'unsuproles', 'usertours', 'xmldb'
|
||||
'monitor', 'oauth2', 'phpunit', 'policy', 'profiling', 'recyclebin', 'replace', 'spamcleaner', 'task',
|
||||
'templatelibrary', 'uploadcourse', 'uploaduser', 'unsuproles', 'usertours', 'xmldb'
|
||||
),
|
||||
|
||||
'webservice' => array(
|
||||
|
Loading…
x
Reference in New Issue
Block a user