MDL-62800 tool_policy: Merge the policy tool to 3.4
The following changes has been done from the original repo: - Remove README.md, LICENSE.md and .travis.yml - Review the version.php content, to look like a standard plugin - Adapt jquery-eu-cookie-law-popup.js and readme_moodle.txt to remove the eslint-ignore
@@ -3,6 +3,7 @@
|
||||
*/**/build/
|
||||
node_modules/
|
||||
vendor/
|
||||
admin/tool/policy/amd/src/jquery-eu-cookie-law-popup.js
|
||||
admin/tool/usertours/amd/src/tour.js
|
||||
admin/tool/usertours/amd/src/popper.js
|
||||
auth/cas/CAS/
|
||||
|
||||
@@ -4,6 +4,7 @@ theme/clean/style/custom.css
|
||||
theme/more/style/custom.css
|
||||
node_modules/
|
||||
vendor/
|
||||
admin/tool/policy/amd/src/jquery-eu-cookie-law-popup.js
|
||||
admin/tool/usertours/amd/src/tour.js
|
||||
admin/tool/usertours/amd/src/popper.js
|
||||
auth/cas/CAS/
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
<?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 or revoke 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);
|
||||
$action = optional_param('action', null, PARAM_ALPHA);
|
||||
|
||||
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, 'action' => $action]);
|
||||
$form->set_data(['returnurl' => $returnurl]);
|
||||
|
||||
if ($form->is_cancelled()) {
|
||||
redirect($returnurl);
|
||||
} else if ($form->get_data()) {
|
||||
$form->process();
|
||||
redirect($returnurl);
|
||||
}
|
||||
|
||||
if ($action == 'revoke') {
|
||||
$title = get_string('revokedetails', 'tool_policy');
|
||||
} else {
|
||||
$title = get_string('consentdetails', 'tool_policy');
|
||||
}
|
||||
|
||||
$output = $PAGE->get_renderer('tool_policy');
|
||||
echo $output->header();
|
||||
echo $output->heading($title);
|
||||
$form->display();
|
||||
echo $output->footer();
|
||||
@@ -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();
|
||||
@@ -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()}}});
|
||||
@@ -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)}}});
|
||||
@@ -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"},{key:"revokedetails",component:"tool_policy"},{key:"irevokethepolicy",component:"tool_policy"}],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){for(var f,g=a.split("&"),h=0;h<g.length;h++){var i=g[h].split("=");"action"==i[0]&&(f=i[1])}b.get_strings(this.stringKeys).done(function(b){var e,g;"revoke"==f?(e=b[4],g=b[5]):(e=b[0],g=b[1]),c.create({type:c.types.SAVE_CANCEL,title:e,body:""},d).done(function(b){this.modal=b,this.setupFormModal(a,g)}.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){return new i(a)}}});
|
||||
@@ -0,0 +1 @@
|
||||
define(["jquery"],function(a){window.console||(window.console={}),window.console.log||(window.console.log=function(){}),a.fn.euCookieLawPopup=function(){var b=this;b.params={cookiePolicyUrl:"http://www.wimagguc.com/?cookie-policy",popupPosition:"top",colorStyle:"default",compactStyle:!1,popupTitle:"This website is using cookies",popupText:"We use cookies to ensure that we give you the best experience on our website. If you continue without changing your settings, we'll assume that you are happy to receive all cookies on this website.",buttonContinueTitle:"Continue",buttonLearnmoreTitle:"Learn more",buttonLearnmoreOpenInNewWindow:!0,agreementExpiresInDays:30,autoAcceptCookiePolicy:!1,htmlMarkup:null},b.vars={INITIALISED:!1,HTML_MARKUP:null,COOKIE_NAME:"EU_COOKIE_LAW_CONSENT"};var c=function(c,d,e){if(c){var f=a(c).attr("class")?a(c).attr("class"):"";f.indexOf("eupopup-top")>-1?b.params.popupPosition="top":f.indexOf("eupopup-fixedtop")>-1?b.params.popupPosition="fixedtop":f.indexOf("eupopup-bottomright")>-1?b.params.popupPosition="bottomright":f.indexOf("eupopup-bottomleft")>-1?b.params.popupPosition="bottomleft":f.indexOf("eupopup-bottom")>-1?b.params.popupPosition="bottom":f.indexOf("eupopup-block")>-1&&(b.params.popupPosition="block"),f.indexOf("eupopup-color-default")>-1?b.params.colorStyle="default":f.indexOf("eupopup-color-inverse")>-1&&(b.params.colorStyle="inverse"),f.indexOf("eupopup-style-compact")>-1&&(b.params.compactStyle=!0)}d&&(b.params.htmlMarkup=d),e&&("undefined"!=typeof e.cookiePolicyUrl&&(b.params.cookiePolicyUrl=e.cookiePolicyUrl),"undefined"!=typeof e.popupPosition&&(b.params.popupPosition=e.popupPosition),"undefined"!=typeof e.colorStyle&&(b.params.colorStyle=e.colorStyle),"undefined"!=typeof e.popupTitle&&(b.params.popupTitle=e.popupTitle),"undefined"!=typeof e.popupText&&(b.params.popupText=e.popupText),"undefined"!=typeof e.buttonContinueTitle&&(b.params.buttonContinueTitle=e.buttonContinueTitle),"undefined"!=typeof e.buttonLearnmoreTitle&&(b.params.buttonLearnmoreTitle=e.buttonLearnmoreTitle),"undefined"!=typeof e.buttonLearnmoreOpenInNewWindow&&(b.params.buttonLearnmoreOpenInNewWindow=e.buttonLearnmoreOpenInNewWindow),"undefined"!=typeof e.agreementExpiresInDays&&(b.params.agreementExpiresInDays=e.agreementExpiresInDays),"undefined"!=typeof e.autoAcceptCookiePolicy&&(b.params.autoAcceptCookiePolicy=e.autoAcceptCookiePolicy),"undefined"!=typeof e.htmlMarkup&&(b.params.htmlMarkup=e.htmlMarkup))},d=function(){if(b.params.htmlMarkup)return b.params.htmlMarkup;var a='<div class="eupopup-container eupopup-container-'+b.params.popupPosition+(b.params.compactStyle?" eupopup-style-compact":"")+" eupopup-color-"+b.params.colorStyle+'"><div class="eupopup-head">'+b.params.popupTitle+'</div><div class="eupopup-body">'+b.params.popupText+'</div><div class="eupopup-buttons"><a href="#" class="eupopup-button eupopup-button_1">'+b.params.buttonContinueTitle+'</a><a href="'+b.params.cookiePolicyUrl+'"'+(b.params.buttonLearnmoreOpenInNewWindow?" target=_blank ":"")+' class="eupopup-button eupopup-button_2">'+b.params.buttonLearnmoreTitle+'</a><div class="clearfix"></div></div><a href="#" class="eupopup-closebutton">x</a></div>';return a},e=function(c){var d=new Date,e=24*b.params.agreementExpiresInDays*60*60*1e3;d.setTime(d.getTime()+e);var f="expires="+d.toGMTString();document.cookie=b.vars.COOKIE_NAME+"="+c+"; "+f+";path=/",a(document).trigger("user_cookie_consent_changed",{consent:c})},f=function(){for(var a=!1,c=document.cookie.split(";"),d=0;d<c.length;d++){var e=c[d].trim();0==e.indexOf(b.vars.COOKIE_NAME)&&(a=e.substring(b.vars.COOKIE_NAME.length+1,e.length))}return a},g=function(){a(".eupopup-container").animate({opacity:0,height:0},200,function(){a(".eupopup-container").hide(0)})},h={init:function(h){c(a(".eupopup").first(),a(".eupopup-markup").html(),h),f()||b.vars.INITIALISED||(b.vars.INITIALISED=!0,b.vars.HTML_MARKUP=d(),a(".eupopup-block").length>0?a(".eupopup-block").append(b.vars.HTML_MARKUP):a("BODY").append(b.vars.HTML_MARKUP),a(".eupopup-button_1").click(function(){return e(!0),g(),!1}),a(".eupopup-closebutton").click(function(){return e(!0),g(),!1}),a(".eupopup-container").show(),b.params.autoAcceptCookiePolicy&&e(!0))}};return h}});
|
||||
@@ -0,0 +1 @@
|
||||
define(["jquery","core/log","core/config","core/str","core/modal_factory","core/modal_events"],function(a,b,c,d,e,f){"use strict";function g(a){this.base=a,this.initEvents()}var h={LINKS:"[data-action]",MAKE_CURRENT:'[data-action="makecurrent"]',INACTIVATE:'[data-action="inactivate"]',DELETE:'[data-action="delete"]'};return g.prototype.initEvents=function(){var g=this;g.base.on("click",h.LINKS,function(g){g.stopPropagation();var i,j,k=a(g.currentTarget);if(k.is(h.MAKE_CURRENT))i=d.get_strings([{key:"activating",component:"tool_policy"},{key:"activateconfirm",component:"tool_policy",param:{name:k.closest("[data-policy-name]").attr("data-policy-name"),revision:k.closest("[data-policy-revision]").attr("data-policy-revision")}},{key:"activateconfirmyes",component:"tool_policy"}]);else if(k.is(h.INACTIVATE))i=d.get_strings([{key:"inactivating",component:"tool_policy"},{key:"inactivatingconfirm",component:"tool_policy",param:{name:k.closest("[data-policy-name]").attr("data-policy-name"),revision:k.closest("[data-policy-revision]").attr("data-policy-revision")}},{key:"inactivatingconfirmyes",component:"tool_policy"}]);else{if(!k.is(h.DELETE))return void b.error("unknown action type detected","tool_policy/managedocsactions");i=d.get_strings([{key:"deleting",component:"tool_policy"},{key:"deleteconfirm",component:"tool_policy",param:{name:k.closest("[data-policy-name]").attr("data-policy-name"),revision:k.closest("[data-policy-revision]").attr("data-policy-revision")}},{key:"delete",component:"core"}])}g.preventDefault(),i.then(function(a){return j=a,e.create({title:j[0],body:j[1],type:e.types.SAVE_CANCEL})}).then(function(a){return a.setSaveButtonText(j[2]),a.getRoot().on(f.save,function(){window.location.href=k.attr("href")+"&sesskey="+c.sesskey+"&confirm=1"}),a.getRoot().on(f.hidden,function(){a.destroy()}),a.show(),!0})["catch"](function(a){return b.error(a),!1})})},{init:function(b){var c=a(document.getElementById(b));if(c.length)return new g(c);throw new Error("managedocsactions: Invalid base element identifier")}}});
|
||||
@@ -0,0 +1 @@
|
||||
define(["jquery","core/ajax","core/notification","core/modal_factory","core/modal_events"],function(a,b,c,d,e){var f={VIEW_POLICY:'[data-action="view"]'},g=function(){this.registerEvents()};return g.prototype.registerEvents=function(){a(f.VIEW_POLICY).click(function(f){f.preventDefault();var g=a(this).data("versionid"),h=a(this).data("behalfid"),i={versionid:g,behalfid:h},j={methodname:"tool_policy_get_policy_version",args:i},k=b.call([j]),l="",m=d.types.DEFAULT;a.when(k[0]).then(function(a){return a.result.policy?(l=a.result.policy.name,a.result.policy.content):(c.addNotification({message:a.warnings[0].message,type:"error"}),!1)}).then(function(a){return 0!=a&&d.create({title:l,body:a,type:m,large:!0}).then(function(a){return a.getRoot().on(e.hidden,function(){a.destroy()}),a})}).done(function(a){a.show()}).fail(c.exception)})},{init:function(){return new g}}});
|
||||
@@ -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();
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
@@ -0,0 +1,268 @@
|
||||
// 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'
|
||||
},
|
||||
{
|
||||
key: 'revokedetails',
|
||||
component: 'tool_policy'
|
||||
},
|
||||
{
|
||||
key: 'irevokethepolicy',
|
||||
component: 'tool_policy'
|
||||
}
|
||||
];
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
var action;
|
||||
var params = formData.split('&');
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
var pair = params[i].split('=');
|
||||
if (pair[0] == 'action') {
|
||||
action = pair[1];
|
||||
}
|
||||
}
|
||||
// Fetch the title string.
|
||||
Str.get_strings(this.stringKeys).done(function(strings) {
|
||||
var title;
|
||||
var saveText;
|
||||
if (action == 'revoke') {
|
||||
title = strings[4];
|
||||
saveText = strings[5];
|
||||
} else {
|
||||
title = strings[0];
|
||||
saveText = strings[1];
|
||||
}
|
||||
// Create the modal.
|
||||
ModalFactory.create({
|
||||
type: ModalFactory.types.SAVE_CANCEL,
|
||||
title: title,
|
||||
body: ''
|
||||
}, triggerElement).done(function(modal) {
|
||||
this.modal = modal;
|
||||
this.setupFormModal(formData, saveText);
|
||||
}.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 {int} contextid The contextid for the course.
|
||||
* @return {AcceptOnBehalf}
|
||||
*/
|
||||
getInstance: function(contextid) {
|
||||
return new AcceptOnBehalf(contextid);
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,254 @@
|
||||
/**
|
||||
*
|
||||
* JQUERY EU COOKIE LAW POPUPS
|
||||
* version 1.0.1
|
||||
*
|
||||
* Code on Github:
|
||||
* https://github.com/wimagguc/jquery-eu-cookie-law-popup
|
||||
*
|
||||
* To see a live demo, go to:
|
||||
* http://www.wimagguc.com/2015/03/jquery-eu-cookie-law-popup/
|
||||
*
|
||||
* by Richard Dancsi
|
||||
* http://www.wimagguc.com/
|
||||
*
|
||||
*/
|
||||
|
||||
define(
|
||||
['jquery'],
|
||||
function($) {
|
||||
|
||||
// for ie9 doesn't support debug console >>>
|
||||
if (!window.console) window.console = {};
|
||||
if (!window.console.log) window.console.log = function () { };
|
||||
// ^^^
|
||||
|
||||
$.fn.euCookieLawPopup = (function() {
|
||||
|
||||
var _self = this;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PARAMETERS (MODIFY THIS PART) //////////////////////////////////////////////////////////////
|
||||
_self.params = {
|
||||
cookiePolicyUrl : 'http://www.wimagguc.com/?cookie-policy',
|
||||
popupPosition : 'top',
|
||||
colorStyle : 'default',
|
||||
compactStyle : false,
|
||||
popupTitle : 'This website is using cookies',
|
||||
popupText : 'We use cookies to ensure that we give you the best experience on our website. If you continue without changing your settings, we\'ll assume that you are happy to receive all cookies on this website.',
|
||||
buttonContinueTitle : 'Continue',
|
||||
buttonLearnmoreTitle : 'Learn more',
|
||||
buttonLearnmoreOpenInNewWindow : true,
|
||||
agreementExpiresInDays : 30,
|
||||
autoAcceptCookiePolicy : false,
|
||||
htmlMarkup : null
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// VARIABLES USED BY THE FUNCTION (DON'T MODIFY THIS PART) ////////////////////////////////////
|
||||
_self.vars = {
|
||||
INITIALISED : false,
|
||||
HTML_MARKUP : null,
|
||||
COOKIE_NAME : 'EU_COOKIE_LAW_CONSENT'
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE FUNCTIONS FOR MANIPULATING DATA ////////////////////////////////////////////////////
|
||||
|
||||
// Overwrite default parameters if any of those is present
|
||||
var parseParameters = function(object, markup, settings) {
|
||||
|
||||
if (object) {
|
||||
var className = $(object).attr('class') ? $(object).attr('class') : '';
|
||||
if (className.indexOf('eupopup-top') > -1) {
|
||||
_self.params.popupPosition = 'top';
|
||||
}
|
||||
else if (className.indexOf('eupopup-fixedtop') > -1) {
|
||||
_self.params.popupPosition = 'fixedtop';
|
||||
}
|
||||
else if (className.indexOf('eupopup-bottomright') > -1) {
|
||||
_self.params.popupPosition = 'bottomright';
|
||||
}
|
||||
else if (className.indexOf('eupopup-bottomleft') > -1) {
|
||||
_self.params.popupPosition = 'bottomleft';
|
||||
}
|
||||
else if (className.indexOf('eupopup-bottom') > -1) {
|
||||
_self.params.popupPosition = 'bottom';
|
||||
}
|
||||
else if (className.indexOf('eupopup-block') > -1) {
|
||||
_self.params.popupPosition = 'block';
|
||||
}
|
||||
if (className.indexOf('eupopup-color-default') > -1) {
|
||||
_self.params.colorStyle = 'default';
|
||||
}
|
||||
else if (className.indexOf('eupopup-color-inverse') > -1) {
|
||||
_self.params.colorStyle = 'inverse';
|
||||
}
|
||||
if (className.indexOf('eupopup-style-compact') > -1) {
|
||||
_self.params.compactStyle = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (markup) {
|
||||
_self.params.htmlMarkup = markup;
|
||||
}
|
||||
|
||||
if (settings) {
|
||||
if (typeof settings.cookiePolicyUrl !== 'undefined') {
|
||||
_self.params.cookiePolicyUrl = settings.cookiePolicyUrl;
|
||||
}
|
||||
if (typeof settings.popupPosition !== 'undefined') {
|
||||
_self.params.popupPosition = settings.popupPosition;
|
||||
}
|
||||
if (typeof settings.colorStyle !== 'undefined') {
|
||||
_self.params.colorStyle = settings.colorStyle;
|
||||
}
|
||||
if (typeof settings.popupTitle !== 'undefined') {
|
||||
_self.params.popupTitle = settings.popupTitle;
|
||||
}
|
||||
if (typeof settings.popupText !== 'undefined') {
|
||||
_self.params.popupText = settings.popupText;
|
||||
}
|
||||
if (typeof settings.buttonContinueTitle !== 'undefined') {
|
||||
_self.params.buttonContinueTitle = settings.buttonContinueTitle;
|
||||
}
|
||||
if (typeof settings.buttonLearnmoreTitle !== 'undefined') {
|
||||
_self.params.buttonLearnmoreTitle = settings.buttonLearnmoreTitle;
|
||||
}
|
||||
if (typeof settings.buttonLearnmoreOpenInNewWindow !== 'undefined') {
|
||||
_self.params.buttonLearnmoreOpenInNewWindow = settings.buttonLearnmoreOpenInNewWindow;
|
||||
}
|
||||
if (typeof settings.agreementExpiresInDays !== 'undefined') {
|
||||
_self.params.agreementExpiresInDays = settings.agreementExpiresInDays;
|
||||
}
|
||||
if (typeof settings.autoAcceptCookiePolicy !== 'undefined') {
|
||||
_self.params.autoAcceptCookiePolicy = settings.autoAcceptCookiePolicy;
|
||||
}
|
||||
if (typeof settings.htmlMarkup !== 'undefined') {
|
||||
_self.params.htmlMarkup = settings.htmlMarkup;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
var createHtmlMarkup = function() {
|
||||
|
||||
if (_self.params.htmlMarkup) {
|
||||
return _self.params.htmlMarkup;
|
||||
}
|
||||
|
||||
var html =
|
||||
'<div class="eupopup-container' +
|
||||
' eupopup-container-' + _self.params.popupPosition +
|
||||
(_self.params.compactStyle ? ' eupopup-style-compact' : '') +
|
||||
' eupopup-color-' + _self.params.colorStyle + '">' +
|
||||
'<div class="eupopup-head">' + _self.params.popupTitle + '</div>' +
|
||||
'<div class="eupopup-body">' + _self.params.popupText + '</div>' +
|
||||
'<div class="eupopup-buttons">' +
|
||||
'<a href="#" class="eupopup-button eupopup-button_1">' + _self.params.buttonContinueTitle + '</a>' +
|
||||
'<a href="' + _self.params.cookiePolicyUrl + '"' +
|
||||
(_self.params.buttonLearnmoreOpenInNewWindow ? ' target=_blank ' : '') +
|
||||
' class="eupopup-button eupopup-button_2">' + _self.params.buttonLearnmoreTitle + '</a>' +
|
||||
'<div class="clearfix"></div>' +
|
||||
'</div>' +
|
||||
'<a href="#" class="eupopup-closebutton">x</a>' +
|
||||
'</div>';
|
||||
|
||||
return html;
|
||||
};
|
||||
|
||||
// Storing the consent in a cookie
|
||||
var setUserAcceptsCookies = function(consent) {
|
||||
var d = new Date();
|
||||
var expiresInDays = _self.params.agreementExpiresInDays * 24 * 60 * 60 * 1000;
|
||||
d.setTime( d.getTime() + expiresInDays );
|
||||
var expires = "expires=" + d.toGMTString();
|
||||
document.cookie = _self.vars.COOKIE_NAME + '=' + consent + "; " + expires + ";path=/";
|
||||
|
||||
$(document).trigger("user_cookie_consent_changed", {'consent' : consent});
|
||||
};
|
||||
|
||||
// Let's see if we have a consent cookie already
|
||||
var userAlreadyAcceptedCookies = function() {
|
||||
var userAcceptedCookies = false;
|
||||
var cookies = document.cookie.split(";");
|
||||
for (var i = 0; i < cookies.length; i++) {
|
||||
var c = cookies[i].trim();
|
||||
if (c.indexOf(_self.vars.COOKIE_NAME) == 0) {
|
||||
userAcceptedCookies = c.substring(_self.vars.COOKIE_NAME.length + 1, c.length);
|
||||
}
|
||||
}
|
||||
|
||||
return userAcceptedCookies;
|
||||
};
|
||||
|
||||
var hideContainer = function() {
|
||||
// $('.eupopup-container').slideUp(200);
|
||||
$('.eupopup-container').animate({
|
||||
opacity: 0,
|
||||
height: 0
|
||||
}, 200, function() {
|
||||
$('.eupopup-container').hide(0);
|
||||
});
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////
|
||||
var publicfunc = {
|
||||
|
||||
// INITIALIZE EU COOKIE LAW POPUP /////////////////////////////////////////////////////////
|
||||
init : function(settings) {
|
||||
|
||||
parseParameters(
|
||||
$(".eupopup").first(),
|
||||
$(".eupopup-markup").html(),
|
||||
settings);
|
||||
|
||||
// No need to display this if user already accepted the policy
|
||||
if (userAlreadyAcceptedCookies()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We should initialise only once
|
||||
if (_self.vars.INITIALISED) {
|
||||
return;
|
||||
}
|
||||
_self.vars.INITIALISED = true;
|
||||
|
||||
// Markup and event listeners >>>
|
||||
_self.vars.HTML_MARKUP = createHtmlMarkup();
|
||||
|
||||
if ($('.eupopup-block').length > 0) {
|
||||
$('.eupopup-block').append(_self.vars.HTML_MARKUP);
|
||||
} else {
|
||||
$('BODY').append(_self.vars.HTML_MARKUP);
|
||||
}
|
||||
|
||||
$('.eupopup-button_1').click(function() {
|
||||
setUserAcceptsCookies(true);
|
||||
hideContainer();
|
||||
return false;
|
||||
});
|
||||
$('.eupopup-closebutton').click(function() {
|
||||
setUserAcceptsCookies(true);
|
||||
hideContainer();
|
||||
return false;
|
||||
});
|
||||
// ^^^ Markup and event listeners
|
||||
|
||||
// Ready to start!
|
||||
$('.eupopup-container').show();
|
||||
|
||||
// In case it's alright to just display the message once
|
||||
if (_self.params.autoAcceptCookiePolicy) {
|
||||
setUserAcceptsCookies(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return publicfunc;
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,154 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* Adds support for confirmation via JS modal for some management actions at the Manage policies page.
|
||||
*
|
||||
* @module tool_policy/managedocsactions
|
||||
* @package tool_policy
|
||||
* @copyright 2018 David Mudrák <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'core/log',
|
||||
'core/config',
|
||||
'core/str',
|
||||
'core/modal_factory',
|
||||
'core/modal_events'
|
||||
], function($, Log, Config, Str, ModalFactory, ModalEvents) {
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* List of action selectors.
|
||||
*
|
||||
* @property {string} LINKS - Selector for all action links
|
||||
* @property {string} MAKE_CURRENT
|
||||
*/
|
||||
var ACTION = {
|
||||
LINKS: '[data-action]',
|
||||
MAKE_CURRENT: '[data-action="makecurrent"]',
|
||||
INACTIVATE: '[data-action="inactivate"]',
|
||||
DELETE: '[data-action="delete"]'
|
||||
};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {Element} base - Management area wrapping element
|
||||
*/
|
||||
function ManageDocsActions(base) {
|
||||
this.base = base;
|
||||
|
||||
this.initEvents();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register event listeners.
|
||||
*/
|
||||
ManageDocsActions.prototype.initEvents = function() {
|
||||
var self = this;
|
||||
|
||||
self.base.on('click', ACTION.LINKS, function(e) {
|
||||
e.stopPropagation();
|
||||
|
||||
var link = $(e.currentTarget);
|
||||
var promise;
|
||||
var strings;
|
||||
|
||||
if (link.is(ACTION.MAKE_CURRENT)) {
|
||||
promise = Str.get_strings([
|
||||
{key: 'activating', component: 'tool_policy'},
|
||||
{key: 'activateconfirm', component: 'tool_policy', param: {
|
||||
name: link.closest('[data-policy-name]').attr('data-policy-name'),
|
||||
revision: link.closest('[data-policy-revision]').attr('data-policy-revision')
|
||||
}},
|
||||
{key: 'activateconfirmyes', component: 'tool_policy'}
|
||||
]);
|
||||
|
||||
} else if (link.is(ACTION.INACTIVATE)) {
|
||||
promise = Str.get_strings([
|
||||
{key: 'inactivating', component: 'tool_policy'},
|
||||
{key: 'inactivatingconfirm', component: 'tool_policy', param: {
|
||||
name: link.closest('[data-policy-name]').attr('data-policy-name'),
|
||||
revision: link.closest('[data-policy-revision]').attr('data-policy-revision')
|
||||
}},
|
||||
{key: 'inactivatingconfirmyes', component: 'tool_policy'}
|
||||
]);
|
||||
|
||||
} else if (link.is(ACTION.DELETE)) {
|
||||
promise = Str.get_strings([
|
||||
{key: 'deleting', component: 'tool_policy'},
|
||||
{key: 'deleteconfirm', component: 'tool_policy', param: {
|
||||
name: link.closest('[data-policy-name]').attr('data-policy-name'),
|
||||
revision: link.closest('[data-policy-revision]').attr('data-policy-revision')
|
||||
}},
|
||||
{key: 'delete', component: 'core'}
|
||||
]);
|
||||
|
||||
} else {
|
||||
Log.error('unknown action type detected', 'tool_policy/managedocsactions');
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
promise.then(function(strs) {
|
||||
strings = strs;
|
||||
return ModalFactory.create({
|
||||
title: strings[0],
|
||||
body: strings[1],
|
||||
type: ModalFactory.types.SAVE_CANCEL
|
||||
});
|
||||
|
||||
}).then(function(modal) {
|
||||
modal.setSaveButtonText(strings[2]);
|
||||
modal.getRoot().on(ModalEvents.save, function() {
|
||||
window.location.href = link.attr('href') + '&sesskey=' + Config.sesskey + '&confirm=1';
|
||||
});
|
||||
|
||||
modal.getRoot().on(ModalEvents.hidden, function() {
|
||||
modal.destroy();
|
||||
});
|
||||
|
||||
modal.show();
|
||||
return true;
|
||||
|
||||
}).catch(function(e) {
|
||||
Log.error(e);
|
||||
return false;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
/**
|
||||
* Factory method returning instance of the ManageDocsActions
|
||||
*
|
||||
* @param {String} baseid - ID of the management area wrapping element
|
||||
* @return {ManageDocsActions}
|
||||
*/
|
||||
init: function(baseid) {
|
||||
var base = $(document.getElementById(baseid));
|
||||
|
||||
if (base.length) {
|
||||
return new ManageDocsActions(base);
|
||||
|
||||
} else {
|
||||
throw new Error("managedocsactions: Invalid base element identifier");
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,122 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* Policy actions.
|
||||
*
|
||||
* @module tool_policy/policyactions
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Sara Arjona ([email protected])
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'core/ajax',
|
||||
'core/notification',
|
||||
'core/modal_factory',
|
||||
'core/modal_events'],
|
||||
function($, Ajax, Notification, ModalFactory, ModalEvents) {
|
||||
|
||||
/**
|
||||
* List of action selectors.
|
||||
*
|
||||
* @type {{VIEW_POLICY: string}}
|
||||
*/
|
||||
var ACTIONS = {
|
||||
VIEW_POLICY: '[data-action="view"]'
|
||||
};
|
||||
|
||||
/**
|
||||
* PolicyActions class.
|
||||
*/
|
||||
var PolicyActions = function() {
|
||||
this.registerEvents();
|
||||
};
|
||||
|
||||
/**
|
||||
* Register event listeners.
|
||||
*/
|
||||
PolicyActions.prototype.registerEvents = function() {
|
||||
$(ACTIONS.VIEW_POLICY).click(function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var versionid = $(this).data('versionid');
|
||||
var behalfid = $(this).data('behalfid');
|
||||
|
||||
var params = {
|
||||
'versionid': versionid,
|
||||
'behalfid': behalfid
|
||||
};
|
||||
|
||||
var request = {
|
||||
methodname: 'tool_policy_get_policy_version',
|
||||
args: params
|
||||
};
|
||||
|
||||
var promises = Ajax.call([request]);
|
||||
var modalTitle = '';
|
||||
var modalType = ModalFactory.types.DEFAULT;
|
||||
$.when(promises[0]).then(function(data) {
|
||||
if (data.result.policy) {
|
||||
modalTitle = data.result.policy.name;
|
||||
return data.result.policy.content;
|
||||
}
|
||||
// Fail.
|
||||
Notification.addNotification({
|
||||
message: data.warnings[0].message,
|
||||
type: 'error'
|
||||
});
|
||||
return false;
|
||||
|
||||
}).then(function(html) {
|
||||
if (html != false) {
|
||||
return ModalFactory.create({
|
||||
title: modalTitle,
|
||||
body: html,
|
||||
type: modalType,
|
||||
large: true
|
||||
}).then(function(modal) {
|
||||
// Handle hidden event.
|
||||
modal.getRoot().on(ModalEvents.hidden, function() {
|
||||
// Destroy when hidden.
|
||||
modal.destroy();
|
||||
});
|
||||
|
||||
return modal;
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}).done(function(modal) {
|
||||
// Show the modal.
|
||||
modal.show();
|
||||
}).fail(Notification.exception);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
return /** @alias module:tool_policy/policyactions */ {
|
||||
// Public variables and functions.
|
||||
|
||||
/**
|
||||
* Initialise the actions helper.
|
||||
*
|
||||
* @method init
|
||||
* @return {PolicyActions}
|
||||
*/
|
||||
'init': function() {
|
||||
return new PolicyActions();
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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}'";
|
||||
}
|
||||
}
|
||||
@@ -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}'";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Class containing the external API functions functions for the Policy tool.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Sara Arjona ([email protected])
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_policy;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use coding_exception;
|
||||
use context_system;
|
||||
use context_user;
|
||||
use core\invalid_persistent_exception;
|
||||
use dml_exception;
|
||||
use external_api;
|
||||
use external_description;
|
||||
use external_function_parameters;
|
||||
use external_single_structure;
|
||||
use external_value;
|
||||
use external_warnings;
|
||||
use invalid_parameter_exception;
|
||||
use moodle_exception;
|
||||
use restricted_context_exception;
|
||||
use tool_policy\api;
|
||||
use tool_policy\form\accept_policy;
|
||||
|
||||
/**
|
||||
* Class external.
|
||||
*
|
||||
* The external API for the Policy tool.
|
||||
*
|
||||
* @copyright 2018 Sara Arjona ([email protected])
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class external extends external_api {
|
||||
|
||||
/**
|
||||
* Parameter description for get_policy_version_parameters().
|
||||
*
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function get_policy_version_parameters() {
|
||||
return new external_function_parameters([
|
||||
'versionid' => new external_value(PARAM_INT, 'The policy version ID', VALUE_REQUIRED),
|
||||
'behalfid' => new external_value(PARAM_INT, 'The id of user on whose behalf the user is viewing the policy',
|
||||
VALUE_DEFAULT, 0)
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the details of a policy version.
|
||||
*
|
||||
* @param int $versionid The policy version ID.
|
||||
* @param int $behalfid The id of user on whose behalf the user is viewing the policy.
|
||||
* @return array
|
||||
* @throws coding_exception
|
||||
* @throws dml_exception
|
||||
* @throws invalid_parameter_exception
|
||||
* @throws restricted_context_exception
|
||||
* @throws moodle_exception
|
||||
*/
|
||||
public static function get_policy_version($versionid, $behalfid = null) {
|
||||
global $PAGE;
|
||||
|
||||
$result = [];
|
||||
$warnings = [];
|
||||
$params = external_api::validate_parameters(self::get_policy_version_parameters(), [
|
||||
'versionid' => $versionid,
|
||||
'behalfid' => $behalfid
|
||||
]);
|
||||
$versionid = $params['versionid'];
|
||||
$behalfid = $params['behalfid'];
|
||||
|
||||
$context = context_system::instance();
|
||||
$PAGE->set_context($context);
|
||||
|
||||
try {
|
||||
// Validate if the user has access to the policy version.
|
||||
$version = api::get_policy_version($versionid);
|
||||
if (!api::can_user_view_policy_version($version, $behalfid)) {
|
||||
$warnings[] = [
|
||||
'item' => $versionid,
|
||||
'warningcode' => 'errorusercantviewpolicyversion',
|
||||
'message' => get_string('errorusercantviewpolicyversion', 'tool_policy')
|
||||
];
|
||||
} else if (!empty($version)) {
|
||||
$version = api::get_policy_version($versionid);
|
||||
$policy['name'] = $version->name;
|
||||
$policy['versionid'] = $versionid;
|
||||
list($policy['content'], $notusedformat) = external_format_text(
|
||||
$version->content,
|
||||
$version->contentformat,
|
||||
SYSCONTEXTID,
|
||||
'tool_policy',
|
||||
'policydocumentcontent',
|
||||
$version->id
|
||||
);
|
||||
$result['policy'] = $policy;
|
||||
}
|
||||
} catch (moodle_exception $e) {
|
||||
$warnings[] = [
|
||||
'item' => $versionid,
|
||||
'warningcode' => 'errorpolicyversionnotfound',
|
||||
'message' => get_string('errorpolicyversionnotfound', 'tool_policy')
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'result' => $result,
|
||||
'warnings' => $warnings
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameter description for get_policy_version().
|
||||
*
|
||||
* @return external_description
|
||||
*/
|
||||
public static function get_policy_version_returns() {
|
||||
return new external_single_structure([
|
||||
'result' => new external_single_structure([
|
||||
'policy' => new external_single_structure([
|
||||
'name' => new external_value(PARAM_RAW, 'The policy version name', VALUE_OPTIONAL),
|
||||
'versionid' => new external_value(PARAM_INT, 'The policy version id', VALUE_OPTIONAL),
|
||||
'content' => new external_value(PARAM_RAW, 'The policy version content', VALUE_OPTIONAL)
|
||||
], 'Policy information', VALUE_OPTIONAL)
|
||||
]),
|
||||
'warnings' => new external_warnings()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes the parameters for submit_create_group_form webservice.
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function submit_accept_on_behalf_parameters() {
|
||||
return new external_function_parameters(
|
||||
array(
|
||||
'jsonformdata' => new external_value(PARAM_RAW, 'The data from the create group form, encoded as a json array')
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit the create group form.
|
||||
*
|
||||
* @param string $jsonformdata The data from the form, encoded as a json array.
|
||||
* @return int new group id.
|
||||
*/
|
||||
public static function submit_accept_on_behalf($jsonformdata) {
|
||||
// We always must pass webservice params through validate_parameters.
|
||||
$params = self::validate_parameters(self::submit_accept_on_behalf_parameters(),
|
||||
['jsonformdata' => $jsonformdata]);
|
||||
|
||||
self::validate_context(context_system::instance());
|
||||
|
||||
$serialiseddata = json_decode($params['jsonformdata']);
|
||||
|
||||
$data = array();
|
||||
parse_str($serialiseddata, $data);
|
||||
|
||||
// The last param is the ajax submitted data.
|
||||
$mform = new accept_policy(null, $data, 'post', '', null, true, $data);
|
||||
|
||||
// Do the action.
|
||||
$mform->process();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of method result value.
|
||||
*
|
||||
* @return external_description
|
||||
* @since Moodle 3.0
|
||||
*/
|
||||
public static function submit_accept_on_behalf_returns() {
|
||||
return new external_value(PARAM_BOOL, 'success');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
<?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 or revoking 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');
|
||||
}
|
||||
$revoke = (!empty($this->_customdata['action']) && $this->_customdata['action'] == 'revoke');
|
||||
$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, $revoke);
|
||||
$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));
|
||||
|
||||
if ($revoke) {
|
||||
$mform->addElement('static', 'ack', '', get_string('revokeacknowledgement', 'tool_policy'));
|
||||
$mform->addElement('hidden', 'action', 'revoke');
|
||||
$mform->setType('action', PARAM_ALPHA);
|
||||
} else {
|
||||
$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'])) {
|
||||
if ($revoke) {
|
||||
$this->add_action_buttons(true, get_string('irevokethepolicy', 'tool_policy'));
|
||||
} else {
|
||||
$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
|
||||
* @param boolean $revoke True if policies will be revoked; false when policies will be accepted.
|
||||
* @return array (userid=>username)
|
||||
*/
|
||||
protected function validate_and_get_users($userids, $revoke = false) {
|
||||
global $DB;
|
||||
$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);
|
||||
|
||||
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');
|
||||
}
|
||||
\context_helper::preload_from_record($user);
|
||||
if ($revoke) {
|
||||
api::can_revoke_policies($userid, true);
|
||||
} else {
|
||||
api::can_accept_policies($userid, true);
|
||||
}
|
||||
$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()) {
|
||||
$revoke = (!empty($data->action) && $data->action == 'revoke');
|
||||
foreach ($data->userids as $userid) {
|
||||
if ($revoke) {
|
||||
foreach ($data->versionids as $versionid) {
|
||||
\tool_policy\api::revoke_acceptance($versionid, $userid, $data->note);
|
||||
}
|
||||
} else {
|
||||
\tool_policy\api::accept_policies($data->versionids, $userid, $data->note);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
<?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\policydoc} class.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @category output
|
||||
* @copyright 2018 David Mudrák <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_policy\form;
|
||||
|
||||
use context_system;
|
||||
use html_writer;
|
||||
use moodleform;
|
||||
use tool_policy\api;
|
||||
use tool_policy\policy_version;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Defines the form for editing a policy document version.
|
||||
*
|
||||
* @copyright 2018 David Mudrak <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class policydoc extends moodleform {
|
||||
|
||||
/**
|
||||
* Defines the form fields.
|
||||
*/
|
||||
public function definition() {
|
||||
|
||||
$mform = $this->_form;
|
||||
$formdata = $this->_customdata['formdata'];
|
||||
|
||||
$mform->addElement('text', 'name', get_string('policydocname', 'tool_policy'), ['maxlength' => 1333]);
|
||||
$mform->settype('name', PARAM_TEXT);
|
||||
$mform->addRule('name', null, 'required', null, 'client');
|
||||
$mform->addRule('name', get_string('maximumchars', '', 1333), 'maxlength', 1333, 'client');
|
||||
|
||||
$options = [];
|
||||
foreach ([policy_version::TYPE_SITE,
|
||||
policy_version::TYPE_PRIVACY,
|
||||
policy_version::TYPE_THIRD_PARTY,
|
||||
policy_version::TYPE_OTHER] as $type) {
|
||||
$options[$type] = get_string('policydoctype'.$type, 'tool_policy');
|
||||
}
|
||||
$mform->addElement('select', 'type', get_string('policydoctype', 'tool_policy'), $options);
|
||||
|
||||
$options = [];
|
||||
foreach ([policy_version::AUDIENCE_ALL,
|
||||
policy_version::AUDIENCE_LOGGEDIN,
|
||||
policy_version::AUDIENCE_GUESTS] as $audience) {
|
||||
$options[$audience] = get_string('policydocaudience'.$audience, 'tool_policy');
|
||||
}
|
||||
$mform->addElement('select', 'audience', get_string('policydocaudience', 'tool_policy'), $options);
|
||||
|
||||
if (empty($formdata->id)) {
|
||||
$default = userdate(time(), get_string('strftimedate', 'core_langconfig'));
|
||||
} else {
|
||||
$default = userdate($formdata->timecreated, get_string('strftimedate', 'core_langconfig'));
|
||||
}
|
||||
$mform->addElement('text', 'revision', get_string('policydocrevision', 'tool_policy'),
|
||||
['maxlength' => 1333, 'placeholder' => $default]);
|
||||
$mform->settype('revision', PARAM_TEXT);
|
||||
$mform->addRule('revision', get_string('maximumchars', '', 1333), 'maxlength', 1333, 'client');
|
||||
|
||||
$mform->addElement('editor', 'summary_editor', get_string('policydocsummary', 'tool_policy'), ['rows' => 7],
|
||||
api::policy_summary_field_options());
|
||||
$mform->addRule('summary_editor', null, 'required', null, 'client');
|
||||
|
||||
$mform->addElement('editor', 'content_editor', get_string('policydoccontent', 'tool_policy'), null,
|
||||
api::policy_content_field_options());
|
||||
$mform->addRule('content_editor', null, 'required', null, 'client');
|
||||
|
||||
if (!$formdata->id || $formdata->status == policy_version::STATUS_DRAFT) {
|
||||
// Creating a new version or editing a draft/archived version.
|
||||
$mform->addElement('hidden', 'minorchange');
|
||||
$mform->setType('minorchange', PARAM_INT);
|
||||
|
||||
$statusgrp = [
|
||||
$mform->createElement('radio', 'status', '', get_string('status'.policy_version::STATUS_ACTIVE, 'tool_policy'),
|
||||
policy_version::STATUS_ACTIVE),
|
||||
$mform->createElement('radio', 'status', '', get_string('status'.policy_version::STATUS_DRAFT, 'tool_policy'),
|
||||
policy_version::STATUS_DRAFT),
|
||||
$mform->createElement('static', 'statusinfo', '', html_writer::div(get_string('statusinfo', 'tool_policy'),
|
||||
'muted text-muted')),
|
||||
];
|
||||
$mform->addGroup($statusgrp, null, get_string('status', 'tool_policy'), ['<br>'], false);
|
||||
|
||||
} else {
|
||||
// Editing an active version.
|
||||
$mform->addElement('hidden', 'status', policy_version::STATUS_ACTIVE);
|
||||
$mform->setType('status', PARAM_INT);
|
||||
|
||||
$statusgrp = [
|
||||
$mform->createElement('checkbox', 'minorchange', '', get_string('minorchange', 'tool_policy')),
|
||||
$mform->createElement('static', 'minorchangeinfo', '',
|
||||
html_writer::div(get_string('minorchangeinfo', 'tool_policy'), 'muted text-muted')),
|
||||
];
|
||||
$mform->addGroup($statusgrp, null, get_string('status', 'tool_policy'), ['<br>'], false);
|
||||
}
|
||||
|
||||
// Add "Save" button and, optionally, "Save as draft".
|
||||
$buttonarray = [];
|
||||
$buttonarray[] = $mform->createElement('submit', 'save', get_string('save', 'tool_policy'));
|
||||
if ($formdata->id && $formdata->status == policy_version::STATUS_ACTIVE) {
|
||||
$buttonarray[] = $mform->createElement('submit', 'saveasdraft', get_string('saveasdraft', 'tool_policy'));
|
||||
}
|
||||
$buttonarray[] = $mform->createElement('cancel');
|
||||
$mform->addGroup($buttonarray, 'buttonar', '', array(' '), false);
|
||||
$mform->closeHeaderBefore('buttonar');
|
||||
|
||||
$this->set_data($formdata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Form validation
|
||||
*
|
||||
* @param array $data array of ("fieldname"=>value) of submitted data
|
||||
* @param array $files array of uploaded files "element_name"=>tmp_file_path
|
||||
* @return array of "element_name"=>"error_description" if there are errors,
|
||||
* or an empty array if everything is OK (true allowed for backwards compatibility too).
|
||||
*/
|
||||
public function validation($data, $files) {
|
||||
$errors = parent::validation($data, $files);
|
||||
if (!empty($data['minorchange']) && !empty($data['saveasdraft'])) {
|
||||
// If minorchange is checked and "save as draft" is pressed - return error.
|
||||
$errors['minorchange'] = get_string('errorsaveasdraft', 'tool_policy');
|
||||
}
|
||||
return $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return submitted data if properly submitted or returns NULL if validation fails or
|
||||
* if there is no submitted data.
|
||||
*
|
||||
* @return object submitted data; NULL if not valid or not submitted or cancelled
|
||||
*/
|
||||
public function get_data() {
|
||||
if ($data = parent::get_data()) {
|
||||
if (!empty($data->saveasdraft)) {
|
||||
$data->status = policy_version::STATUS_DRAFT;
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/** @var bool */
|
||||
protected $canrevoke;
|
||||
|
||||
/**
|
||||
* Contructor.
|
||||
*
|
||||
* @param int $userid
|
||||
* @param string|moodle_url $returnurl
|
||||
*/
|
||||
public function __construct($userid, $returnurl = null) {
|
||||
$this->userid = $userid;
|
||||
$this->returnurl = $returnurl ? (new moodle_url($returnurl))->out(false) : null;
|
||||
$this->canrevoke = \tool_policy\api::can_revoke_policies($this->userid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
$data->canrevoke = $this->canrevoke;
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?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\renderer} class.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @category output
|
||||
* @copyright 2018 Sara Arjona <[email protected]>
|
||||
* @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 templatable;
|
||||
use tool_policy\api;
|
||||
use tool_policy\policy_version;
|
||||
|
||||
/**
|
||||
* Renderer for the policies plugin.
|
||||
*
|
||||
* @copyright 2018 Sara Arjona <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class guestconsent implements renderable, templatable {
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
global $PAGE;
|
||||
|
||||
$data = (object) [];
|
||||
$data->pluginbaseurl = (new moodle_url('/admin/tool/policy'))->out(true);
|
||||
if (strpos(qualified_me(), '/tool/policy/view.php') === false) {
|
||||
// Current page is not a policy doc, so returnurl parameter will be it.
|
||||
$data->returnurl = qualified_me();
|
||||
} else {
|
||||
// If current page is also a policy doc to view, get previous returnurl parameter to avoid error.
|
||||
$returnurl = $PAGE->url->get_param('returnurl');
|
||||
if (isset($returnurl)) {
|
||||
$data->returnurl = $returnurl;
|
||||
}
|
||||
}
|
||||
$data->returnurl = urlencode($data->returnurl);
|
||||
|
||||
$policies = api::list_current_versions(policy_version::AUDIENCE_GUESTS);
|
||||
$data->policies = array_values($policies);
|
||||
$data->haspolicies = !empty($policies);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,419 @@
|
||||
<?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\renderer} class.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @category output
|
||||
* @copyright 2018 Sara Arjona <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_policy\output;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use context_system;
|
||||
use core\output\notification;
|
||||
use core\session\manager;
|
||||
use core_user;
|
||||
use html_writer;
|
||||
use moodle_url;
|
||||
use renderable;
|
||||
use renderer_base;
|
||||
use single_button;
|
||||
use templatable;
|
||||
use tool_policy\api;
|
||||
use tool_policy\policy_version;
|
||||
|
||||
/**
|
||||
* Represents a page for showing all the policy documents which a user has to agree to.
|
||||
*
|
||||
* @copyright 2018 Sara Arjona <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class page_agreedocs implements renderable, templatable {
|
||||
|
||||
/** @var array $policies List of public policies objects with information about the user acceptance. */
|
||||
protected $policies = null;
|
||||
|
||||
/** @var array $agreedocs List of policy identifiers which the user has agreed using the form. */
|
||||
protected $agreedocs = null;
|
||||
|
||||
/** @var string $action Form action to identify when user agreeds policies. */
|
||||
protected $action = null;
|
||||
|
||||
/** @var int User id who wants to accept this page. */
|
||||
protected $behalfid = null;
|
||||
|
||||
/** @var object User who wants to accept this page. */
|
||||
protected $behalfuser = null;
|
||||
|
||||
/** @var boolean True if signup user has agreed to all the policies; false otherwise. */
|
||||
protected $signupuserpolicyagreed = false;
|
||||
|
||||
/** @var array Info or error messages to show. */
|
||||
protected $messages = [];
|
||||
|
||||
/** @var bool This is an existing user (rather than non-loggedin/guest). */
|
||||
protected $isexistinguser;
|
||||
|
||||
/**
|
||||
* Prepare the page for rendering.
|
||||
*
|
||||
* @param array $agreedocs Array with the policy identifiers which the user has agreed using the form.
|
||||
* @param int $behalfid The userid to accept the policy versions as (such as child's id).
|
||||
* @param string $action Form action to identify when user agreeds policies.
|
||||
*/
|
||||
public function __construct($agreedocs = null, $behalfid = 0, $action = null) {
|
||||
global $USER;
|
||||
$realuser = manager::get_realuser();
|
||||
|
||||
$this->agreedocs = $agreedocs;
|
||||
if (empty($this->agreedocs)) {
|
||||
$this->agreedocs = [];
|
||||
}
|
||||
|
||||
$this->action = $action;
|
||||
|
||||
$this->isexistinguser = isloggedin() && !isguestuser();
|
||||
$behalfid = $behalfid ?: $USER->id;
|
||||
if ($realuser->id != $behalfid) {
|
||||
$this->behalfuser = core_user::get_user($behalfid, '*', MUST_EXIST);
|
||||
$this->behalfid = $this->behalfuser->id;
|
||||
}
|
||||
|
||||
$this->policies = api::list_current_versions(policy_version::AUDIENCE_LOGGEDIN);
|
||||
if (empty($this->behalfid)) {
|
||||
$userid = $USER->id;
|
||||
} else {
|
||||
$userid = $this->behalfid;
|
||||
}
|
||||
$this->accept_and_revoke_policies();
|
||||
$this->prepare_global_page_access($userid);
|
||||
$this->prepare_user_acceptances($userid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept and revoke the policy versions.
|
||||
* The capabilities for accepting/revoking policies are checked into the api functions.
|
||||
*
|
||||
*/
|
||||
protected function accept_and_revoke_policies() {
|
||||
global $USER;
|
||||
|
||||
if ($this->isexistinguser) {
|
||||
// Existing user.
|
||||
if (!empty($this->action) && confirm_sesskey()) {
|
||||
// The form has been sent. Update policies acceptances according to $this->agreedocs.
|
||||
$lang = current_language();
|
||||
// Accept / revoke policies.
|
||||
$acceptversionids = array();
|
||||
foreach ($this->policies as $policy) {
|
||||
if (in_array($policy->id, $this->agreedocs)) {
|
||||
// Save policy version doc to accept it.
|
||||
$acceptversionids[] = $policy->id;
|
||||
} else {
|
||||
// Revoke policy doc.
|
||||
api::revoke_acceptance($policy->id, $this->behalfid);
|
||||
}
|
||||
}
|
||||
// Accept all policy docs saved in $acceptversionids.
|
||||
api::accept_policies($acceptversionids, $this->behalfid, null, $lang);
|
||||
// Show a message to let know the user he/she must agree all the policies.
|
||||
if (count($acceptversionids) != count($this->policies)) {
|
||||
$message = (object) [
|
||||
'type' => 'error',
|
||||
'text' => get_string('mustagreetocontinue', 'tool_policy')
|
||||
];
|
||||
} else {
|
||||
$message = (object) [
|
||||
'type' => 'success',
|
||||
'text' => get_string('acceptancessavedsucessfully', 'tool_policy')
|
||||
];
|
||||
}
|
||||
$this->messages[] = $message;
|
||||
} else if (!empty($this->policies) && empty($USER->policyagreed)) {
|
||||
// Inform users they must agree to all policies before continuing.
|
||||
$message = (object) [
|
||||
'type' => 'error',
|
||||
'text' => get_string('mustagreetocontinue', 'tool_policy')
|
||||
];
|
||||
$this->messages[] = $message;
|
||||
}
|
||||
} else {
|
||||
// New user.
|
||||
if (!empty($this->action) && confirm_sesskey()) {
|
||||
// The form has been sent.
|
||||
$currentpolicyversionids = [];
|
||||
foreach ($this->policies as $policy) {
|
||||
$currentpolicyversionids[] = $policy->id;
|
||||
}
|
||||
// If the user has accepted all the policies, add it to the session to let continue with the signup process.
|
||||
$this->signupuserpolicyagreed = empty(array_diff($currentpolicyversionids, $this->agreedocs));
|
||||
\cache::make('core', 'presignup')->set('tool_policy_userpolicyagreed',
|
||||
$this->signupuserpolicyagreed);
|
||||
} else if (empty($this->policies)) {
|
||||
// There are no policies to agree to. Update the policyagreed value to avoid show empty consent page.
|
||||
\cache::make('core', 'presignup')->set('tool_policy_userpolicyagreed', 1);
|
||||
}
|
||||
if (!empty($this->policies) && !$this->signupuserpolicyagreed) {
|
||||
// During the signup process, inform users they must agree to all policies before continuing.
|
||||
$message = (object) [
|
||||
'type' => 'error',
|
||||
'text' => get_string('mustagreetocontinue', 'tool_policy')
|
||||
];
|
||||
$this->messages[] = $message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Before display the consent page, the user has to view all the still-non-accepted policy docs.
|
||||
* This function checks if the non-accepted policy docs have been shown and redirect to them.
|
||||
*
|
||||
* @param int $userid User identifier who wants to access to the consent page.
|
||||
* @param moodle_url $returnurl URL to return after shown the policy docs.
|
||||
*/
|
||||
protected function redirect_to_policies($userid, $returnurl = null) {
|
||||
$allpolicies = $this->policies;
|
||||
if ($this->isexistinguser) {
|
||||
$acceptances = api::get_user_acceptances($userid);
|
||||
foreach ($allpolicies as $policy) {
|
||||
if (api::is_user_version_accepted($userid, $policy->id, $acceptances)) {
|
||||
// If this version is accepted by the user, remove from the pending policies list.
|
||||
unset($allpolicies[array_search($policy, $allpolicies)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($allpolicies)) {
|
||||
$currentpolicyversionids = [];
|
||||
foreach ($allpolicies as $policy) {
|
||||
$currentpolicyversionids[] = $policy->id;
|
||||
}
|
||||
|
||||
$cache = \cache::make('core', 'presignup');
|
||||
$cachekey = 'tool_policy_viewedpolicies';
|
||||
|
||||
$viewedpolicies = $cache->get($cachekey);
|
||||
if (!empty($viewedpolicies)) {
|
||||
// Get the list of the policies docs which the user haven't viewed during this session.
|
||||
$pendingpolicies = array_diff($currentpolicyversionids, $viewedpolicies);
|
||||
} else {
|
||||
$pendingpolicies = $currentpolicyversionids;
|
||||
}
|
||||
if (count($pendingpolicies) > 0) {
|
||||
// Still is needed to show some policies docs. Save in the session and redirect.
|
||||
$policyversionid = array_shift($pendingpolicies);
|
||||
$viewedpolicies[] = $policyversionid;
|
||||
$cache->set($cachekey, $viewedpolicies);
|
||||
if (empty($returnurl)) {
|
||||
$returnurl = new moodle_url('/admin/tool/policy/index.php');
|
||||
}
|
||||
$urlparams = ['versionid' => $policyversionid,
|
||||
'returnurl' => $returnurl,
|
||||
'numpolicy' => count($currentpolicyversionids) - count($pendingpolicies),
|
||||
'totalpolicies' => count($currentpolicyversionids),
|
||||
];
|
||||
redirect(new moodle_url('/admin/tool/policy/view.php', $urlparams));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect to signup page if defined or to $CFG->wwwroot if not.
|
||||
*/
|
||||
protected function redirect_to_previous_url() {
|
||||
global $SESSION;
|
||||
|
||||
if ($this->isexistinguser) {
|
||||
// Existing user.
|
||||
if (!empty($SESSION->wantsurl)) {
|
||||
$returnurl = $SESSION->wantsurl;
|
||||
unset($SESSION->wantsurl);
|
||||
} else {
|
||||
$returnurl = new moodle_url('/admin/tool/policy/user.php');
|
||||
}
|
||||
} else {
|
||||
// Non-authenticated user.
|
||||
$issignup = \cache::make('core', 'presignup')->get('tool_policy_issignup');
|
||||
if ($issignup) {
|
||||
// User came here from signup page - redirect back there.
|
||||
$returnurl = new moodle_url('/login/signup.php');
|
||||
\cache::make('core', 'presignup')->set('tool_policy_issignup', false);
|
||||
} else {
|
||||
// Guests should not be on this page unless it's part of signup - redirect home.
|
||||
$returnurl = new moodle_url('/');
|
||||
}
|
||||
}
|
||||
|
||||
redirect($returnurl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the global $PAGE and performs the access checks.
|
||||
*
|
||||
* @param int $userid
|
||||
*/
|
||||
protected function prepare_global_page_access($userid) {
|
||||
global $PAGE, $SITE, $USER;
|
||||
|
||||
// Guest users or not logged users (but the users during the signup process) are not allowed to access to this page.
|
||||
$newsignupuser = \cache::make('core', 'presignup')->get('tool_policy_issignup');
|
||||
if (!$this->isexistinguser && !$newsignupuser) {
|
||||
$this->redirect_to_previous_url();
|
||||
}
|
||||
|
||||
// Check for correct user capabilities.
|
||||
if ($this->isexistinguser) {
|
||||
// For existing users, it's needed to check if they have the capability for accepting policies.
|
||||
api::can_accept_policies($this->behalfid, true);
|
||||
} else {
|
||||
// For new users, the behalfid parameter is ignored.
|
||||
if ($this->behalfid) {
|
||||
redirect(new moodle_url('/admin/tool/policy/index.php'));
|
||||
}
|
||||
}
|
||||
|
||||
// If the current user has the $USER->policyagreed = 1 or $userpolicyagreed = 1
|
||||
// redirect to the return page.
|
||||
$hasagreedsignupuser = !$this->isexistinguser && $this->signupuserpolicyagreed;
|
||||
$hasagreedloggeduser = $USER->id == $userid && !empty($USER->policyagreed);
|
||||
if (!is_siteadmin() && ($hasagreedsignupuser || $hasagreedloggeduser)) {
|
||||
$this->redirect_to_previous_url();
|
||||
}
|
||||
|
||||
$myparams = [];
|
||||
if ($this->isexistinguser && !empty($this->behalfid) && $this->behalfid != $USER->id) {
|
||||
$myparams['userid'] = $this->behalfid;
|
||||
}
|
||||
$myurl = new moodle_url('/admin/tool/policy/index.php', $myparams);
|
||||
|
||||
// Redirect to policy docs before the consent page.
|
||||
$this->redirect_to_policies($userid, $myurl);
|
||||
|
||||
// Page setup.
|
||||
$PAGE->set_context(context_system::instance());
|
||||
$PAGE->set_url($myurl);
|
||||
$PAGE->set_heading($SITE->fullname);
|
||||
$PAGE->set_title(get_string('policiesagreements', 'tool_policy'));
|
||||
$PAGE->navbar->add(get_string('policiesagreements', 'tool_policy'), new moodle_url('/admin/tool/policy/index.php'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare user acceptances.
|
||||
*
|
||||
* @param int $userid
|
||||
*/
|
||||
protected function prepare_user_acceptances($userid) {
|
||||
global $USER;
|
||||
|
||||
// Get all the policy version acceptances for this user.
|
||||
$lang = current_language();
|
||||
foreach ($this->policies as $policy) {
|
||||
// Get a link to display the full policy document.
|
||||
$policy->url = new moodle_url('/admin/tool/policy/view.php',
|
||||
array('policyid' => $policy->policyid, 'returnurl' => qualified_me()));
|
||||
$policyattributes = array('data-action' => 'view',
|
||||
'data-versionid' => $policy->id,
|
||||
'data-behalfid' => $this->behalfid);
|
||||
$policymodal = html_writer::link($policy->url, $policy->name, $policyattributes);
|
||||
|
||||
// Check if this policy version has been agreed or not.
|
||||
if ($this->isexistinguser) {
|
||||
// Existing user.
|
||||
$versionagreed = false;
|
||||
$acceptances = api::get_user_acceptances($userid);
|
||||
$policy->versionacceptance = api::get_user_version_acceptance($userid, $policy->id, $acceptances);
|
||||
if (!empty($policy->versionacceptance)) {
|
||||
// The policy version has ever been agreed. Check if status = 1 to know if still is accepted.
|
||||
$versionagreed = $policy->versionacceptance->status;
|
||||
if ($versionagreed) {
|
||||
if ($policy->versionacceptance->lang != $lang) {
|
||||
// Add a message because this version has been accepted in a different language than the current one.
|
||||
$policy->versionlangsagreed = get_string('policyversionacceptedinotherlang', 'tool_policy');
|
||||
}
|
||||
if ($policy->versionacceptance->usermodified != $userid && $USER->id == $userid) {
|
||||
// Add a message because this version has been accepted in behalf of current user.
|
||||
$policy->versionbehalfsagreed = get_string('policyversionacceptedinbehalf', 'tool_policy');
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// New user.
|
||||
$versionagreed = in_array($policy->id, $this->agreedocs);
|
||||
}
|
||||
$policy->versionagreed = $versionagreed;
|
||||
$policy->policylink = html_writer::link($policy->url, $policy->name);
|
||||
$policy->policymodal = $policymodal;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
global $USER;
|
||||
|
||||
$myparams = [];
|
||||
if ($this->isexistinguser && !empty($this->behalfid) && $this->behalfid != $USER->id) {
|
||||
$myparams['userid'] = $this->behalfid;
|
||||
}
|
||||
$data = (object) [
|
||||
'pluginbaseurl' => (new moodle_url('/admin/tool/policy'))->out(false),
|
||||
'myurl' => (new moodle_url('/admin/tool/policy/index.php', $myparams))->out(false),
|
||||
'sesskey' => sesskey(),
|
||||
];
|
||||
|
||||
if (!empty($this->messages)) {
|
||||
foreach ($this->messages as $message) {
|
||||
switch ($message->type) {
|
||||
case 'error':
|
||||
$data->messages[] = $output->notification($message->text, notification::NOTIFY_ERROR);
|
||||
break;
|
||||
|
||||
case 'success':
|
||||
$data->messages[] = $output->notification($message->text, notification::NOTIFY_SUCCESS);
|
||||
break;
|
||||
|
||||
default:
|
||||
$data->messages[] = $output->notification($message->text, notification::NOTIFY_INFO);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$data->policies = array_values($this->policies);
|
||||
|
||||
// If viewing docs in behalf of other user, get his/her full name and profile link.
|
||||
if (!empty($this->behalfuser)) {
|
||||
$userfullname = fullname($this->behalfuser, has_capability('moodle/site:viewfullnames', \context_system::instance()) ||
|
||||
has_capability('moodle/site:viewfullnames', \context_user::instance($this->behalfid)));
|
||||
$data->behalfuser = html_writer::link(\context_user::instance($this->behalfid)->get_url(), $userfullname);
|
||||
}
|
||||
|
||||
// User can cancel accepting policies only if it is a part of signup.
|
||||
$data->cancancel = !isloggedin() || isguestuser();
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
<?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\page_managedocs_list} class.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @category output
|
||||
* @copyright 2018 David Mudrák <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_policy\output;
|
||||
|
||||
use html_writer;
|
||||
use tool_policy\api;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use action_menu;
|
||||
use action_menu_link;
|
||||
use moodle_url;
|
||||
use pix_icon;
|
||||
use renderable;
|
||||
use renderer_base;
|
||||
use single_button;
|
||||
use templatable;
|
||||
use tool_policy\policy_version;
|
||||
|
||||
/**
|
||||
* Represents a management page with the list of policy documents.
|
||||
*
|
||||
* The page displays all policy documents in their sort order, together with draft future versions.
|
||||
*
|
||||
* @copyright 2018 David Mudrak <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class page_managedocs_list implements renderable, templatable {
|
||||
|
||||
/** @var int */
|
||||
protected $policyid = null;
|
||||
/** @var moodle_url */
|
||||
protected $returnurl = null;
|
||||
|
||||
/**
|
||||
* page_managedocs_list constructor.
|
||||
* @param int $policyid when specified only archived versions of this policy will be displayed.
|
||||
*/
|
||||
public function __construct($policyid = null) {
|
||||
$this->policyid = $policyid;
|
||||
$this->returnurl = new moodle_url('/admin/tool/policy/managedocs.php');
|
||||
if ($this->policyid) {
|
||||
$this->returnurl->param('archived', $this->policyid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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->pluginbaseurl = (new moodle_url('/admin/tool/policy'))->out(false);
|
||||
$data->canmanage = has_capability('tool/policy:managedocs', \context_system::instance());
|
||||
$data->canaddnew = $data->canmanage && !$this->policyid;
|
||||
$data->canviewacceptances = has_capability('tool/policy:viewacceptances', \context_system::instance());
|
||||
$data->title = get_string('policiesagreements', 'tool_policy');
|
||||
$data->policies = [];
|
||||
|
||||
if ($this->policyid) {
|
||||
// We are only interested in the archived versions of the given policy.
|
||||
$data->backurl = (new moodle_url('/admin/tool/policy/managedocs.php'))->out(false);
|
||||
$policy = api::list_policies([$this->policyid], true)[0];
|
||||
if ($firstversion = $policy->currentversion ?: (reset($policy->draftversions) ?: reset($policy->archivedversions))) {
|
||||
$data->title = get_string('previousversions', 'tool_policy', format_string($firstversion->name));
|
||||
}
|
||||
|
||||
foreach ($policy->archivedversions as $i => $version) {
|
||||
$data->versions[] = $this->export_version_for_template($output, $policy, $version,
|
||||
false, false, false);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
// List all policies. Display current and all draft versions of each policy in this list.
|
||||
// If none found, then show only one archived version.
|
||||
$policies = api::list_policies(null, true);
|
||||
foreach ($policies as $i => $policy) {
|
||||
|
||||
if (empty($policy->currentversion) && empty($policy->draftversions)) {
|
||||
// There is no current and no draft versions, display the first archived version.
|
||||
$firstpolicy = array_shift($policy->archivedversions);
|
||||
$data->versions[] = $this->export_version_for_template($output, $policy, $firstpolicy,
|
||||
false, $i > 0, $i < count($policies) - 1);
|
||||
}
|
||||
|
||||
if (!empty($policy->currentversion)) {
|
||||
|
||||
// Current version of the policy.
|
||||
$data->versions[] = $this->export_version_for_template($output, $policy, $policy->currentversion,
|
||||
false, $i > 0, $i < count($policies) - 1);
|
||||
|
||||
} else if ($policy->draftversions) {
|
||||
|
||||
// There is no current version, display the first draft version as the current.
|
||||
$firstpolicy = array_shift($policy->draftversions);
|
||||
$data->versions[] = $this->export_version_for_template($output, $policy, $firstpolicy,
|
||||
false, $i > 0, $i < count($policies) - 1);
|
||||
}
|
||||
|
||||
foreach ($policy->draftversions as $draft) {
|
||||
// Show all [other] draft policies indented.
|
||||
$data->versions[] = $this->export_version_for_template($output, $policy, $draft,
|
||||
true, false, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports one version for the list of policies
|
||||
*
|
||||
* @param \renderer_base $output
|
||||
* @param \stdClass $policy
|
||||
* @param \stdClass $version
|
||||
* @param bool $isindented display indented (normally drafts of the current version)
|
||||
* @param bool $moveup can move up
|
||||
* @param bool $movedown can move down
|
||||
* @return \stdClass
|
||||
*/
|
||||
protected function export_version_for_template($output, $policy, $version, $isindented, $moveup, $movedown) {
|
||||
|
||||
$status = $version->status;
|
||||
$version->statustext = get_string('status' . $status, 'tool_policy');
|
||||
|
||||
if ($status == policy_version::STATUS_ACTIVE) {
|
||||
$version->statustext = html_writer::span($version->statustext, 'label label-success');
|
||||
} else if ($status == policy_version::STATUS_DRAFT) {
|
||||
$version->statustext = html_writer::span($version->statustext, 'label label-warning');
|
||||
} else {
|
||||
$version->statustext = html_writer::span($version->statustext, 'label');
|
||||
}
|
||||
|
||||
$version->indented = $isindented;
|
||||
|
||||
$editbaseurl = new moodle_url('/admin/tool/policy/editpolicydoc.php', [
|
||||
'sesskey' => sesskey(),
|
||||
'policyid' => $policy->id,
|
||||
'returnurl' => $this->returnurl->out_as_local_url(false),
|
||||
]);
|
||||
|
||||
$viewurl = new moodle_url('/admin/tool/policy/view.php', [
|
||||
'policyid' => $policy->id,
|
||||
'versionid' => $version->id,
|
||||
'manage' => 1,
|
||||
'returnurl' => $this->returnurl->out_as_local_url(false),
|
||||
]);
|
||||
|
||||
$actionmenu = new action_menu();
|
||||
$actionmenu->set_menu_trigger(get_string('actions', 'tool_policy'));
|
||||
$actionmenu->set_alignment(action_menu::TL, action_menu::BL);
|
||||
$actionmenu->prioritise = true;
|
||||
if ($moveup) {
|
||||
$actionmenu->add(new action_menu_link(
|
||||
new moodle_url($editbaseurl, ['moveup' => $policy->id]),
|
||||
new pix_icon('t/up', get_string('moveup', 'tool_policy')),
|
||||
get_string('moveup', 'tool_policy'),
|
||||
true
|
||||
));
|
||||
}
|
||||
if ($movedown) {
|
||||
$actionmenu->add(new action_menu_link(
|
||||
new moodle_url($editbaseurl, ['movedown' => $policy->id]),
|
||||
new pix_icon('t/down', get_string('movedown', 'tool_policy')),
|
||||
get_string('movedown', 'tool_policy'),
|
||||
true
|
||||
));
|
||||
}
|
||||
$actionmenu->add(new action_menu_link(
|
||||
$viewurl,
|
||||
null,
|
||||
get_string('view'),
|
||||
false
|
||||
));
|
||||
if ($status != policy_version::STATUS_ARCHIVED) {
|
||||
$actionmenu->add(new action_menu_link(
|
||||
new moodle_url($editbaseurl, ['versionid' => $version->id]),
|
||||
null,
|
||||
get_string('edit'),
|
||||
false
|
||||
));
|
||||
}
|
||||
if ($status == policy_version::STATUS_ACTIVE) {
|
||||
$actionmenu->add(new action_menu_link(
|
||||
new moodle_url($editbaseurl, ['inactivate' => $policy->id]),
|
||||
null,
|
||||
get_string('inactivate', 'tool_policy'),
|
||||
false,
|
||||
['data-action' => 'inactivate']
|
||||
));
|
||||
}
|
||||
if ($status == policy_version::STATUS_DRAFT) {
|
||||
$actionmenu->add(new action_menu_link(
|
||||
new moodle_url($editbaseurl, ['makecurrent' => $version->id]),
|
||||
null,
|
||||
get_string('activate', 'tool_policy'),
|
||||
false,
|
||||
['data-action' => 'makecurrent']
|
||||
));
|
||||
}
|
||||
if (api::can_delete_version($version)) {
|
||||
$actionmenu->add(new action_menu_link(
|
||||
new moodle_url($editbaseurl, ['delete' => $version->id]),
|
||||
null,
|
||||
get_string('delete'),
|
||||
false,
|
||||
['data-action' => 'delete']
|
||||
));
|
||||
}
|
||||
if ($status == policy_version::STATUS_ARCHIVED) {
|
||||
$actionmenu->add(new action_menu_link(
|
||||
new moodle_url($editbaseurl, ['versionid' => $version->id]),
|
||||
null,
|
||||
get_string('settodraft', 'tool_policy'),
|
||||
false
|
||||
));
|
||||
}
|
||||
if (!$this->policyid && !$isindented && $policy->archivedversions &&
|
||||
($status != policy_version::STATUS_ARCHIVED || count($policy->archivedversions) > 1)) {
|
||||
$actionmenu->add(new action_menu_link(
|
||||
new moodle_url('/admin/tool/policy/managedocs.php', ['archived' => $policy->id]),
|
||||
null,
|
||||
get_string('viewarchived', 'tool_policy'),
|
||||
false
|
||||
));
|
||||
}
|
||||
|
||||
$version->actionmenu = $actionmenu->export_for_template($output);
|
||||
return $version;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
<?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\renderer} class.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @category output
|
||||
* @copyright 2018 Sara Arjona <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_policy\output;
|
||||
|
||||
use core\session\manager;
|
||||
use moodle_exception;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use context_system;
|
||||
use core_user;
|
||||
use html_writer;
|
||||
use moodle_url;
|
||||
use renderable;
|
||||
use renderer_base;
|
||||
use templatable;
|
||||
use tool_policy\api;
|
||||
use tool_policy\policy_version;
|
||||
|
||||
/**
|
||||
* Represents a page for showing the error messages.
|
||||
*
|
||||
* This is used when a user has no permission to agree to policies or accept policies on behalf of defined behalfid.
|
||||
*
|
||||
* @copyright 2018 Sara Arjona <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class page_nopermission implements renderable, templatable {
|
||||
|
||||
/** @var int User id who wants to view this page. */
|
||||
protected $behalfid = null;
|
||||
|
||||
/** @var object User who wants to accept this page. */
|
||||
protected $behalfuser = null;
|
||||
|
||||
/** @var bool True if user has permission to accept policy documents; false otherwise. */
|
||||
protected $haspermissionagreedocs = true;
|
||||
|
||||
/** @var array $policies List of public policies objects. */
|
||||
protected $policies = null;
|
||||
|
||||
/**
|
||||
* Prepare the page for rendering.
|
||||
*
|
||||
* @param int $behalfid The userid to consent policies as (such as child's id).
|
||||
*/
|
||||
public function __construct($behalfid) {
|
||||
global $USER;
|
||||
|
||||
$behalfid = $behalfid ?: $USER->id;
|
||||
$realuser = manager::get_realuser();
|
||||
if ($realuser->id != $behalfid) {
|
||||
$this->behalfuser = core_user::get_user($behalfid, '*', MUST_EXIST);
|
||||
$this->behalfid = $this->behalfuser->id;
|
||||
}
|
||||
|
||||
if (!empty($USER->id)) {
|
||||
// For existing users, it's needed to check if they have the capability for accepting policies.
|
||||
$this->haspermissionagreedocs = api::can_accept_policies($this->behalfid);
|
||||
}
|
||||
|
||||
$this->policies = api::list_current_versions(policy_version::AUDIENCE_LOGGEDIN);
|
||||
|
||||
if (empty($this->policies) && !empty($USER->id)) {
|
||||
// Existing user without policies to agree to.
|
||||
$currentuser = (!empty($this->behalfuser)) ? $this->behalfuser : $USER;
|
||||
if (!$currentuser->policyagreed) {
|
||||
// If there are no policies to agreed, change $user->policyagreed to true.
|
||||
api::update_policyagreed($currentuser);
|
||||
}
|
||||
}
|
||||
|
||||
$this->prepare_global_page_access();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the global $PAGE and performs the access checks.
|
||||
*/
|
||||
protected function prepare_global_page_access() {
|
||||
global $PAGE, $SITE, $USER;
|
||||
|
||||
$myurl = new moodle_url('/admin/tool/policy/index.php', [
|
||||
'behalfid' => $this->behalfid,
|
||||
]);
|
||||
|
||||
if (isguestuser() || empty($USER->id) || !$USER->policyagreed) {
|
||||
// Disable notifications for new users, guests or users who haven't agreed to the policies.
|
||||
$PAGE->set_popup_notification_allowed(false);
|
||||
}
|
||||
$PAGE->set_context(context_system::instance());
|
||||
$PAGE->set_pagelayout('standard');
|
||||
$PAGE->set_url($myurl);
|
||||
$PAGE->set_heading($SITE->fullname);
|
||||
$PAGE->set_title(get_string('policiesagreements', 'tool_policy'));
|
||||
$PAGE->navbar->add(get_string('policiesagreements', 'tool_policy'), new moodle_url('/admin/tool/policy/index.php'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
global $CFG;
|
||||
|
||||
$data = (object) [
|
||||
'pluginbaseurl' => (new moodle_url('/admin/tool/policy'))->out(false),
|
||||
'haspermissionagreedocs' => $this->haspermissionagreedocs,
|
||||
'supportname' => $CFG->supportname,
|
||||
'supportemail' => $CFG->supportemail,
|
||||
];
|
||||
|
||||
// Get the messages to display.
|
||||
$messagetitle = null;
|
||||
$messagedesc = null;
|
||||
if (!$this->haspermissionagreedocs) {
|
||||
if (!empty($this->behalfuser)) {
|
||||
// If viewing docs in behalf of other user, get his/her full name and profile link.
|
||||
$userfullname = fullname($this->behalfuser, has_capability('moodle/site:viewfullnames', \context_system::instance())
|
||||
|| has_capability('moodle/site:viewfullnames', \context_user::instance($this->behalfid)));
|
||||
$data->behalfuser = html_writer::link(\context_user::instance($this->behalfid)->get_url(), $userfullname);
|
||||
|
||||
$messagetitle = get_string('nopermissiontoagreedocsbehalf', 'tool_policy');
|
||||
$messagedesc = get_string('nopermissiontoagreedocsbehalf_desc', 'tool_policy', $data->behalfuser);
|
||||
} else {
|
||||
$messagetitle = get_string('nopermissiontoagreedocs', 'tool_policy');
|
||||
$messagedesc = get_string('nopermissiontoagreedocs_desc', 'tool_policy');
|
||||
}
|
||||
}
|
||||
$data->messagetitle = $messagetitle;
|
||||
$data->messagedesc = $messagedesc;
|
||||
|
||||
// Add policies list.
|
||||
$policieslinks = array();
|
||||
foreach ($this->policies as $policyversion) {
|
||||
// Get a link to display the full policy document.
|
||||
$policyurl = new moodle_url('/admin/tool/policy/view.php',
|
||||
array('policyid' => $policyversion->policyid, 'returnurl' => qualified_me()));
|
||||
$policyattributes = array('data-action' => 'view',
|
||||
'data-versionid' => $policyversion->id,
|
||||
'data-behalfid' => $this->behalfid);
|
||||
$policieslinks[] = html_writer::link($policyurl, $policyversion->name, $policyattributes);
|
||||
}
|
||||
$data->policies = $policieslinks;
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
<?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\renderer} class.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @category output
|
||||
* @copyright 2018 Sara Arjona <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_policy\output;
|
||||
|
||||
use moodle_exception;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once("$CFG->libdir/filelib.php");
|
||||
|
||||
use context_system;
|
||||
use moodle_url;
|
||||
use renderable;
|
||||
use renderer_base;
|
||||
use single_button;
|
||||
use templatable;
|
||||
use tool_policy\api;
|
||||
use tool_policy\policy_version;
|
||||
|
||||
/**
|
||||
* Represents a page for showing all the policy documents with a current version.
|
||||
*
|
||||
* @copyright 2018 Sara Arjona <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class page_viewalldoc implements renderable, templatable {
|
||||
|
||||
/**
|
||||
* Prepare the page for rendering.
|
||||
*
|
||||
*/
|
||||
public function __construct() {
|
||||
|
||||
$this->prepare_global_page_access();
|
||||
$this->prepare_policies();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the policy versions to display on the page.
|
||||
*
|
||||
*/
|
||||
protected function prepare_policies() {
|
||||
$this->policies = api::list_current_versions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the global $PAGE and performs the access checks.
|
||||
*/
|
||||
protected function prepare_global_page_access() {
|
||||
global $PAGE, $SITE, $USER;
|
||||
|
||||
$myurl = new moodle_url('/admin/tool/policy/viewall.php', []);
|
||||
|
||||
// Disable notifications for new users, guests or users who haven't agreed to the policies.
|
||||
if (isguestuser() || empty($USER->id) || !$USER->policyagreed) {
|
||||
$PAGE->set_popup_notification_allowed(false);
|
||||
}
|
||||
|
||||
$PAGE->set_context(context_system::instance());
|
||||
$PAGE->set_pagelayout('popup');
|
||||
$PAGE->set_url($myurl);
|
||||
$PAGE->set_heading($SITE->fullname);
|
||||
$PAGE->set_title(get_string('policiesagreements', 'tool_policy'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) [
|
||||
'pluginbaseurl' => (new moodle_url('/admin/tool/policy'))->out(false),
|
||||
];
|
||||
|
||||
$data->policies = array_values($this->policies);
|
||||
|
||||
array_walk($data->policies, function($item, $key) {
|
||||
$item->policytypestr = get_string('policydoctype'.$item->type, 'tool_policy');
|
||||
$item->policyaudiencestr = get_string('policydocaudience'.$item->audience, 'tool_policy');
|
||||
});
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
<?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\renderer} class.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @category output
|
||||
* @copyright 2018 Sara Arjona <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_policy\output;
|
||||
|
||||
use moodle_exception;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use context_system;
|
||||
use moodle_url;
|
||||
use renderable;
|
||||
use renderer_base;
|
||||
use single_button;
|
||||
use templatable;
|
||||
use tool_policy\api;
|
||||
use tool_policy\policy_version;
|
||||
|
||||
/**
|
||||
* Represents a page for showing the given policy document version.
|
||||
*
|
||||
* @copyright 2018 Sara Arjona <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class page_viewdoc implements renderable, templatable {
|
||||
|
||||
/** @var stdClass Exported {@link \tool_policy\policy_version_exporter} to display on this page. */
|
||||
protected $policy;
|
||||
|
||||
/** @var string Return URL. */
|
||||
protected $returnurl = null;
|
||||
|
||||
/** @var int User id who wants to view this page. */
|
||||
protected $behalfid = null;
|
||||
|
||||
/**
|
||||
* Prepare the page for rendering.
|
||||
*
|
||||
* @param int $policyid The policy id for this page.
|
||||
* @param int $versionid The version id to show. Empty tries to load the current one.
|
||||
* @param string $returnurl URL of a page to continue after reading the policy text.
|
||||
* @param int $behalfid The userid to view this policy version as (such as child's id).
|
||||
* @param bool $manage View the policy as a part of the management UI.
|
||||
* @param int $numpolicy Position of the current policy with respect to the total of policy docs to display.
|
||||
* @param int $totalpolicies Total number of policy documents which the user has to agree to.
|
||||
*/
|
||||
public function __construct($policyid, $versionid, $returnurl, $behalfid, $manage, $numpolicy = 0, $totalpolicies = 0) {
|
||||
|
||||
$this->returnurl = $returnurl;
|
||||
$this->behalfid = $behalfid;
|
||||
$this->manage = $manage;
|
||||
$this->numpolicy = $numpolicy;
|
||||
$this->totalpolicies = $totalpolicies;
|
||||
|
||||
$this->prepare_policy($policyid, $versionid);
|
||||
$this->prepare_global_page_access();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the policy version to display on the page.
|
||||
*
|
||||
* @param int $policyid The policy id for this page.
|
||||
* @param int $versionid The version id to show. Empty tries to load the current one.
|
||||
*/
|
||||
protected function prepare_policy($policyid, $versionid) {
|
||||
|
||||
if ($versionid) {
|
||||
$this->policy = api::get_policy_version($versionid);
|
||||
|
||||
} else {
|
||||
$this->policy = array_reduce(api::list_current_versions(), function ($carry, $current) use ($policyid) {
|
||||
if ($current->policyid == $policyid) {
|
||||
return $current;
|
||||
}
|
||||
return $carry;
|
||||
});
|
||||
}
|
||||
|
||||
if (empty($this->policy)) {
|
||||
throw new \moodle_exception('errorpolicyversionnotfound', 'tool_policy');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the global $PAGE and performs the access checks.
|
||||
*/
|
||||
protected function prepare_global_page_access() {
|
||||
global $CFG, $PAGE, $SITE, $USER;
|
||||
|
||||
$myurl = new moodle_url('/admin/tool/policy/view.php', [
|
||||
'policyid' => $this->policy->policyid,
|
||||
'versionid' => $this->policy->id,
|
||||
'returnurl' => $this->returnurl,
|
||||
'behalfid' => $this->behalfid,
|
||||
'manage' => $this->manage,
|
||||
'numpolicy' => $this->numpolicy,
|
||||
'totalpolicies' => $this->totalpolicies,
|
||||
]);
|
||||
|
||||
if ($this->manage) {
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
admin_externalpage_setup('tool_policy_managedocs', '', null, $myurl);
|
||||
require_capability('tool/policy:managedocs', context_system::instance());
|
||||
$PAGE->navbar->add(format_string($this->policy->name),
|
||||
new moodle_url('/admin/tool/policy/managedocs.php', ['id' => $this->policy->policyid]));
|
||||
} else {
|
||||
if ($this->policy->status != policy_version::STATUS_ACTIVE) {
|
||||
require_login();
|
||||
} else if (isguestuser() || empty($USER->id) || !$USER->policyagreed) {
|
||||
// Disable notifications for new users, guests or users who haven't agreed to the policies.
|
||||
$PAGE->set_popup_notification_allowed(false);
|
||||
}
|
||||
$PAGE->set_url($myurl);
|
||||
$PAGE->set_heading($SITE->fullname);
|
||||
$PAGE->set_title(get_string('policiesagreements', 'tool_policy'));
|
||||
$PAGE->navbar->add(get_string('policiesagreements', 'tool_policy'), new moodle_url('/admin/tool/policy/index.php'));
|
||||
$PAGE->navbar->add(format_string($this->policy->name));
|
||||
}
|
||||
|
||||
if (!api::can_user_view_policy_version($this->policy, $this->behalfid)) {
|
||||
throw new moodle_exception('accessdenied', 'tool_policy');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) [
|
||||
'pluginbaseurl' => (new moodle_url('/admin/tool/policy'))->out(false),
|
||||
'returnurl' => $this->returnurl ? (new moodle_url($this->returnurl))->out(false) : null,
|
||||
'numpolicy' => $this->numpolicy ? : null,
|
||||
'totalpolicies' => $this->totalpolicies ? : null,
|
||||
];
|
||||
if ($this->manage && $this->policy->status != policy_version::STATUS_ARCHIVED) {
|
||||
$paramsurl = ['policyid' => $this->policy->policyid, 'versionid' => $this->policy->id];
|
||||
$data->editurl = (new moodle_url('/admin/tool/policy/editpolicydoc.php', $paramsurl))->out(false);
|
||||
}
|
||||
|
||||
$data->policy = clone($this->policy);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?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\renderer} class.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @category output
|
||||
* @copyright 2018 David Mudrák <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_policy\output;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use core\output\mustache_template_finder;
|
||||
use plugin_renderer_base;
|
||||
use renderable;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Renderer for the policies plugin.
|
||||
*
|
||||
* @copyright 2018 David Mudrak <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class renderer extends plugin_renderer_base {
|
||||
|
||||
/**
|
||||
* Overrides the parent so that templatable widgets are handled even without their explicit render method.
|
||||
*
|
||||
* @param renderable $widget
|
||||
* @return string
|
||||
*/
|
||||
public function render(renderable $widget) {
|
||||
|
||||
$namespacedclassname = get_class($widget);
|
||||
$plainclassname = preg_replace('/^.*\\\/', '', $namespacedclassname);
|
||||
$rendermethod = 'render_'.$plainclassname;
|
||||
|
||||
if (method_exists($this, $rendermethod)) {
|
||||
// Explicit rendering method exists, fall back to the default behaviour.
|
||||
return parent::render($widget);
|
||||
}
|
||||
|
||||
$interfaces = class_implements($namespacedclassname);
|
||||
|
||||
if (isset($interfaces['templatable'])) {
|
||||
// Default implementation of template-based rendering.
|
||||
$data = $widget->export_for_template($this);
|
||||
return parent::render_from_template('tool_policy/'.$plainclassname, $data);
|
||||
|
||||
} else {
|
||||
return parent::render($widget);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
<?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;
|
||||
|
||||
/** @var bool */
|
||||
protected $canrevoke;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param bool $canrevoke does the current user have permission to revoke the policy on behalf of user $userid
|
||||
*/
|
||||
public function __construct($userid, $accepted, moodle_url $pageurl, $versions, $onbehalf = false,
|
||||
$canaccept = null, $canrevoke = 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 = \tool_policy\api::can_accept_policies($this->userid);
|
||||
}
|
||||
if (count($this->accepted) == count($this->versions) && $canrevoke === null) {
|
||||
$this->canrevoke = \tool_policy\api::can_revoke_policies($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,
|
||||
'canrevoke' => $this->canrevoke,
|
||||
];
|
||||
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);
|
||||
} else if ($data['status'] && $this->canrevoke) {
|
||||
$linkparams = ['userids[0]' => $this->userid];
|
||||
foreach (array_keys($this->versions) as $versionid) {
|
||||
$linkparams["versionids[{$versionid}]"] = $versionid;
|
||||
}
|
||||
$linkparams['returnurl'] = $this->pageurl->out_as_local_url(false);
|
||||
$linkparams['action'] = 'revoke';
|
||||
$link = new \moodle_url('/admin/tool/policy/accept.php', $linkparams);
|
||||
$data['revokelink'] = $link->out(false);
|
||||
}
|
||||
$data['singleversion'] = count($this->versions) == 1;
|
||||
if ($data['singleversion']) {
|
||||
$firstversion = reset($this->versions);
|
||||
$data['versionname'] = $firstversion;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Provides the {@link tool_policy\policy_exporter} class.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 David Mudrak <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_policy;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use core\external\exporter;
|
||||
use renderer_base;
|
||||
|
||||
/**
|
||||
* Exporter of a policy document model.
|
||||
*
|
||||
* @copyright 2018 David Mudrak <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class policy_exporter extends exporter {
|
||||
|
||||
/**
|
||||
* Return the list of properties.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function define_properties() {
|
||||
return [
|
||||
'id' => [
|
||||
'type' => PARAM_INT,
|
||||
],
|
||||
'sortorder' => [
|
||||
'type' => PARAM_INT,
|
||||
'default' => 999,
|
||||
],
|
||||
'currentversionid' => [
|
||||
'type' => PARAM_INT,
|
||||
'null' => NULL_ALLOWED,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of objects that are related.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function define_related() {
|
||||
return [
|
||||
'versions' => 'tool_policy\policy_version_exporter[]',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of additional, generated dynamically from the given properties.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function define_other_properties() {
|
||||
return [
|
||||
'currentversion' => [
|
||||
'type' => policy_version_exporter::read_properties_definition(),
|
||||
'null' => NULL_ALLOWED,
|
||||
],
|
||||
'draftversions' => [
|
||||
'type' => policy_version_exporter::read_properties_definition(),
|
||||
'multiple' => true,
|
||||
],
|
||||
'archivedversions' => [
|
||||
'type' => policy_version_exporter::read_properties_definition(),
|
||||
'multiple' => true,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the additional values to inject while exporting.
|
||||
*
|
||||
* @param renderer_base $output The renderer.
|
||||
* @return array Keys are the property names, values are their values.
|
||||
*/
|
||||
protected function get_other_values(renderer_base $output) {
|
||||
|
||||
$othervalues = [
|
||||
'currentversion' => null,
|
||||
'draftversions' => [],
|
||||
'archivedversions' => [],
|
||||
];
|
||||
|
||||
foreach ($this->related['versions'] as $exporter) {
|
||||
$data = $exporter->export($output);
|
||||
|
||||
if ($data->id == $this->data->currentversionid) {
|
||||
$othervalues['currentversion'] = $data;
|
||||
|
||||
} else if ($data->archived) {
|
||||
$othervalues['archivedversions'][] = $data;
|
||||
|
||||
} else {
|
||||
$othervalues['draftversions'][] = $data;
|
||||
}
|
||||
}
|
||||
|
||||
return $othervalues;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Provides the {@link tool_policy\policy_version} persistent.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Sara Arjona ([email protected])
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_policy;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use core\persistent;
|
||||
|
||||
/**
|
||||
* Persistent model representing a single policy document version.
|
||||
*
|
||||
* @copyright 2018 Sara Arjona ([email protected])
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class policy_version extends persistent {
|
||||
|
||||
/** @var string Table name this persistent is mapped to. */
|
||||
const TABLE = 'tool_policy_versions';
|
||||
|
||||
/** @var int Site policy document. */
|
||||
const TYPE_SITE = 0;
|
||||
|
||||
/** @var int Privacy policy document. */
|
||||
const TYPE_PRIVACY = 1;
|
||||
|
||||
/** @var int Third party policy document. */
|
||||
const TYPE_THIRD_PARTY = 2;
|
||||
|
||||
/** @var int Other policy document. */
|
||||
const TYPE_OTHER = 99;
|
||||
|
||||
/** @var int Policy applies to all users. */
|
||||
const AUDIENCE_ALL = 0;
|
||||
|
||||
/** @var int Policy applies to logged in users only. */
|
||||
const AUDIENCE_LOGGEDIN = 1;
|
||||
|
||||
/** @var int Policy applies to guests only. */
|
||||
const AUDIENCE_GUESTS = 2;
|
||||
|
||||
/** @var int Policy version is a draft. */
|
||||
const STATUS_DRAFT = 0;
|
||||
|
||||
/** @var int Policy version is the active one. */
|
||||
const STATUS_ACTIVE = 1;
|
||||
|
||||
/** @var int Policy version has been archived. */
|
||||
const STATUS_ARCHIVED = 2;
|
||||
|
||||
/**
|
||||
* Return the definition of the properties of this model.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function define_properties() {
|
||||
return [
|
||||
'name' => [
|
||||
'type' => PARAM_TEXT,
|
||||
'default' => '',
|
||||
],
|
||||
'type' => [
|
||||
'type' => PARAM_INT,
|
||||
'choices' => [
|
||||
self::TYPE_SITE,
|
||||
self::TYPE_PRIVACY,
|
||||
self::TYPE_THIRD_PARTY,
|
||||
self::TYPE_OTHER,
|
||||
],
|
||||
'default' => self::TYPE_SITE,
|
||||
],
|
||||
'audience' => [
|
||||
'type' => PARAM_INT,
|
||||
'choices' => [
|
||||
self::AUDIENCE_ALL,
|
||||
self::AUDIENCE_LOGGEDIN,
|
||||
self::AUDIENCE_GUESTS,
|
||||
],
|
||||
'default' => self::AUDIENCE_ALL,
|
||||
],
|
||||
'archived' => [
|
||||
'type' => PARAM_BOOL,
|
||||
'default' => false,
|
||||
],
|
||||
'policyid' => [
|
||||
'type' => PARAM_INT,
|
||||
],
|
||||
'revision' => [
|
||||
'type' => PARAM_TEXT,
|
||||
'default' => '',
|
||||
],
|
||||
'summary' => [
|
||||
'type' => PARAM_RAW,
|
||||
'default' => '',
|
||||
],
|
||||
'summaryformat' => [
|
||||
'type' => PARAM_INT,
|
||||
'default' => FORMAT_HTML,
|
||||
'choices' => [
|
||||
FORMAT_PLAIN,
|
||||
FORMAT_HTML,
|
||||
FORMAT_MOODLE,
|
||||
FORMAT_MARKDOWN,
|
||||
],
|
||||
],
|
||||
'content' => [
|
||||
'type' => PARAM_RAW,
|
||||
'default' => '',
|
||||
],
|
||||
'contentformat' => [
|
||||
'type' => PARAM_INT,
|
||||
'default' => FORMAT_HTML,
|
||||
'choices' => [
|
||||
FORMAT_PLAIN,
|
||||
FORMAT_HTML,
|
||||
FORMAT_MOODLE,
|
||||
FORMAT_MARKDOWN,
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Provides the {@link tool_policy\policy_version_exporter} class.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 David Mudrak <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_policy;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use core\external\exporter;
|
||||
use renderer_base;
|
||||
use tool_policy\api;
|
||||
|
||||
/**
|
||||
* Exporter of a single policy document version.
|
||||
*
|
||||
* Note we cannot use the persistent_exporter as our super class because we want to add some properties not present in
|
||||
* the persistent (e.g. acceptancescount).
|
||||
*
|
||||
* @copyright 2018 David Mudrak <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class policy_version_exporter extends exporter {
|
||||
|
||||
/**
|
||||
* Return the list of properties.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function define_properties() {
|
||||
|
||||
return policy_version::properties_definition() + [
|
||||
'acceptancescount' => [
|
||||
'type' => PARAM_INT,
|
||||
'default' => 0,
|
||||
],
|
||||
'status' => [
|
||||
'type' => PARAM_INT,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of objects that are related.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function define_related() {
|
||||
return [
|
||||
'context' => 'context',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of additional (calculated and readonly) properties.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function define_other_properties() {
|
||||
return [
|
||||
// Human readable type of the policy document version.
|
||||
'typetext' => [
|
||||
'type' => PARAM_TEXT,
|
||||
],
|
||||
// Human readable audience of the policy document audience.
|
||||
'audiencetext' => [
|
||||
'type' => PARAM_TEXT,
|
||||
],
|
||||
// Detailed information about the number of policy acceptances.
|
||||
'acceptancescounttext' => [
|
||||
'type' => PARAM_TEXT,
|
||||
],
|
||||
// Link to view acceptances.
|
||||
'acceptancescounturl' => [
|
||||
'type' => PARAM_LOCALURL,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the additional values to inject while exporting.
|
||||
*
|
||||
* @param renderer_base $output The renderer.
|
||||
* @return array Keys are the property names, values are their values.
|
||||
*/
|
||||
protected function get_other_values(renderer_base $output) {
|
||||
|
||||
$othervalues = [
|
||||
'typetext' => get_string('policydoctype'.$this->data->type, 'tool_policy'),
|
||||
'audiencetext' => get_string('policydocaudience'.$this->data->audience, 'tool_policy'),
|
||||
];
|
||||
|
||||
if (!isset($this->data->acceptancescount) || $this->data->status == policy_version::STATUS_DRAFT) {
|
||||
// Return "N/A" for acceptances count.
|
||||
$othervalues['acceptancescounttext'] = get_string('useracceptancecountna', 'tool_policy');
|
||||
$othervalues['acceptancescounturl'] = null;
|
||||
return $othervalues;
|
||||
}
|
||||
|
||||
$acceptancescount = empty($this->data->acceptancescount) ? 0 : $this->data->acceptancescount;
|
||||
$acceptancesexpected = api::count_total_users();
|
||||
|
||||
$a = [
|
||||
'agreedcount' => $acceptancescount,
|
||||
'userscount' => $acceptancesexpected,
|
||||
'percent' => min(100, round($acceptancescount * 100 / max($acceptancesexpected, 1))),
|
||||
];
|
||||
|
||||
$othervalues['acceptancescounttext'] = get_string('useracceptancecount', 'tool_policy', $a);
|
||||
$acceptancesurl = new \moodle_url('/admin/tool/policy/acceptances.php', ['policyid' => $this->data->policyid]);
|
||||
if ($this->data->status != policy_version::STATUS_ACTIVE) {
|
||||
$acceptancesurl->param('versionid', $this->data->id);
|
||||
}
|
||||
$othervalues['acceptancescounturl'] = $acceptancesurl->out(false);
|
||||
|
||||
return $othervalues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the formatting parameters for the summary field.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_format_parameters_for_summary() {
|
||||
return [
|
||||
'component' => 'tool_policy',
|
||||
'filearea' => 'policydocumentsummary',
|
||||
'itemid' => $this->data->id
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the formatting parameters for the content field.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_format_parameters_for_content() {
|
||||
return [
|
||||
'component' => 'tool_policy',
|
||||
'filearea' => 'policydocumentcontent',
|
||||
'itemid' => $this->data->id
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Site policy handler class.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Sara Arjona <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_policy\privacy\local\sitepolicy;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use tool_policy\api;
|
||||
use tool_policy\policy_version;
|
||||
|
||||
/**
|
||||
* Class implementation for a site policy handler.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Sara Arjona <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class handler extends \core_privacy\local\sitepolicy\handler {
|
||||
|
||||
/**
|
||||
* Returns URL to redirect user to when user needs to agree to site policy
|
||||
*
|
||||
* This is a regular interactive page for web users. It should have normal Moodle header/footers, it should
|
||||
* allow user to view policies and accept them.
|
||||
*
|
||||
* @param bool $forguests
|
||||
* @return moodle_url|null (returns null if site policy is not defined)
|
||||
*/
|
||||
public static function get_redirect_url($forguests = false) {
|
||||
// There is no redirect for guests, policies are shown in the popup, only return redirect url for the logged in users.
|
||||
if (!$forguests && api::get_current_versions_ids(policy_version::AUDIENCE_LOGGEDIN)) {
|
||||
return new \moodle_url('/admin/tool/policy/index.php');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns URL of the site policy that needs to be displayed to the user (inside iframe or to use in WS such as mobile app)
|
||||
*
|
||||
* This page should not have any header/footer, it does not also have any buttons/checkboxes. The caller needs to implement
|
||||
* the "Accept" button and call {@link self::accept()} on completion.
|
||||
*
|
||||
* @param bool $forguests
|
||||
* @return moodle_url|null
|
||||
*/
|
||||
public static function get_embed_url($forguests = false) {
|
||||
if (api::get_current_versions_ids($forguests ? policy_version::AUDIENCE_GUESTS : policy_version::AUDIENCE_LOGGEDIN)) {
|
||||
return new \moodle_url('/admin/tool/policy/viewall.php');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept site policy for the current user
|
||||
*
|
||||
* @return bool - false if sitepolicy not defined, user is not logged in or user has already agreed to site policy;
|
||||
* true - if we have successfully marked the user as agreed to the site policy
|
||||
*/
|
||||
public static function accept() {
|
||||
global $USER, $DB;
|
||||
if (!isloggedin()) {
|
||||
return false;
|
||||
}
|
||||
if ($USER->policyagreed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isguestuser()) {
|
||||
// Accepts all policies with a current version for logged users on behalf of the current user.
|
||||
if (!$versions = api::get_current_versions_ids(policy_version::AUDIENCE_LOGGEDIN)) {
|
||||
return false;
|
||||
}
|
||||
api::accept_policies(array_values($versions));
|
||||
}
|
||||
|
||||
if (!isguestuser()) {
|
||||
// For the guests agreement in stored in session only, for other users - in DB.
|
||||
$DB->set_field('user', 'policyagreed', 1, array('id' => $USER->id));
|
||||
}
|
||||
$USER->policyagreed = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds "Agree to site policy" checkbox to the signup form.
|
||||
*
|
||||
* @param \MoodleQuickForm $mform
|
||||
*/
|
||||
public static function signup_form($mform) {
|
||||
if (static::is_defined()) {
|
||||
// This plugin displays policies to the user who is signing up before the signup form is shown.
|
||||
// By the time user has access to signup form they have already agreed to the policies.
|
||||
$mform->addElement('hidden', 'policyagreed', 1);
|
||||
$mform->setType('policyagreed', PARAM_INT);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,313 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Privacy Subsystem implementation for tool_policy.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Sara Arjona <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_policy\privacy;
|
||||
|
||||
use core_privacy\local\metadata\collection;
|
||||
use core_privacy\local\request\approved_contextlist;
|
||||
use core_privacy\local\request\contextlist;
|
||||
use core_privacy\local\request\moodle_content_writer;
|
||||
use core_privacy\local\request\transform;
|
||||
use core_privacy\local\request\writer;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Implementation of the privacy subsystem plugin provider for the policy tool.
|
||||
*
|
||||
* @copyright 2018 Sara Arjona <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements
|
||||
// This tool stores user data.
|
||||
\core_privacy\local\metadata\provider,
|
||||
|
||||
// This tool may provide access to and deletion of user data.
|
||||
\core_privacy\local\request\plugin\provider {
|
||||
|
||||
/**
|
||||
* Return the fields which contain personal data.
|
||||
*
|
||||
* @param collection $collection The initialised collection to add items to.
|
||||
* @return collection A listing of user data stored through this system.
|
||||
*/
|
||||
public static function get_metadata(collection $collection) : collection {
|
||||
$collection->add_database_table(
|
||||
'tool_policy_acceptances',
|
||||
[
|
||||
'policyversionid' => 'privacy:metadata:acceptances:policyversionid',
|
||||
'userid' => 'privacy:metadata:acceptances:userid',
|
||||
'status' => 'privacy:metadata:acceptances:status',
|
||||
'lang' => 'privacy:metadata:acceptances:lang',
|
||||
'usermodified' => 'privacy:metadata:acceptances:usermodified',
|
||||
'timecreated' => 'privacy:metadata:acceptances:timecreated',
|
||||
'timemodified' => 'privacy:metadata:acceptances:timemodified',
|
||||
'note' => 'privacy:metadata:acceptances:note',
|
||||
],
|
||||
'privacy:metadata:acceptances'
|
||||
);
|
||||
|
||||
$collection->add_database_table(
|
||||
'tool_policy_versions',
|
||||
[
|
||||
'name' => 'privacy:metadata:versions:name',
|
||||
'type' => 'privacy:metadata:versions:type',
|
||||
'audience' => 'privacy:metadata:versions:audience',
|
||||
'archived' => 'privacy:metadata:versions:archived',
|
||||
'usermodified' => 'privacy:metadata:versions:usermodified',
|
||||
'timecreated' => 'privacy:metadata:versions:timecreated',
|
||||
'timemodified' => 'privacy:metadata:versions:timemodified',
|
||||
'policyid' => 'privacy:metadata:versions:policyid',
|
||||
'revision' => 'privacy:metadata:versions:revision',
|
||||
'summary' => 'privacy:metadata:versions:summary',
|
||||
'summaryformat' => 'privacy:metadata:versions:summaryformat',
|
||||
'content' => 'privacy:metadata:versions:content',
|
||||
'contentformat' => 'privacy:metadata:versions:contentformat',
|
||||
],
|
||||
'privacy:metadata:versions'
|
||||
);
|
||||
|
||||
$collection->add_subsystem_link('core_files', [], 'privacy:metadata:subsystem:corefiles');
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of contexts that contain user information for the specified user.
|
||||
*
|
||||
* @param int $userid The userid.
|
||||
* @return contextlist The list of contexts containing user info for the user.
|
||||
*/
|
||||
public static function get_contexts_for_userid(int $userid) : contextlist {
|
||||
$contextlist = new contextlist();
|
||||
|
||||
// Policies a user has modified.
|
||||
$sql = "SELECT c.id
|
||||
FROM {context} c
|
||||
JOIN {tool_policy_versions} v ON v.usermodified = :userid
|
||||
WHERE c.contextlevel = :contextlevel";
|
||||
$params = [
|
||||
'contextlevel' => CONTEXT_SYSTEM,
|
||||
'userid' => $userid,
|
||||
];
|
||||
$contextlist->add_from_sql($sql, $params);
|
||||
|
||||
// Policies a user has accepted.
|
||||
$sql = "SELECT c.id
|
||||
FROM {context} c
|
||||
JOIN {tool_policy_acceptances} a ON c.instanceid = a.userid
|
||||
WHERE
|
||||
c.contextlevel = :contextlevel
|
||||
AND (
|
||||
a.userid = :userid OR a.usermodified = :usermodified
|
||||
)";
|
||||
$params = [
|
||||
'contextlevel' => CONTEXT_USER,
|
||||
'userid' => $userid,
|
||||
'usermodified' => $userid,
|
||||
];
|
||||
$contextlist->add_from_sql($sql, $params);
|
||||
|
||||
return $contextlist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export personal data for the given approved_contextlist. User and context information is contained within the contextlist.
|
||||
*
|
||||
* @param approved_contextlist $contextlist A list of contexts approved for export.
|
||||
*/
|
||||
public static function export_user_data(approved_contextlist $contextlist) {
|
||||
global $DB;
|
||||
|
||||
// Export user agreements.
|
||||
foreach ($contextlist->get_contexts() as $context) {
|
||||
if ($context->contextlevel == CONTEXT_USER) {
|
||||
static::export_policy_agreements_for_context($context);
|
||||
} else if ($context->contextlevel == CONTEXT_SYSTEM) {
|
||||
static::export_authored_policies($contextlist->get_user());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all data for all users in the specified context.
|
||||
*
|
||||
* We never delete user agreements to the policies because they are part of privacy data.
|
||||
* We never delete policy versions because they are part of privacy data.
|
||||
*
|
||||
* @param \context $context The context to delete in.
|
||||
*/
|
||||
public static function delete_data_for_all_users_in_context(\context $context) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all user data for the specified user, in the specified contexts.
|
||||
*
|
||||
* We never delete user agreements to the policies because they are part of privacy data.
|
||||
* We never delete policy versions because they are part of privacy data.
|
||||
*
|
||||
* @param approved_contextlist $contextlist A list of contexts approved for deletion.
|
||||
*/
|
||||
public static function delete_data_for_user(approved_contextlist $contextlist) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Export all policy agreements relating to the specified user context.
|
||||
*
|
||||
* @param \context_user $context The context to export
|
||||
*/
|
||||
protected static function export_policy_agreements_for_context(\context_user $context) {
|
||||
global $DB;
|
||||
|
||||
$sysctx = \context_system::instance();
|
||||
$fs = get_file_storage();
|
||||
$agreementsql = "
|
||||
SELECT
|
||||
a.id AS agreementid, a.userid, a.timemodified, a.note, a.status,
|
||||
a.policyversionid AS versionid, a.usermodified, a.timecreated,
|
||||
v.id, v.archived, v.name, v.revision,
|
||||
v.summary, v.summaryformat,
|
||||
v.content, v.contentformat,
|
||||
p.currentversionid
|
||||
FROM {tool_policy_acceptances} a
|
||||
JOIN {tool_policy_versions} v ON v.id = a.policyversionid
|
||||
JOIN {tool_policy} p ON v.policyid = p.id
|
||||
WHERE a.userid = :userid OR a.usermodified = :usermodified";
|
||||
|
||||
// Fetch all agreements related to this user.
|
||||
$agreements = $DB->get_recordset_sql($agreementsql, [
|
||||
'userid' => $context->instanceid,
|
||||
'usermodified' => $context->instanceid,
|
||||
]);
|
||||
|
||||
$basecontext = [
|
||||
get_string('privacyandpolicies', 'admin'),
|
||||
get_string('useracceptances', 'tool_policy'),
|
||||
];
|
||||
|
||||
foreach ($agreements as $agreement) {
|
||||
$subcontext = array_merge($basecontext, [get_string('policynamedversion', 'tool_policy', $agreement)]);
|
||||
|
||||
$summary = writer::with_context($context)->rewrite_pluginfile_urls(
|
||||
$subcontext,
|
||||
'tool_policy',
|
||||
'policydocumentsummary',
|
||||
$agreement->versionid,
|
||||
$agreement->summary
|
||||
);
|
||||
$content = writer::with_context($context)->rewrite_pluginfile_urls(
|
||||
$subcontext,
|
||||
'tool_policy',
|
||||
'policydocumentcontent',
|
||||
$agreement->versionid,
|
||||
$agreement->content
|
||||
);
|
||||
$agreementcontent = (object) [
|
||||
'name' => $agreement->name,
|
||||
'revision' => $agreement->revision,
|
||||
'isactive' => transform::yesno($agreement->versionid == $agreement->currentversionid),
|
||||
'isagreed' => transform::yesno($agreement->status),
|
||||
'agreedby' => transform::user($agreement->usermodified),
|
||||
'timecreated' => transform::datetime($agreement->timecreated),
|
||||
'timemodified' => transform::datetime($agreement->timemodified),
|
||||
'note' => $agreement->note,
|
||||
'summary' => format_text($summary, $agreement->summaryformat),
|
||||
'content' => format_text($content, $agreement->contentformat),
|
||||
];
|
||||
|
||||
writer::with_context($context)->export_data($subcontext, $agreementcontent);
|
||||
// Manually export the files as they reside in the system context so we can't use
|
||||
// the write's helper methods.
|
||||
foreach ($fs->get_area_files($sysctx->id, 'tool_policy', 'policydocumentsummary', $agreement->versionid) as $file) {
|
||||
writer::with_context($context)->export_file($subcontext, $file);
|
||||
}
|
||||
foreach ($fs->get_area_files($sysctx->id, 'tool_policy', 'policydocumentcontent', $agreement->versionid) as $file) {
|
||||
writer::with_context($context)->export_file($subcontext, $file);
|
||||
}
|
||||
}
|
||||
$agreements->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Export all policy agreements that the user authored.
|
||||
*
|
||||
* @param stdClass $user The user who has created the policies to export.
|
||||
*/
|
||||
protected static function export_authored_policies(\stdClass $user) {
|
||||
global $DB;
|
||||
|
||||
// Authored policies are exported against the system.
|
||||
$context = \context_system::instance();
|
||||
$basecontext = [
|
||||
get_string('policydocuments', 'tool_policy'),
|
||||
];
|
||||
|
||||
$sql = "SELECT v.id,
|
||||
v.name,
|
||||
v.revision,
|
||||
v.summary,
|
||||
v.content,
|
||||
v.archived,
|
||||
v.usermodified,
|
||||
v.timecreated,
|
||||
v.timemodified,
|
||||
p.currentversionid
|
||||
FROM {tool_policy_versions} v
|
||||
JOIN {tool_policy} p ON p.id = v.policyid
|
||||
WHERE v.usermodified = :userid";
|
||||
$versions = $DB->get_recordset_sql($sql, ['userid' => $user->id]);
|
||||
foreach ($versions as $version) {
|
||||
$subcontext = array_merge($basecontext, [get_string('policynamedversion', 'tool_policy', $version)]);
|
||||
|
||||
$versioncontent = (object) [
|
||||
'name' => $version->name,
|
||||
'revision' => $version->revision,
|
||||
'summary' => writer::with_context($context)->rewrite_pluginfile_urls(
|
||||
$subcontext,
|
||||
'tool_policy',
|
||||
'policydocumentsummary',
|
||||
$version->id,
|
||||
$version->summary
|
||||
),
|
||||
'content' => writer::with_context($context)->rewrite_pluginfile_urls(
|
||||
$subcontext,
|
||||
'tool_policy',
|
||||
'policydocumentcontent',
|
||||
$version->id,
|
||||
$version->content
|
||||
),
|
||||
'isactive' => transform::yesno($version->id == $version->currentversionid),
|
||||
'isarchived' => transform::yesno($version->archived),
|
||||
'createdbyme' => transform::yesno($version->usermodified == $user->id),
|
||||
'timecreated' => transform::datetime($version->timecreated),
|
||||
'timemodified' => transform::datetime($version->timemodified),
|
||||
];
|
||||
writer::with_context($context)
|
||||
->export_data($subcontext, $versioncontent)
|
||||
->export_area_files($subcontext, 'tool_policy', 'policydocumentsummary', $version->id)
|
||||
->export_area_files($subcontext, 'tool_policy', 'policydocumentcontent', $version->id);
|
||||
}
|
||||
$versions->close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Plugin capabilities are defined here.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @category access
|
||||
* @copyright 2018 David Mudrák <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$capabilities = [
|
||||
|
||||
'tool/policy:accept' => [
|
||||
'captype' => 'write',
|
||||
'contextlevel' => CONTEXT_SYSTEM,
|
||||
'archetypes' => [
|
||||
'user' => CAP_ALLOW,
|
||||
],
|
||||
],
|
||||
|
||||
'tool/policy:acceptbehalf' => [
|
||||
'riskbitmask' => RISK_PERSONAL,
|
||||
'captype' => 'write',
|
||||
'contextlevel' => CONTEXT_USER,
|
||||
'archetypes' => [
|
||||
],
|
||||
],
|
||||
|
||||
'tool/policy:managedocs' => [
|
||||
'captype' => 'write',
|
||||
'contextlevel' => CONTEXT_SYSTEM,
|
||||
'archetypes' => [
|
||||
'manager' => CAP_ALLOW,
|
||||
],
|
||||
],
|
||||
|
||||
'tool/policy:viewacceptances' => [
|
||||
'captype' => 'read',
|
||||
'contextlevel' => CONTEXT_SYSTEM,
|
||||
'archetypes' => [
|
||||
'manager' => CAP_ALLOW,
|
||||
],
|
||||
],
|
||||
];
|
||||
@@ -0,0 +1,32 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* This file defines observers needed by the plugin.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Mihail Geshoski <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$observers = [
|
||||
[
|
||||
'eventname' => '\core\event\user_created',
|
||||
'callback' => '\tool_policy\api::create_acceptances_user_created',
|
||||
],
|
||||
];
|
||||
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<XMLDB PATH="admin/tool/policy/db" VERSION="20180307" COMMENT="The plugin allows to manage various policy documents that users have to accept to use the site."
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="../../../../lib/xmldb/xmldb.xsd"
|
||||
>
|
||||
<TABLES>
|
||||
<TABLE NAME="tool_policy" COMMENT="Contains the list of policy documents defined on the site.">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
|
||||
<FIELD NAME="sortorder" TYPE="int" LENGTH="5" NOTNULL="true" DEFAULT="999" SEQUENCE="false" COMMENT="Defines the order in which policies should be presented to users"/>
|
||||
<FIELD NAME="currentversionid" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="ID of the current policy version that applies on the site, NULL if the policy does not apply"/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
<KEY NAME="fk_currentversionid" TYPE="foreign" FIELDS="currentversionid" REFTABLE="tool_policy_versions" REFFIELDS="id"/>
|
||||
</KEYS>
|
||||
</TABLE>
|
||||
<TABLE NAME="tool_policy_versions" COMMENT="Holds versions of the policy documents">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
|
||||
<FIELD NAME="name" TYPE="char" LENGTH="1333" NOTNULL="true" SEQUENCE="false" COMMENT="Name of the policy document"/>
|
||||
<FIELD NAME="type" TYPE="int" LENGTH="3" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Type of the policy: 0 - Site policy, 1 - Privacy policy, 2 - Third party policy, 99 - Other"/>
|
||||
<FIELD NAME="audience" TYPE="int" LENGTH="3" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Who is this policy targeted at: 0 - all users, 1 - logged in users only, 2 - guests only"/>
|
||||
<FIELD NAME="archived" TYPE="int" LENGTH="3" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Should the version be considered as archived. All non-archived, non-current versions are considered to be drafts."/>
|
||||
<FIELD NAME="usermodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="ID of the user who last edited this policy document version."/>
|
||||
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Timestamp of when the policy version was created."/>
|
||||
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Timestamp of when the policy version was last modified."/>
|
||||
<FIELD NAME="policyid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="ID of the policy document we are version of."/>
|
||||
<FIELD NAME="revision" TYPE="char" LENGTH="1333" NOTNULL="true" SEQUENCE="false" COMMENT="Human readable version of the policy document"/>
|
||||
<FIELD NAME="summary" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="Policy text summary"/>
|
||||
<FIELD NAME="summaryformat" TYPE="int" LENGTH="3" NOTNULL="true" SEQUENCE="false" COMMENT="Format of the summary field"/>
|
||||
<FIELD NAME="content" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="Full policy text"/>
|
||||
<FIELD NAME="contentformat" TYPE="int" LENGTH="3" NOTNULL="true" SEQUENCE="false" COMMENT="Format of the content field"/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
<KEY NAME="fk_usermodified" TYPE="foreign" FIELDS="usermodified" REFTABLE="user" REFFIELDS="id"/>
|
||||
<KEY NAME="fk_policyid" TYPE="foreign" FIELDS="policyid" REFTABLE="tool_policy" REFFIELDS="id"/>
|
||||
</KEYS>
|
||||
</TABLE>
|
||||
<TABLE NAME="tool_policy_acceptances" COMMENT="Tracks users accepting the policy versions">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
|
||||
<FIELD NAME="policyversionid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="ID of the policy document version"/>
|
||||
<FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="ID of the user this acceptance is relevant to"/>
|
||||
<FIELD NAME="status" TYPE="int" LENGTH="1" NOTNULL="false" SEQUENCE="false" COMMENT="Acceptance status: 1 - accepted, 0 - not accepted"/>
|
||||
<FIELD NAME="lang" TYPE="char" LENGTH="30" NOTNULL="true" SEQUENCE="false" COMMENT="Code of the language the user had when the policy document was displayed"/>
|
||||
<FIELD NAME="usermodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="ID of the user who last modified the acceptance record"/>
|
||||
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Timestamp of when the acceptance record was created"/>
|
||||
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Timestamp of when the acceptance record was last modified"/>
|
||||
<FIELD NAME="note" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Plain text note describing how the actual consent has been obtained if the policy has been accepted on other user's behalf."/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
<KEY NAME="fk_policyversionid" TYPE="foreign" FIELDS="policyversionid" REFTABLE="tool_policy_versions" REFFIELDS="id"/>
|
||||
<KEY NAME="fk_userid" TYPE="foreign" FIELDS="userid" REFTABLE="user" REFFIELDS="id"/>
|
||||
<KEY NAME="fk_usermodified" TYPE="foreign" FIELDS="usermodified" REFTABLE="user" REFFIELDS="id"/>
|
||||
<KEY NAME="uq_versionuser" TYPE="unique" FIELDS="policyversionid, userid" COMMENT="There cannot exist more records for given user and policy document version."/>
|
||||
</KEYS>
|
||||
</TABLE>
|
||||
</TABLES>
|
||||
</XMLDB>
|
||||
@@ -0,0 +1,48 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Tool policy external functions and service definitions.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @category external
|
||||
* @copyright 2018 Sara Arjona ([email protected])
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die;
|
||||
|
||||
$functions = [
|
||||
'tool_policy_get_policy_version' => [
|
||||
'classname' => 'tool_policy\external',
|
||||
'methodname' => 'get_policy_version',
|
||||
'classpath' => '',
|
||||
'description' => 'Fetch the details of a policy version',
|
||||
'type' => 'read',
|
||||
'capabilities' => '',
|
||||
'ajax' => true,
|
||||
'loginrequired' => false,
|
||||
],
|
||||
|
||||
'tool_policy_submit_accept_on_behalf' => [
|
||||
'classname' => 'tool_policy\external',
|
||||
'methodname' => 'submit_accept_on_behalf',
|
||||
'classpath' => '',
|
||||
'description' => 'Accept policies on behalf of other users',
|
||||
'ajax' => true,
|
||||
'type' => 'write',
|
||||
],
|
||||
];
|
||||
@@ -0,0 +1,190 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Edit/create a policy document version.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 David Mudrák <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
use tool_policy\api;
|
||||
use tool_policy\policy_version;
|
||||
|
||||
require(__DIR__.'/../../../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
|
||||
$policyid = optional_param('policyid', null, PARAM_INT);
|
||||
$versionid = optional_param('versionid', null, PARAM_INT);
|
||||
$makecurrent = optional_param('makecurrent', null, PARAM_INT);
|
||||
$inactivate = optional_param('inactivate', null, PARAM_INT);
|
||||
$delete = optional_param('delete', null, PARAM_INT);
|
||||
$confirm = optional_param('confirm', false, PARAM_BOOL);
|
||||
$moveup = optional_param('moveup', null, PARAM_INT);
|
||||
$movedown = optional_param('movedown', null, PARAM_INT);
|
||||
|
||||
admin_externalpage_setup('tool_policy_managedocs', '', ['policyid' => $policyid, 'versionid' => $versionid],
|
||||
new moodle_url('/admin/tool/policy/editpolicydoc.php'));
|
||||
require_capability('tool/policy:managedocs', context_system::instance());
|
||||
|
||||
$output = $PAGE->get_renderer('tool_policy');
|
||||
$PAGE->navbar->add(get_string('editingpolicydocument', 'tool_policy'));
|
||||
|
||||
if ($makecurrent) {
|
||||
$version = api::get_policy_version($makecurrent);
|
||||
|
||||
if ($confirm) {
|
||||
require_sesskey();
|
||||
api::make_current($makecurrent);
|
||||
redirect(new moodle_url('/admin/tool/policy/managedocs.php'));
|
||||
}
|
||||
|
||||
echo $output->header();
|
||||
echo $output->heading(get_string('activating', 'tool_policy'));
|
||||
echo $output->confirm(
|
||||
get_string('activateconfirm', 'tool_policy', [
|
||||
'name' => format_string($version->name),
|
||||
'revision' => format_string($version->revision),
|
||||
]),
|
||||
new moodle_url($PAGE->url, ['makecurrent' => $makecurrent, 'confirm' => 1]),
|
||||
new moodle_url('/admin/tool/policy/managedocs.php')
|
||||
);
|
||||
echo $output->footer();
|
||||
die();
|
||||
}
|
||||
|
||||
if ($inactivate) {
|
||||
$policies = api::list_policies([$inactivate]);
|
||||
|
||||
if (empty($policies[0]->currentversionid)) {
|
||||
redirect(new moodle_url('/admin/tool/policy/managedocs.php'));
|
||||
}
|
||||
|
||||
if ($confirm) {
|
||||
require_sesskey();
|
||||
api::inactivate($inactivate);
|
||||
redirect(new moodle_url('/admin/tool/policy/managedocs.php'));
|
||||
}
|
||||
|
||||
echo $output->header();
|
||||
echo $output->heading(get_string('inactivating', 'tool_policy'));
|
||||
echo $output->confirm(
|
||||
get_string('inactivatingconfirm', 'tool_policy', [
|
||||
'name' => format_string($policies[0]->currentversion->name),
|
||||
'revision' => format_string($policies[0]->currentversion->revision),
|
||||
]),
|
||||
new moodle_url($PAGE->url, ['inactivate' => $inactivate, 'confirm' => 1]),
|
||||
new moodle_url('/admin/tool/policy/managedocs.php')
|
||||
);
|
||||
echo $output->footer();
|
||||
die();
|
||||
}
|
||||
|
||||
if ($delete) {
|
||||
$version = api::get_policy_version($delete);
|
||||
|
||||
if ($confirm) {
|
||||
require_sesskey();
|
||||
api::delete($delete);
|
||||
redirect(new moodle_url('/admin/tool/policy/managedocs.php'));
|
||||
}
|
||||
|
||||
echo $output->header();
|
||||
echo $output->heading(get_string('deleting', 'tool_policy'));
|
||||
echo $output->confirm(
|
||||
get_string('deleteconfirm', 'tool_policy', [
|
||||
'name' => format_string($version->name),
|
||||
'revision' => format_string($version->revision),
|
||||
]),
|
||||
new moodle_url($PAGE->url, ['delete' => $delete, 'confirm' => 1]),
|
||||
new moodle_url('/admin/tool/policy/managedocs.php')
|
||||
);
|
||||
echo $output->footer();
|
||||
die();
|
||||
}
|
||||
|
||||
if ($moveup || $movedown) {
|
||||
require_sesskey();
|
||||
|
||||
if ($moveup) {
|
||||
api::move_up($moveup);
|
||||
} else {
|
||||
api::move_down($movedown);
|
||||
}
|
||||
|
||||
redirect(new moodle_url('/admin/tool/policy/managedocs.php'));
|
||||
}
|
||||
|
||||
if (!$versionid && $policyid) {
|
||||
if (($policies = api::list_policies([$policyid])) && !empty($policies[0]->currentversionid)) {
|
||||
$policy = $policies[0];
|
||||
$policyversion = new policy_version($policy->currentversionid);
|
||||
} else {
|
||||
redirect(new moodle_url('/admin/tool/policy/managedocs.php'));
|
||||
}
|
||||
} else {
|
||||
$policyversion = new policy_version($versionid);
|
||||
if ($policyversion->get('policyid')) {
|
||||
$policy = api::list_policies([$policyversion->get('policyid')])[0];
|
||||
} else {
|
||||
$policy = null;
|
||||
}
|
||||
}
|
||||
|
||||
$formdata = api::form_policydoc_data($policyversion);
|
||||
|
||||
if ($policy && $formdata->id && $policy->currentversionid == $formdata->id) {
|
||||
// We are editing an active version.
|
||||
$formdata->status = policy_version::STATUS_ACTIVE;
|
||||
} else {
|
||||
// We are editing a draft or archived version and the default next status is "draft".
|
||||
$formdata->status = policy_version::STATUS_DRAFT;
|
||||
// Archived versions can not be edited without creating a new version.
|
||||
$formdata->minorchange = $policyversion->get('archived') ? 0 : 1;
|
||||
}
|
||||
|
||||
$form = new \tool_policy\form\policydoc($PAGE->url, ['formdata' => $formdata]);
|
||||
|
||||
if ($form->is_cancelled()) {
|
||||
redirect(new moodle_url('/admin/tool/policy/managedocs.php'));
|
||||
|
||||
} else if ($data = $form->get_data()) {
|
||||
|
||||
if (! $policyversion->get('id')) {
|
||||
$policyversion = api::form_policydoc_add($data);
|
||||
|
||||
} else if (empty($data->minorchange)) {
|
||||
$data->policyid = $policyversion->get('policyid');
|
||||
$policyversion = api::form_policydoc_update_new($data);
|
||||
|
||||
} else {
|
||||
$data->id = $policyversion->get('id');
|
||||
$policyversion = api::form_policydoc_update_overwrite($data);
|
||||
}
|
||||
|
||||
if ($data->status == policy_version::STATUS_ACTIVE) {
|
||||
api::make_current($policyversion->get('id'));
|
||||
}
|
||||
|
||||
redirect(new moodle_url('/admin/tool/policy/managedocs.php'));
|
||||
|
||||
} else {
|
||||
echo $output->header();
|
||||
echo $output->heading(get_string('editingpolicydocument', 'tool_policy'));
|
||||
echo $form->render();
|
||||
echo $output->footer();
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Show a user the policy documents to be agreed to.
|
||||
*
|
||||
* Script parameters:
|
||||
* agreedoc=<array> Policy version id which have been accepted by the user.
|
||||
* behalfid=<id> The user id to view the policy version as (such as child's id).
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Sara Arjona ([email protected])
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
use tool_policy\api;
|
||||
use tool_policy\output\page_agreedocs;
|
||||
|
||||
// Do not check for the site policies in require_login() to avoid the redirect loop.
|
||||
define('NO_SITEPOLICY_CHECK', true);
|
||||
|
||||
// @codingStandardsIgnoreLine See the {@link page_agreedocs} for the access control checks.
|
||||
require(__DIR__.'/../../../config.php');
|
||||
|
||||
$submit = optional_param('submit', null, PARAM_NOTAGS);
|
||||
$cancel = optional_param('cancel', null, PARAM_NOTAGS);
|
||||
$agreedocs = optional_param_array('agreedoc', null, PARAM_INT);
|
||||
$behalfid = optional_param('userid', null, PARAM_INT);
|
||||
|
||||
$PAGE->set_context(context_system::instance());
|
||||
$PAGE->set_pagelayout('standard');
|
||||
$PAGE->set_url('/admin/tool/policy/index.php');
|
||||
$PAGE->set_popup_notification_allowed(false);
|
||||
|
||||
if (isloggedin() && !isguestuser()) {
|
||||
// Existing user.
|
||||
$haspermissionagreedocs = api::can_accept_policies($behalfid);
|
||||
} else {
|
||||
// New user.
|
||||
$haspermissionagreedocs = true;
|
||||
}
|
||||
|
||||
if (!$haspermissionagreedocs) {
|
||||
$outputpage = new \tool_policy\output\page_nopermission($behalfid);
|
||||
} else if ($cancel) {
|
||||
redirect(new moodle_url('/'));
|
||||
} else {
|
||||
if (!$behalfid && \core\session\manager::is_loggedinas()) {
|
||||
$behalfid = $USER->id;
|
||||
}
|
||||
$outputpage = new \tool_policy\output\page_agreedocs($agreedocs, $behalfid, $submit);
|
||||
}
|
||||
|
||||
$output = $PAGE->get_renderer('tool_policy');
|
||||
|
||||
echo $output->header();
|
||||
echo $output->render($outputpage);
|
||||
echo $output->footer();
|
||||
@@ -0,0 +1,179 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Plugin strings are defined here.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @category string
|
||||
* @copyright 2018 David Mudrák <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['acceptanceacknowledgement'] = 'I acknowledge that I have received a request to give consent on behalf of user(s).';
|
||||
$string['acceptancecount'] = '{$a->agreedcount} of {$a->policiescount}';
|
||||
$string['acceptancenote'] = 'Remarks';
|
||||
$string['acceptancepolicies'] = 'Policies';
|
||||
$string['acceptancessavedsucessfully'] = 'The agreements have been saved successfully.';
|
||||
$string['acceptancestatusoverall'] = 'Overall';
|
||||
$string['acceptanceusers'] = 'Users';
|
||||
$string['actions'] = 'Actions';
|
||||
$string['activate'] = 'Set status to "Active"';
|
||||
$string['activating'] = 'Activating a policy';
|
||||
$string['activateconfirm'] = '<p>You are about to activate policy <em>\'{$a->name}\'</em> and make the version <em>\'{$a->revision}\'</em> the current one.</p><p>All users will be required to agree to this new policy version to be able to use the site.</p>';
|
||||
$string['activateconfirmyes'] = 'Activate';
|
||||
$string['agreed'] = 'Agreed';
|
||||
$string['agreedby'] = 'Agreed by';
|
||||
$string['agreedno'] = 'Consent not given';
|
||||
$string['agreednowithlink'] = 'Consent not given; click to give consent on behalf of user for {$a}';
|
||||
$string['agreednowithlinkall'] = 'Consent not given; click to give consent on behalf of user for all policies';
|
||||
$string['agreedon'] = 'Agreed on';
|
||||
$string['agreedyes'] = 'Agreed';
|
||||
$string['agreedyesonbehalf'] = 'Consent given on behalf of user';
|
||||
$string['agreedyesonbehalfwithlink'] = 'Consent given on behalf of user; click to withdraw user consent for {$a}';
|
||||
$string['agreedyesonbehalfwithlinkall'] = 'Consent given on behalf of user; click to withdraw user consent for all policies';
|
||||
$string['agreedyeswithlink'] = 'Consent given; click to withdraw user consent for {$a}';
|
||||
$string['agreedyeswithlinkall'] = 'Consent given; click to withdraw user consent for all policies';
|
||||
$string['agreepolicies'] = 'Please agree to the following policies';
|
||||
$string['backtotop'] = 'Back to top';
|
||||
$string['consentbulk'] = 'Consent';
|
||||
$string['consentdetails'] = 'Give consent on behalf of user';
|
||||
$string['consentpagetitle'] = 'Consent';
|
||||
$string['contactdpo'] = 'For any questions about the policies please contact the privacy officer.';
|
||||
$string['dataproc'] = 'Personal data processing';
|
||||
$string['deleting'] = 'Deleting a version';
|
||||
$string['deleteconfirm'] = '<p>Are you sure you want to delete policy <em>\'{$a->name}\'</em>?</p><p>This operation can not be undone.</p>';
|
||||
$string['editingpolicydocument'] = 'Editing policy';
|
||||
$string['errorpolicyversionnotfound'] = 'There isn\'t any policy version with this identifier.';
|
||||
$string['errorsaveasdraft'] = 'Minor change can not be saved as draft';
|
||||
$string['errorusercantviewpolicyversion'] = 'The user doesn\'t have access to this policy version.';
|
||||
$string['event_acceptance_created'] = 'User policy agreement created';
|
||||
$string['event_acceptance_updated'] = 'User policy agreement updated';
|
||||
$string['filtercapabilityno'] = 'Permission: Can not agree';
|
||||
$string['filtercapabilityyes'] = 'Permission: Can agree';
|
||||
$string['filterrevision'] = 'Version: {$a}';
|
||||
$string['filterrevisionstatus'] = 'Version: {$a->name} ({$a->status})';
|
||||
$string['filterrole'] = 'Role: {$a}';
|
||||
$string['filters'] = 'Filters';
|
||||
$string['filterstatusno'] = 'Status: Not agreed';
|
||||
$string['filterstatusyes'] = 'Status: Agreed';
|
||||
$string['filterplaceholder'] = 'Search keyword or select filter';
|
||||
$string['filterpolicy'] = 'Policy: {$a}';
|
||||
$string['guestconsent:continue'] = 'Continue';
|
||||
$string['guestconsentmessage'] = 'If you continue browsing this website, you agree to our policies:';
|
||||
$string['iagree'] = 'I agree to the {$a}';
|
||||
$string['iagreetothepolicy'] = 'Give consent on behalf of user';
|
||||
$string['inactivate'] = 'Set status to "Inactive"';
|
||||
$string['inactivating'] = 'Inactivating a policy';
|
||||
$string['inactivatingconfirm'] = '<p>You are about to inactivate policy <em>\'{$a->name}\'</em> version <em>\'{$a->revision}\'</em>.</p>';
|
||||
$string['inactivatingconfirmyes'] = 'Inactivate';
|
||||
$string['invalidversionid'] = 'There is no policy with this identifier!';
|
||||
$string['irevokethepolicy'] = 'Withdraw user consent';
|
||||
$string['listactivepolicies'] = 'List of active policies';
|
||||
$string['minorchange'] = 'Minor change';
|
||||
$string['minorchangeinfo'] = 'A minor change does not alter the meaning of the policy. Users are not required to agree to the policy again if the edit is marked as a minor change.';
|
||||
$string['managepolicies'] = 'Manage policies';
|
||||
$string['movedown'] = 'Move down';
|
||||
$string['moveup'] = 'Move up';
|
||||
$string['mustagreetocontinue'] = 'Before continuing you must agree to all these policies.';
|
||||
$string['newpolicy'] = 'New policy';
|
||||
$string['newversion'] = 'New version';
|
||||
$string['noactivepolicies'] = 'There are no policies with an active version.';
|
||||
$string['nofiltersapplied'] = 'No filters applied';
|
||||
$string['nopermissiontoagreedocs'] = 'No permission to agree to the policies';
|
||||
$string['nopermissiontoagreedocs_desc'] = 'Sorry, you do not have the required permissions to agree to the policies.<br />You will not be able to use this site until the following policies are agreed:';
|
||||
$string['nopermissiontoagreedocsbehalf'] = 'No permission to agree to the policies on behalf of this user';
|
||||
$string['nopermissiontoagreedocsbehalf_desc'] = 'Sorry, you do not have the required permission to agree to the following policies on behalf of {$a}:';
|
||||
$string['nopermissiontoagreedocscontact'] = 'For further assistance, please contact';
|
||||
$string['nopermissiontoviewpolicyversion'] = 'You do not have permissions to view this policy version.';
|
||||
$string['nopolicies'] = 'There are no policies for registered users with an active version.';
|
||||
$string['selectpolicyandversion'] = 'Use the filter above to select policy and/or version';
|
||||
$string['steppolicies'] = 'Policy {$a->numpolicy} out of {$a->totalpolicies}';
|
||||
$string['pluginname'] = 'Policies';
|
||||
$string['policiesagreements'] = 'Policies and agreements';
|
||||
$string['policy:accept'] = 'Agree to the policies';
|
||||
$string['policy:acceptbehalf'] = 'Give consent for policies on someone else\'s behalf';
|
||||
$string['policy:managedocs'] = 'Manage policies';
|
||||
$string['policy:viewacceptances'] = 'View user agreement reports';
|
||||
$string['policydocaudience'] = 'User consent';
|
||||
$string['policydocaudience0'] = 'All users';
|
||||
$string['policydocaudience1'] = 'Authenticated users';
|
||||
$string['policydocaudience2'] = 'Guests';
|
||||
$string['policydoccontent'] = 'Full policy';
|
||||
$string['policydochdrpolicy'] = 'Policy';
|
||||
$string['policydochdrversion'] = 'Document version';
|
||||
$string['policydocname'] = 'Name';
|
||||
$string['policydocrevision'] = 'Version';
|
||||
$string['policydocsummary'] = 'Summary';
|
||||
$string['policydocsummary_help'] = 'This text should provide a summary of the policy, potentially in a simplified and easily accessible form, using clear and plain language.';
|
||||
$string['policydoctype'] = 'Type';
|
||||
$string['policydoctype0'] = 'Site policy';
|
||||
$string['policydoctype1'] = 'Privacy policy';
|
||||
$string['policydoctype2'] = 'Third parties policy';
|
||||
$string['policydoctype99'] = 'Other policy';
|
||||
$string['policydocuments'] = 'Policy documents';
|
||||
$string['policynamedversion'] = 'Policy {$a->name} (version {$a->revision} - {$a->id})';
|
||||
$string['policyversionacceptedinbehalf'] = 'Consent for this policy has been given on your behalf.';
|
||||
$string['policyversionacceptedinotherlang'] = 'Consent for this policy version has been given in a different language.';
|
||||
$string['previousversions'] = '{$a} previous versions';
|
||||
$string['privacy:metadata:acceptances'] = 'Information about policy agreements made by users.';
|
||||
$string['privacy:metadata:acceptances:policyversionid'] = 'The version of the policy for which consent was given.';
|
||||
$string['privacy:metadata:acceptances:userid'] = 'The user for whom this policy agreement relates to.';
|
||||
$string['privacy:metadata:acceptances:status'] = 'The status of the agreement.';
|
||||
$string['privacy:metadata:acceptances:lang'] = 'The language used to display the policy when consent was given.';
|
||||
$string['privacy:metadata:acceptances:usermodified'] = 'The user who gave consent for the policy, if made on behalf of another user.';
|
||||
$string['privacy:metadata:acceptances:timecreated'] = 'The time when the user agreed to the policy.';
|
||||
$string['privacy:metadata:acceptances:timemodified'] = 'The time when the user updated their agreement.';
|
||||
$string['privacy:metadata:acceptances:note'] = 'Any comments added by a user when giving consent on behalf of another user.';
|
||||
$string['privacy:metadata:subsystem:corefiles'] = 'The policy tool stores files included in the summary and full policy.';
|
||||
$string['privacy:metadata:versions'] = 'Policy version information.';
|
||||
$string['privacy:metadata:versions:name'] = 'The name of the policy.';
|
||||
$string['privacy:metadata:versions:type'] = 'Policy type.';
|
||||
$string['privacy:metadata:versions:audience'] = 'The type of users required to give their consent.';
|
||||
$string['privacy:metadata:versions:archived'] = 'The policy status (active or inactive).';
|
||||
$string['privacy:metadata:versions:usermodified'] = 'The user who modified the policy.';
|
||||
$string['privacy:metadata:versions:timecreated'] = 'The time that this version of the policy was created.';
|
||||
$string['privacy:metadata:versions:timemodified'] = 'The time that this version of the policy was updated.';
|
||||
$string['privacy:metadata:versions:policyid'] = 'The policy that this version is associated with.';
|
||||
$string['privacy:metadata:versions:revision'] = 'The revision name of this version of the policy.';
|
||||
$string['privacy:metadata:versions:summary'] = 'The summary of this version of the policy.';
|
||||
$string['privacy:metadata:versions:summaryformat'] = 'The format of the summary field.';
|
||||
$string['privacy:metadata:versions:content'] = 'The content of this version of the policy.';
|
||||
$string['privacy:metadata:versions:contentformat'] = 'The format of the content field.';
|
||||
$string['privacysettings'] = 'Privacy settings';
|
||||
$string['readpolicy'] = 'Please read our {$a}';
|
||||
$string['refertofullpolicytext'] = 'Please refer to the full {$a} if you would like to review the text.';
|
||||
$string['revokeacknowledgement'] = 'I acknowledge that I have received a request to withdraw consent on behalf of user(s).';
|
||||
$string['revokedetails'] = 'Withdraw user consent';
|
||||
$string['save'] = 'Save';
|
||||
$string['saveasdraft'] = 'Save as draft';
|
||||
$string['selectuser'] = 'Select user {$a}';
|
||||
$string['selectusersforconsent'] = 'Select users to give consent on behalf of';
|
||||
$string['settodraft'] = 'Create a new draft';
|
||||
$string['status'] = 'Policy status';
|
||||
$string['statusinfo'] = 'A policy with \'Active\' status requires users to give their consent, either when they first log in, or in the case of existing users when they next log in.';
|
||||
$string['status0'] = 'Draft';
|
||||
$string['status1'] = 'Active';
|
||||
$string['status2'] = 'Inactive';
|
||||
$string['useracceptancecount'] = '{$a->agreedcount} of {$a->userscount} ({$a->percent}%)';
|
||||
$string['useracceptancecountna'] = 'N/A';
|
||||
$string['useracceptances'] = 'User agreements';
|
||||
$string['userpolicysettings'] = 'Policies';
|
||||
$string['usersaccepted'] = 'Agreements';
|
||||
$string['viewarchived'] = 'View previous versions';
|
||||
$string['viewconsentpageforuser'] = 'Viewing this page on behalf of {$a}';
|
||||
@@ -0,0 +1,233 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Plugin version and other meta-data are defined here.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 David Mudrák <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use core_user\output\myprofile\tree;
|
||||
use tool_policy\api;
|
||||
use tool_policy\policy_version;
|
||||
|
||||
/**
|
||||
* Add nodes to myprofile page.
|
||||
*
|
||||
* @param tree $tree Tree object
|
||||
* @param stdClass $user User object
|
||||
* @param bool $iscurrentuser
|
||||
* @param stdClass $course Course object
|
||||
* @return bool
|
||||
* @throws coding_exception
|
||||
* @throws dml_exception
|
||||
* @throws moodle_exception
|
||||
*/
|
||||
function tool_policy_myprofile_navigation(tree $tree, $user, $iscurrentuser, $course) {
|
||||
global $CFG;
|
||||
|
||||
// Do nothing if we are not set as the site policies handler.
|
||||
if (empty($CFG->sitepolicyhandler) || $CFG->sitepolicyhandler !== 'tool_policy') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the Privacy and policies category.
|
||||
if (!array_key_exists('privacyandpolicies', $tree->__get('categories'))) {
|
||||
// Create the category.
|
||||
$categoryname = get_string('privacyandpolicies', 'admin');
|
||||
$category = new core_user\output\myprofile\category('privacyandpolicies', $categoryname, 'contact');
|
||||
$tree->add_category($category);
|
||||
} else {
|
||||
// Get the existing category.
|
||||
$category = $tree->__get('categories')['privacyandpolicies'];
|
||||
}
|
||||
|
||||
// Add "Policies and agreements" node only for current user or users who can accept on behalf of current user.
|
||||
$usercontext = \context_user::instance($user->id);
|
||||
if ($iscurrentuser || has_capability('tool/policy:acceptbehalf', $usercontext)) {
|
||||
$url = new moodle_url('/admin/tool/policy/user.php', ['userid' => $user->id]);
|
||||
$node = new core_user\output\myprofile\node('privacyandpolicies', 'tool_policy',
|
||||
get_string('policiesagreements', 'tool_policy'), null, $url);
|
||||
$category->add_node($node);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load policy message for guests.
|
||||
*
|
||||
* @return string The HTML code to insert before the head.
|
||||
*/
|
||||
function tool_policy_before_standard_html_head() {
|
||||
global $CFG, $PAGE, $USER;
|
||||
|
||||
$message = null;
|
||||
if (!empty($CFG->sitepolicyhandler)
|
||||
&& $CFG->sitepolicyhandler == 'tool_policy'
|
||||
&& empty($USER->policyagreed)
|
||||
&& (isguestuser() || !isloggedin())) {
|
||||
$output = $PAGE->get_renderer('tool_policy');
|
||||
$page = new \tool_policy\output\guestconsent();
|
||||
|
||||
$message = $output->render($page);
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to add footer elements.
|
||||
*
|
||||
* @return str valid html footer content
|
||||
*/
|
||||
function tool_policy_standard_footer_html() {
|
||||
global $CFG;
|
||||
|
||||
$output = '';
|
||||
if (!empty($CFG->sitepolicyhandler)
|
||||
&& $CFG->sitepolicyhandler == 'tool_policy') {
|
||||
$policies = api::get_current_versions_ids();
|
||||
if (!empty($policies)) {
|
||||
$url = (new moodle_url('/admin/tool/policy/viewall.php'))->out();
|
||||
$output .= html_writer::link($url, get_string('userpolicysettings', 'tool_policy'));
|
||||
$output = html_writer::div($output, 'policiesfooter');
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooks redirection to policy acceptance pages before sign up.
|
||||
*/
|
||||
function tool_policy_pre_signup_requests() {
|
||||
global $CFG;
|
||||
|
||||
// Do nothing if we are not set as the site policies handler.
|
||||
if (empty($CFG->sitepolicyhandler) || $CFG->sitepolicyhandler !== 'tool_policy') {
|
||||
return;
|
||||
}
|
||||
|
||||
$policies = api::get_current_versions_ids(policy_version::AUDIENCE_LOGGEDIN);
|
||||
$userpolicyagreed = cache::make('core', 'presignup')->get('tool_policy_userpolicyagreed');
|
||||
if (!empty($policies) && !$userpolicyagreed) {
|
||||
// Redirect to "Policy" pages for consenting before creating the user.
|
||||
cache::make('core', 'presignup')->set('tool_policy_issignup', 1);
|
||||
redirect(new \moodle_url('/admin/tool/policy/index.php'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serve the embedded files.
|
||||
*
|
||||
* @param stdClass $course the course object
|
||||
* @param stdClass $cm the course module object
|
||||
* @param stdClass $context the context
|
||||
* @param string $filearea the name of the file area
|
||||
* @param array $args extra arguments (itemid, path)
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool false if the file not found, just send the file otherwise and do not return anything
|
||||
*/
|
||||
function tool_policy_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $CFG, $PAGE;
|
||||
|
||||
// Do not allow access to files if we are not set as the site policy handler.
|
||||
if (empty($CFG->sitepolicyhandler) || $CFG->sitepolicyhandler !== 'tool_policy') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($context->contextlevel != CONTEXT_SYSTEM) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$PAGE->set_context($context);
|
||||
|
||||
if ($filearea !== 'policydocumentsummary' && $filearea !== 'policydocumentcontent') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$itemid = array_shift($args);
|
||||
|
||||
$policy = api::get_policy_version($itemid);
|
||||
|
||||
if ($policy->status != policy_version::STATUS_ACTIVE) {
|
||||
require_login();
|
||||
}
|
||||
|
||||
if (!api::can_user_view_policy_version($policy)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$filename = array_pop($args);
|
||||
|
||||
if (!$args) {
|
||||
$filepath = '/';
|
||||
} else {
|
||||
$filepath = '/'.implode('/', $args).'/';
|
||||
}
|
||||
|
||||
$fs = get_file_storage();
|
||||
$file = $fs->get_file($context->id, 'tool_policy', $filearea, $itemid, $filepath, $filename);
|
||||
|
||||
if (!$file) {
|
||||
return false;
|
||||
}
|
||||
|
||||
send_stored_file($file, null, 0, $forcedownload, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map icons for font-awesome themes.
|
||||
*/
|
||||
function tool_policy_get_fontawesome_icon_map() {
|
||||
return [
|
||||
'tool_policy:agreedno' => 'fa-times text-danger',
|
||||
'tool_policy:agreedyes' => 'fa-check text-success',
|
||||
'tool_policy:agreedyesonbehalf' => 'fa-check text-info',
|
||||
'tool_policy:level' => 'fa-level-up fa-rotate-90 text-muted',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Serve the new group form as a fragment.
|
||||
*
|
||||
* @param array $args List of named arguments for the fragment loader.
|
||||
* @return string
|
||||
*/
|
||||
function tool_policy_output_fragment_accept_on_behalf($args) {
|
||||
$args = (object) $args;
|
||||
|
||||
$data = [];
|
||||
if (!empty($args->jsonformdata)) {
|
||||
$serialiseddata = json_decode($args->jsonformdata);
|
||||
parse_str($serialiseddata, $data);
|
||||
}
|
||||
|
||||
$mform = new \tool_policy\form\accept_policy(null, $data);
|
||||
|
||||
if (!empty($args->jsonformdata)) {
|
||||
// If we were passed non-empty form data we want the mform to call validation functions and show errors.
|
||||
$mform->is_validated();
|
||||
}
|
||||
|
||||
return $mform->render();
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Manage policy documents used on the site.
|
||||
*
|
||||
* Script arguments:
|
||||
* - archived=<int> Show only archived versions of the given policy document
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 David Mudrák <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require(__DIR__.'/../../../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
|
||||
$archived = optional_param('archived', 0, PARAM_INT);
|
||||
|
||||
admin_externalpage_setup('tool_policy_managedocs', '', ['archived' => $archived]);
|
||||
|
||||
$output = $PAGE->get_renderer('tool_policy');
|
||||
|
||||
$manpage = new \tool_policy\output\page_managedocs_list($archived);
|
||||
|
||||
echo $output->header();
|
||||
echo $output->render($manpage);
|
||||
echo $output->footer();
|
||||
|
After Width: | Height: | Size: 258 B |
@@ -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 |
|
After Width: | Height: | Size: 234 B |
@@ -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 |
|
After Width: | Height: | Size: 234 B |
@@ -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 |
|
After Width: | Height: | Size: 345 B |
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
version="1.1"
|
||||
id="svg4554"
|
||||
sodipodi:docname="level.svg"
|
||||
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
|
||||
inkscape:export-filename="/home/mudrd8mz/www/mdk/gdpr33/moodle/admin/tool/policy/pix/level.png"
|
||||
inkscape:export-xdpi="96.000008"
|
||||
inkscape:export-ydpi="96.000008" preserveAspectRatio="xMinYMid meet">
|
||||
<metadata
|
||||
id="metadata4560">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs4558" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1026"
|
||||
id="namedview4556"
|
||||
showgrid="false"
|
||||
inkscape:showpageshadow="false"
|
||||
inkscape:zoom="16"
|
||||
inkscape:cx="10.805859"
|
||||
inkscape:cy="8.40625"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="25"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4554" />
|
||||
<path
|
||||
d="m 10.60981,13.748496 q -0.42076,-0.2046 -0.42076,-0.6595 v -2.1834 H 0.36389001 q -0.15919999,0 -0.26154001,-0.102297 Q 0,10.700897 0,10.541796 V 2.5361969 q 0,-0.2388 0.20469002,-0.3297 0.22743999,-0.091 0.39800999,0.045 L 2.7860701,4.0708971 q 0.1250916,0.1024 0.1250916,0.2842998 v 3.639 H 10.18905 V 5.810797 q 0,-0.4548999 0.42076,-0.6596001 0.42075,-0.1932998 0.77327,0.1024 L 15.749821,8.892496 Q 16,9.0971966 16,9.4496973 16,9.8022974 15.749821,10.006998 l -4.366741,3.638798 q -0.36389,0.307 -0.77327,0.102297 z"
|
||||
id="path4552"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#999999;fill-opacity:1;stroke-width:0.9999997" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
@@ -0,0 +1,56 @@
|
||||
jQuery EU Cookie Law popups 1.0.1
|
||||
-------------
|
||||
https://github.com/wimagguc/jquery-eu-cookie-law-popup
|
||||
|
||||
Instructions to import 'jQuery EU Cookie Law popups' into Moodle:
|
||||
|
||||
1. Download the latest release from https://github.com/wimagguc/jquery-eu-cookie-law-popup
|
||||
2. Copy 'js/jquery-eu-cookie-law-popup.js' into 'amd/src/jquery-eu-cookie-law-popup.js':
|
||||
|
||||
2.a. Replace jquery reference
|
||||
------------------
|
||||
(function($) {
|
||||
------------------
|
||||
|
||||
to
|
||||
------------------
|
||||
define(
|
||||
['jquery'],
|
||||
function($) {
|
||||
------------------
|
||||
|
||||
2.b. Remove initialisation code. It will be added and configured only in the pages where is needed
|
||||
------------------
|
||||
$(document).ready( function() {
|
||||
if ($(".eupopup").length > 0) {
|
||||
$(document).euCookieLawPopup().init({
|
||||
'info' : 'YOU_CAN_ADD_MORE_SETTINGS_HERE',
|
||||
'popupTitle' : 'This website is using cookies. ',
|
||||
'popupText' : 'We use them to give you the best experience. If you continue using our website, we\'ll assume that you are happy to receive all cookies on this website.'
|
||||
});
|
||||
}
|
||||
------------------
|
||||
|
||||
2.c. Remove code
|
||||
------------------
|
||||
$(document).bind("user_cookie_consent_changed", function(event, object) {
|
||||
console.log("User cookie consent changed: " + $(object).attr('consent') );
|
||||
});
|
||||
|
||||
}(jQuery));
|
||||
------------------
|
||||
|
||||
3. Copy the following styles from 'css/jquery-eu-cookie-law-popup.css' into the
|
||||
"jquery-eu-cookie-law-popup styles" section in 'styles.css':
|
||||
.eupopup-container
|
||||
.eupopup-container-bottom
|
||||
.eupopup-closebutton
|
||||
.eupopup-buttons
|
||||
.eupopup-button
|
||||
.eupopup-button:hover
|
||||
.eupopup-button:focus
|
||||
|
||||
Add "tool_policy styles" to the end of the styles file.
|
||||
|
||||
4. Execute grunt to compile js
|
||||
grunt js
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Plugin administration pages are defined here.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 David Mudrák <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
// Do nothing if we are not set as the site policies handler.
|
||||
if (empty($CFG->sitepolicyhandler) || $CFG->sitepolicyhandler !== 'tool_policy') {
|
||||
return;
|
||||
}
|
||||
|
||||
$managecaps = [
|
||||
'tool/policy:managedocs',
|
||||
'tool/policy:viewacceptances',
|
||||
];
|
||||
|
||||
if ($hassiteconfig || has_any_capability($managecaps, context_system::instance())) {
|
||||
|
||||
$ADMIN->add('privacy', new admin_externalpage(
|
||||
'tool_policy_managedocs',
|
||||
new lang_string('managepolicies', 'tool_policy'),
|
||||
new moodle_url('/admin/tool/policy/managedocs.php'),
|
||||
['tool/policy:managedocs', 'tool/policy:viewacceptances']
|
||||
));
|
||||
$ADMIN->add('privacy', new admin_externalpage(
|
||||
'tool_policy_acceptances',
|
||||
new lang_string('useracceptances', 'tool_policy'),
|
||||
new moodle_url('/admin/tool/policy/acceptances.php'),
|
||||
['tool/policy:viewacceptances']
|
||||
));
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/* jquery-eu-cookie-law-popup styles */
|
||||
.eupopup-container {
|
||||
background-color: rgba(25, 25, 25, 0.9);
|
||||
color: #efefef;
|
||||
padding: 5px 20px;
|
||||
font-size: 12px;
|
||||
line-height: 1.2em;
|
||||
text-align: center;
|
||||
display: none;
|
||||
z-index: 9999999;
|
||||
}
|
||||
|
||||
.eupopup-container-bottom {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.eupopup-closebutton {
|
||||
font-size: 16px;
|
||||
font-weight: 100;
|
||||
line-height: 1;
|
||||
color: #a2a2a2;
|
||||
filter: alpha(opacity=20);
|
||||
position: absolute;
|
||||
font-family: helvetica, arial, verdana, sans-serif;
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
.eupopup-buttons {
|
||||
padding: 7px 0 5px 0;
|
||||
}
|
||||
|
||||
.eupopup-button {
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.eupopup-button:hover,
|
||||
.eupopup-button:focus {
|
||||
text-decoration: underline;
|
||||
color: #f6a21d;
|
||||
}
|
||||
|
||||
/* tool_policy styles */
|
||||
.eupopup-body li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.eupopup-body li:before {
|
||||
content: ", ";
|
||||
}
|
||||
|
||||
.eupopup-body li:first-child:before {
|
||||
content: "";
|
||||
}
|
||||
|
||||
.eupopup-body ul {
|
||||
padding: 0;
|
||||
margin: 0 0 3px;
|
||||
}
|
||||
|
||||
.eupopup-closebutton:hover,
|
||||
.eupopup-closebutton:active {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.eupopup-head {
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
padding: 7px;
|
||||
}
|
||||
|
||||
.eupopup-button_1 {
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.eupopup-button_2 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.eupopup-button {
|
||||
color: #f6a21d;
|
||||
}
|
||||
|
||||
.policy-heading .policy-viewdoc-buttons {
|
||||
text-align: center;
|
||||
margin: 15px;
|
||||
}
|
||||
|
||||
#page-admin-tool-policy-acceptances .colselect {
|
||||
width: 35px;
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
{{!
|
||||
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,
|
||||
"canrevoke": 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
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}}
|
||||
{{^canrevoke}}
|
||||
<div class="alert alert-info">{{#str}} contactdpo, tool_policy {{/str}}</div>
|
||||
{{/canrevoke}}
|
||||
|
||||
<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}}
|
||||
{{#agreement}}
|
||||
<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>
|
||||
{{>tool_policy/user_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>
|
||||
{{/agreement}}
|
||||
{{/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}}
|
||||
@@ -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}}
|
||||
@@ -0,0 +1,88 @@
|
||||
{{!
|
||||
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/guestconsent
|
||||
|
||||
Template for the guest consent message.
|
||||
|
||||
Classes required for JS:
|
||||
* eupopup
|
||||
* policyactions
|
||||
|
||||
Data attributes required for JS:
|
||||
-
|
||||
|
||||
Context variables required for this template:
|
||||
* pluginbaseurl
|
||||
* returnurl - urlencoded URL to return to
|
||||
* haspolicies - true if there are guest policies; false otherwise
|
||||
* policies - array of policy documents
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"pluginbaseurl": "https://example.com",
|
||||
"returnurl": "/",
|
||||
"haspolicies": true,
|
||||
"policies": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Terms & conditions"
|
||||
}
|
||||
]
|
||||
}
|
||||
}}
|
||||
|
||||
{{#js}}
|
||||
|
||||
require(['jquery', 'tool_policy/jquery-eu-cookie-law-popup', 'tool_policy/policyactions'], function($, Popup, ActionsMod) {
|
||||
// Initialise the guest popup.
|
||||
$(document).ready(function() {
|
||||
// Only show message if there is some policy related to guests.
|
||||
{{#haspolicies}}
|
||||
// Get localised messages.
|
||||
var textmessage = "{{# str }} guestconsentmessage, tool_policy {{/ str }}" +
|
||||
"<ul>{{#policies}}" +
|
||||
"<li>" +
|
||||
"<a href=\"{{pluginbaseurl}}/view.php?versionid={{id}}{{#returnurl}}&returnurl={{.}}{{/returnurl}}\" " +
|
||||
" data-action=\"view\" data-versionid=\"{{id}}\" data-behalfid=\"1\" >" +
|
||||
"{{{name}}}" +
|
||||
"</a>" +
|
||||
"</li>" +
|
||||
"{{/policies}}" +
|
||||
"</ul>";
|
||||
var continuemessage = "{{# str }} guestconsent:continue, tool_policy {{/ str }}";
|
||||
|
||||
// Initialize popup.
|
||||
$(document.body).addClass('eupopup');
|
||||
if ($(".eupopup").length > 0) {
|
||||
$(document).euCookieLawPopup().init({
|
||||
popupPosition: 'bottom',
|
||||
popupTitle: '',
|
||||
popupText: textmessage,
|
||||
buttonContinueTitle: continuemessage,
|
||||
buttonLearnmoreTitle: '',
|
||||
compactStyle: true,
|
||||
});
|
||||
}
|
||||
{{/haspolicies}}
|
||||
|
||||
// Initialise the JS for the modal window which displays the policy versions.
|
||||
ActionsMod.init();
|
||||
});
|
||||
});
|
||||
|
||||
{{/js}}
|
||||
@@ -0,0 +1,128 @@
|
||||
{{!
|
||||
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/page_agreedocs
|
||||
|
||||
Template for showing to the user the policy docs to agree.
|
||||
|
||||
Classes required for JS:
|
||||
* policyactions
|
||||
|
||||
Data attributes required for JS:
|
||||
-
|
||||
|
||||
Context variables required for this template:
|
||||
* pluginbaseurl
|
||||
* myurl
|
||||
* sesskey
|
||||
* policies - policy array
|
||||
* behalfuser - If behalfid is defined and valid, full name of the behalf user with a link to his/her profile; null otherwise
|
||||
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"myurl": "/admin/tool/policy/index.php",
|
||||
"sesskey": "123456",
|
||||
"behalfuser": "Sam Student",
|
||||
"policies": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Terms & conditions",
|
||||
"policymodal": "<a href=\"#\">Terms & conditions</a>",
|
||||
"summary": "Policy <u>summary</u>",
|
||||
"versionagreed": false,
|
||||
"versionlangsagreed": "Agreed",
|
||||
"versionbehalfsagreed": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
{{#messages}}{{{.}}}{{/messages}}
|
||||
|
||||
<form id="agreedocsform" method="post" action="{{myurl}}">
|
||||
<input type="hidden" name="sesskey" value="{{sesskey}}">
|
||||
|
||||
{{#behalfuser}}
|
||||
<div class="clearfix">
|
||||
<div class="pull-right m-b-2">
|
||||
{{# str }} viewconsentpageforuser, tool_policy, {{{ . }}} {{/ str }}
|
||||
</div>
|
||||
</div>
|
||||
{{/behalfuser}}
|
||||
|
||||
<div class="clearfix">
|
||||
<div class="pull-left">
|
||||
<h2>{{# str }}consentpagetitle, tool_policy{{/ str }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="clearfix m-t-2">
|
||||
<h3>{{# str }}agreepolicies, tool_policy {{/ str }}</h3>
|
||||
</div>
|
||||
<hr>
|
||||
|
||||
|
||||
{{#policies}}
|
||||
|
||||
<div class="agreedoc-policy clearfix m-t-2 m-b-1">
|
||||
<h3>{{{name}}}</h3>
|
||||
<div class="agreedoc-content">
|
||||
<div class="agreedoc-summary m-b-2">
|
||||
{{{summary}}}
|
||||
</div>
|
||||
<div class="agreedoc-msg">
|
||||
{{# str }}refertofullpolicytext, tool_policy, {{{policymodal}}} {{/ str }}
|
||||
</div>
|
||||
<div class="agreedoc-form m-t-1">
|
||||
<div class="agreedoc-checkbox">
|
||||
<label>
|
||||
<input value="{{id}}" name="agreedoc[]" {{#versionagreed}}checked="{{.}}"{{/versionagreed}} type="checkbox">
|
||||
<strong>{{# str }}iagree, tool_policy, {{{name}}} {{/ str }}</strong>
|
||||
<i class="icon fa fa-exclamation-circle text-danger fa-fw" title="{{# str }} required {{/ str }}" ></i>
|
||||
</label>
|
||||
</div>
|
||||
<ul class="agreedoc-msg list-unstyled">
|
||||
{{#versionlangsagreed}}
|
||||
<li><small>{{{.}}}</small></li>
|
||||
{{/versionlangsagreed}}
|
||||
{{#versionbehalfsagreed}}
|
||||
<li><small>{{{.}}}</small></li>
|
||||
{{/versionbehalfsagreed}}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{/policies}}
|
||||
|
||||
{{# str }}somefieldsrequired, form, <i class="icon fa fa-exclamation-circle text-danger fa-fw" title="{{# str }} required {{/ str }}" ></i>{{/ str }}
|
||||
<hr>
|
||||
|
||||
<input type="submit" class="btn btn-primary" name="submit" value={{#quote}}{{#str}} next {{/str}}{{/quote}}>
|
||||
{{#cancancel}}
|
||||
<input type="submit" class="btn btn-secondary" name="cancel" value={{#quote}}{{#str}} cancel {{/str}}{{/quote}}>
|
||||
{{/cancancel}}
|
||||
</form>
|
||||
|
||||
{{#js}}
|
||||
// Initialise the JS for the modal window which displays the policy versions.
|
||||
require(['tool_policy/policyactions'], function(ActionsMod) {
|
||||
ActionsMod.init();
|
||||
});
|
||||
{{/js}}
|
||||
@@ -0,0 +1,146 @@
|
||||
{{!
|
||||
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/page_managedocs_list
|
||||
|
||||
Template for the policy documents management page.
|
||||
|
||||
Classes required for JS:
|
||||
-
|
||||
|
||||
Data attributes required for JS:
|
||||
* data-policy-name
|
||||
* data-policy-revision
|
||||
* data-action
|
||||
|
||||
Context variables required for this template:
|
||||
* haspolicies
|
||||
* policies
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"title": "Manage policies",
|
||||
"backurl": "/",
|
||||
"pluginbaseurl": "/admin/tool/policy/",
|
||||
"canviewacceptances": true,
|
||||
"canmanage": true,
|
||||
"versions": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Terms & conditions",
|
||||
"typetext": "Site policy",
|
||||
"audiencetext": "All users",
|
||||
"statustext": "Active",
|
||||
"revision": "1.0",
|
||||
"timemodified": 1521531208,
|
||||
"acceptancescounturl": "#",
|
||||
"acceptancescounttext": "10 out of 1000 (1%)"
|
||||
},
|
||||
{
|
||||
"indented": true,
|
||||
"name": "Terms & conditions",
|
||||
"typetext": "Site policy",
|
||||
"audiencetext": "All users",
|
||||
"statustext": "Draft",
|
||||
"revision": "2.0",
|
||||
"timemodified": 1521531208,
|
||||
"acceptancescounttext": "N/A"
|
||||
}
|
||||
]
|
||||
}
|
||||
}}
|
||||
<h2>{{{title}}}</h2>
|
||||
{{#backurl}}
|
||||
<div>
|
||||
<div class="btn-group">
|
||||
<a href="{{backurl}}" class="btn btn-secondary">{{#str}} back {{/str}}</a>
|
||||
</div>
|
||||
</div>
|
||||
{{/backurl}}
|
||||
{{#canaddnew}}
|
||||
<div>
|
||||
<div class="btn-group">
|
||||
<a href="{{pluginbaseurl}}/editpolicydoc.php" class="btn btn-primary">{{#str}} newpolicy, tool_policy {{/str}}</a>
|
||||
</div>
|
||||
</div>
|
||||
{{/canaddnew}}
|
||||
|
||||
<table id="tool-policy-managedocs-wrapper" class="generaltable fullwidth listpolicydocuments">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">{{#str}} policydocname, tool_policy {{/str}}</th>
|
||||
<th scope="col">{{#str}} status, tool_policy {{/str}}</th>
|
||||
<th scope="col">{{#str}} policydocrevision, tool_policy {{/str}}</th>
|
||||
<th scope="col">{{#str}} lastmodified, core {{/str}}</th>
|
||||
{{#canviewacceptances}}
|
||||
<th scope="col">{{#str}} usersaccepted, tool_policy {{/str}}</th>
|
||||
{{/canviewacceptances}}
|
||||
{{#canmanage}}
|
||||
<th scope="col"></th>
|
||||
{{/canmanage}}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#versions}}
|
||||
<tr data-policy-name="{{{name}}}" data-policy-revision="{{revision}}">
|
||||
<td>
|
||||
{{#indented}}
|
||||
<div style="float:left">
|
||||
{{#pix}} level, tool_policy {{/pix}}
|
||||
</div>
|
||||
{{/indented}}
|
||||
<div {{#indented}}style="margin-left: 24px" {{/indented}}>
|
||||
<div>{{{name}}}</div>
|
||||
<div class="text-muted, muted"><small>{{{typetext}}}, {{{audiencetext}}}</small></div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
{{{statustext}}}
|
||||
</td>
|
||||
<td>
|
||||
{{revision}}
|
||||
</td>
|
||||
<td>
|
||||
{{#userdate}} {{timemodified}}, {{#str}} strftimedatetime, core_langconfig {{/str}} {{/userdate}}
|
||||
</td>
|
||||
{{#canviewacceptances}}
|
||||
<td>
|
||||
{{#acceptancescounturl}}
|
||||
<a href="{{acceptancescounturl}}">{{acceptancescounttext}}</a>
|
||||
{{/acceptancescounturl}}
|
||||
{{^acceptancescounturl}}
|
||||
{{acceptancescounttext}}
|
||||
{{/acceptancescounturl}}
|
||||
</td>
|
||||
{{/canviewacceptances}}
|
||||
{{#canmanage}}
|
||||
<td>
|
||||
{{#actionmenu}}
|
||||
{{>core/action_menu}}
|
||||
{{/actionmenu}}
|
||||
</td>
|
||||
{{/canmanage}}
|
||||
</tr>
|
||||
{{/versions}}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{{#js}}
|
||||
require(['tool_policy/managedocsactions'], function(ManageDocsActions) {
|
||||
ManageDocsActions.init('tool-policy-managedocs-wrapper');
|
||||
});
|
||||
{{/js}}
|
||||
@@ -0,0 +1,78 @@
|
||||
{{!
|
||||
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/page_nopermission
|
||||
|
||||
Template for showing to the user the policy docs to agree.
|
||||
|
||||
Classes required for JS:
|
||||
* policyactions
|
||||
|
||||
Data attributes required for JS:
|
||||
-
|
||||
|
||||
Context variables required for this template:
|
||||
* pluginbaseurl
|
||||
* haspermissionagreedocs - status of the capability of the user to accept policy documents
|
||||
* messagetitle - Message title to display, with the error.
|
||||
* messagedesc - Message description to display, with the error.
|
||||
* supportname - name of the support contact; displayed when the user does not have permission to accept policy documents
|
||||
* supportemail - email of the support contact; displayed when the user does not have permission to accept policy documents
|
||||
* behalfuser - If behalfid is defined and valid, full name of the behalf user with a link to his/her profile; null otherwise
|
||||
* policies - Array with all the links to current policies (for showing them if needed).
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"haspermissionagreedocs": false,
|
||||
"messagetitle": "You don't have permission",
|
||||
"messagedesc": "Sorry you don't have permission to accept",
|
||||
"policies": [
|
||||
"Policy 1",
|
||||
"Policy 2"
|
||||
],
|
||||
"supportname": "Admin",
|
||||
"supportemail": "[email protected]"
|
||||
}
|
||||
}}
|
||||
|
||||
{{^haspermissionagreedocs}}
|
||||
<h3>{{{messagetitle}}}</h3>
|
||||
<p class="m-t-1 m-b-1">{{{messagedesc}}}</p>
|
||||
|
||||
<div class="policies">
|
||||
<ul>
|
||||
{{# policies }}
|
||||
<li>{{{.}}}</li>
|
||||
{{/ policies }}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<p class="m-t-3">{{#str}}nopermissiontoagreedocscontact, tool_policy{{/str}}</p>
|
||||
<div class="agreedoc-officer well">
|
||||
<div>
|
||||
<p class="m-b-0">{{{supportname}}}</p>
|
||||
<p class="m-b-0"><a href="mailto:{{supportemail}}">{{supportemail}}</a></p>
|
||||
</div>
|
||||
</div>
|
||||
{{/haspermissionagreedocs}}
|
||||
|
||||
{{#js}}
|
||||
// Initialise the JS for the modal window which displays the policy versions.
|
||||
require(['tool_policy/policyactions'], function(ActionsMod) {
|
||||
ActionsMod.init();
|
||||
});
|
||||
{{/js}}
|
||||
@@ -0,0 +1,103 @@
|
||||
{{!
|
||||
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/page_viewalldoc
|
||||
|
||||
Template for viewing all policy versions, one under another.
|
||||
|
||||
Classes required for JS:
|
||||
-
|
||||
|
||||
Data attributes required for JS:
|
||||
-
|
||||
|
||||
Context variables required for this template:
|
||||
* policies - policy array
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"policies": [
|
||||
{
|
||||
"id": "2",
|
||||
"name": "Terms & conditions",
|
||||
"summary": "Policy <u>summary</u>",
|
||||
"content": "Policy <em>content</em>",
|
||||
"policytypestr": "Site policy",
|
||||
"policyaudiencestr": "All users"
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"name": "Privacy",
|
||||
"summary": "We keep your information private",
|
||||
"content": "Very private",
|
||||
"policytypestr": "Privacy policy",
|
||||
"policyaudiencestr": "Authenticated users"
|
||||
}
|
||||
]
|
||||
}
|
||||
}}
|
||||
|
||||
<a id="top"></a>
|
||||
<div id="policies_index">
|
||||
<h1>{{# str }} listactivepolicies, tool_policy {{/ str }}</h1>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">{{# str }}policydocname, tool_policy {{/ str }}</th>
|
||||
<th scope="col">{{# str }}policydoctype, tool_policy {{/ str }}</th>
|
||||
<th scope="col">{{# str }}policydocaudience, tool_policy {{/ str }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#policies }}
|
||||
<tr>
|
||||
<td><a href="#policy-{{id}}">{{{name}}}</a></td>
|
||||
<td>{{{ policytypestr }}}</td>
|
||||
<td>{{{ policyaudiencestr }}}</td>
|
||||
</tr>
|
||||
{{/policies }}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{{^policies }}
|
||||
{{# str }} noactivepolicies, tool_policy {{/ str }}
|
||||
{{/policies }}
|
||||
|
||||
{{#policies }}
|
||||
<hr>
|
||||
<div class="policy_version m-b-3">
|
||||
<div class="clearfix m-t-2">
|
||||
<h2><a id="policy-{{id}}">{{{name}}}</a></h2>
|
||||
</div>
|
||||
<div class="policy_document_summary clearfix m-b-1">
|
||||
<h3>{{# str }} policydocsummary, tool_policy {{/ str }}</h3>
|
||||
{{{summary}}}
|
||||
</div>
|
||||
<div class="policy_document_content m-t-2">
|
||||
<h3>{{# str }} policydoccontent, tool_policy {{/ str }}</h3>
|
||||
{{{content}}}
|
||||
</div>
|
||||
<div class="pull-right">
|
||||
<a href="#top">
|
||||
{{# str }} backtotop, tool_policy {{/ str }}
|
||||
<i class="icon text-primary fa fa-caret-up" title="{{# str }} backtotop, tool_policy {{/ str }}" ></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{/policies }}
|
||||
@@ -0,0 +1,98 @@
|
||||
{{!
|
||||
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/page_viewdoc
|
||||
|
||||
Template for viewing a policy version document.
|
||||
|
||||
Classes required for JS:
|
||||
-
|
||||
|
||||
Data attributes required for JS:
|
||||
-
|
||||
|
||||
Context variables required for this template:
|
||||
* policy - version document object.
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"numpolicy": 1,
|
||||
"totalpolicies": 2,
|
||||
"policy": {
|
||||
"name": "Terms & conditions",
|
||||
"summary": "Policy <u>summary</u>",
|
||||
"content": "Policy <em>content</em>"
|
||||
},
|
||||
"returnurl": "#",
|
||||
"editurl": "#"
|
||||
}
|
||||
}}
|
||||
|
||||
<a id="top"></a>
|
||||
<div class="clearfix">
|
||||
<div class="pull-left">
|
||||
<h2>{{{policy.name}}}</h2>
|
||||
</div>
|
||||
{{# numpolicy }}
|
||||
<div class="pull-right">
|
||||
{{# str }} steppolicies, tool_policy,
|
||||
{ "numpolicy": {{# quote }}{{numpolicy}}{{/quote }}, "totalpolicies": {{# quote }}{{totalpolicies}}{{/ quote }} }
|
||||
{{/ str }}
|
||||
</div>
|
||||
{{/ numpolicy }}
|
||||
</div>
|
||||
|
||||
|
||||
{{# numpolicy }}
|
||||
<div class="clearfix m-t-2">
|
||||
<h3>{{# str }}readpolicy, tool_policy, {{{policy.name}}} {{/ str }}</h3>
|
||||
</div>
|
||||
{{/ numpolicy }}
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="policy_document m-t-1">
|
||||
<div class="policy_document_summary clearfix m-b-1">
|
||||
{{{policy.summary}}}
|
||||
</div>
|
||||
<div class="policy_document_content m-t-2">
|
||||
{{{policy.content}}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="policy_buttons">
|
||||
{{#returnurl}}
|
||||
{{# numpolicy }}
|
||||
<a role="button" href="{{returnurl}}" class="btn btn-primary">{{#str}} next {{/str}}</a>
|
||||
{{/ numpolicy }}
|
||||
{{^ numpolicy }}
|
||||
<a role="button" href="{{returnurl}}" class="btn btn-primary">{{#str}} back {{/str}}</a>
|
||||
{{/ numpolicy }}
|
||||
{{/returnurl}}
|
||||
{{#editurl}}
|
||||
<a role="button" href="{{editurl}}" class="btn">{{#str}} edit {{/str}}</a>
|
||||
{{/editurl}}
|
||||
|
||||
<div class="pull-right">
|
||||
<a href="#top">
|
||||
{{# str }} backtotop, tool_policy {{/ str }}
|
||||
<i class="icon text-primary fa fa-caret-up" title="{{# str }} backtotop, tool_policy {{/ str }}" ></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,92 @@
|
||||
{{!
|
||||
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,
|
||||
"canrevoke": true,
|
||||
"acceptlink": "/",
|
||||
"revokelink": "/",
|
||||
"singleversion": false,
|
||||
"versionname": ""
|
||||
}
|
||||
}}
|
||||
{{#status}}
|
||||
{{#canrevoke}}
|
||||
{{#singleversion}}
|
||||
{{#onbehalf}}
|
||||
<a href="{{revokelink}}" data-action="acceptmodal">{{#pix}}agreedyesonbehalf, tool_policy,
|
||||
{{#str}} agreedyesonbehalfwithlink, tool_policy, {{{versionname}}} {{/str}}{{/pix}}</a>
|
||||
{{/onbehalf}}
|
||||
{{^onbehalf}}
|
||||
<a href="{{revokelink}}" data-action="acceptmodal">{{#pix}}agreedyes, tool_policy,
|
||||
{{#str}} agreedyeswithlink, tool_policy, {{{versionname}}} {{/str}}{{/pix}}</a>
|
||||
{{/onbehalf}}
|
||||
{{/singleversion}}
|
||||
{{^singleversion}}
|
||||
{{#onbehalf}}
|
||||
<a href="{{revokelink}}" data-action="acceptmodal">{{#pix}}agreedyesonbehalf, tool_policy,
|
||||
{{#str}} agreedyesonbehalfwithlinkall, tool_policy {{/str}}{{/pix}}</a>
|
||||
{{/onbehalf}}
|
||||
{{^onbehalf}}
|
||||
<a href="{{revokelink}}" data-action="acceptmodal">{{#pix}}agreedyes, tool_policy,
|
||||
{{#str}} agreedyeswithlinkall, tool_policy {{/str}}{{/pix}}</a>
|
||||
{{/onbehalf}}
|
||||
{{/singleversion}}
|
||||
{{/canrevoke}}
|
||||
|
||||
{{^canrevoke}}
|
||||
{{#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}}
|
||||
{{/canrevoke}}
|
||||
{{/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}}
|
||||
@@ -0,0 +1,635 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Provides the {@link tool_policy_api_testcase} class.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @category test
|
||||
* @copyright 2018 David Mudrák <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
use tool_policy\api;
|
||||
use tool_policy\policy_version;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link \tool_policy\api} class.
|
||||
*
|
||||
* @copyright 2018 David Mudrak <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tool_policy_api_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test the common operations with a policy document and its versions.
|
||||
*/
|
||||
public function test_policy_document_life_cycle() {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
// Prepare the form data for adding a new policy document.
|
||||
$formdata = api::form_policydoc_data(new policy_version(0));
|
||||
$this->assertObjectHasAttribute('name', $formdata);
|
||||
$this->assertArrayHasKey('text', $formdata->summary_editor);
|
||||
$this->assertArrayHasKey('format', $formdata->content_editor);
|
||||
|
||||
// Save the form.
|
||||
$formdata->name = 'Test terms & conditions';
|
||||
$formdata->type = policy_version::TYPE_OTHER;
|
||||
$policy = api::form_policydoc_add($formdata);
|
||||
$record = $policy->to_record();
|
||||
|
||||
$this->assertNotEmpty($record->id);
|
||||
$this->assertNotEmpty($record->policyid);
|
||||
$this->assertNotEmpty($record->timecreated);
|
||||
$this->assertNotEmpty($record->timemodified);
|
||||
$this->assertNotNull($record->name);
|
||||
$this->assertNotNull($record->summary);
|
||||
$this->assertNotNull($record->summaryformat);
|
||||
$this->assertNotNull($record->content);
|
||||
$this->assertNotNull($record->contentformat);
|
||||
|
||||
// Update the policy document version.
|
||||
$formdata = api::form_policydoc_data($policy);
|
||||
$formdata->revision = '*** Unit test ***';
|
||||
$formdata->summary_editor['text'] = '__Just a summary__';
|
||||
$formdata->summary_editor['format'] = FORMAT_MARKDOWN;
|
||||
$formdata->content_editor['text'] = '### Just a test ###';
|
||||
$formdata->content_editor['format'] = FORMAT_MARKDOWN;
|
||||
$updated = api::form_policydoc_update_overwrite($formdata);
|
||||
$this->assertEquals($policy->get('id'), $updated->get('id'));
|
||||
$this->assertEquals($policy->get('policyid'), $updated->get('policyid'));
|
||||
|
||||
// Save form as a new version.
|
||||
$formdata = api::form_policydoc_data($policy);
|
||||
$formdata->name = 'New terms & conditions';
|
||||
$formdata->revision = '*** Unit test 2 ***';
|
||||
$formdata->summary_editor['text'] = '<strong>Yet another summary</strong>';
|
||||
$formdata->summary_editor['format'] = FORMAT_MOODLE;
|
||||
$formdata->content_editor['text'] = '<h3>Yet another test</h3>';
|
||||
$formdata->content_editor['format'] = FORMAT_HTML;
|
||||
$new = api::form_policydoc_update_new($formdata);
|
||||
$this->assertNotEquals($policy->get('id'), $new->get('id'));
|
||||
$this->assertEquals($policy->get('policyid'), $new->get('policyid'));
|
||||
|
||||
// Add yet another policy document.
|
||||
$formdata = api::form_policydoc_data(new policy_version(0));
|
||||
$formdata->name = 'Privacy terms';
|
||||
$formdata->type = policy_version::TYPE_PRIVACY;
|
||||
$another = api::form_policydoc_add($formdata);
|
||||
|
||||
// Get the list of all policies and their versions.
|
||||
$docs = api::list_policies();
|
||||
$this->assertEquals(2, count($docs));
|
||||
|
||||
// Get just one policy and all its versions.
|
||||
$docs = api::list_policies($another->get('policyid'));
|
||||
$this->assertEquals(1, count($docs));
|
||||
|
||||
// Activate a policy.
|
||||
$this->assertEquals(0, count(api::list_current_versions()));
|
||||
api::make_current($updated->get('id'));
|
||||
$current = api::list_current_versions();
|
||||
$this->assertEquals(1, count($current));
|
||||
$first = reset($current);
|
||||
$this->assertEquals('Test terms & conditions', $first->name);
|
||||
|
||||
// Activate another policy version.
|
||||
api::make_current($new->get('id'));
|
||||
$current = api::list_current_versions();
|
||||
$this->assertEquals(1, count($current));
|
||||
$first = reset($current);
|
||||
$this->assertEquals('New terms & conditions', $first->name);
|
||||
|
||||
// Inactivate the policy.
|
||||
api::inactivate($new->get('policyid'));
|
||||
$this->assertEmpty(api::list_current_versions());
|
||||
$archived = api::get_policy_version($new->get('id'));
|
||||
$this->assertEquals(policy_version::STATUS_ARCHIVED, $archived->status);
|
||||
|
||||
// Create a new draft from an archived version.
|
||||
$draft = api::revert_to_draft($archived->id);
|
||||
$draft = api::get_policy_version($draft->get('id'));
|
||||
$archived = api::get_policy_version($archived->id);
|
||||
$this->assertEmpty(api::list_current_versions());
|
||||
$this->assertNotEquals($draft->id, $archived->id);
|
||||
$this->assertEquals(policy_version::STATUS_DRAFT, $draft->status);
|
||||
$this->assertEquals(policy_version::STATUS_ARCHIVED, $archived->status);
|
||||
|
||||
// An active policy can't be set to draft.
|
||||
api::make_current($draft->id);
|
||||
$this->expectException('coding_exception');
|
||||
$this->expectExceptionMessage('Version not found or is not archived');
|
||||
api::revert_to_draft($draft->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test changing the sort order of the policy documents.
|
||||
*/
|
||||
public function test_policy_sortorder() {
|
||||
global $DB;
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$formdata = api::form_policydoc_data(new policy_version(0));
|
||||
$formdata->name = 'Policy1';
|
||||
$formdata->summary_editor = ['text' => 'P1 summary', 'format' => FORMAT_HTML, 'itemid' => 0];
|
||||
$formdata->content_editor = ['text' => 'P1 content', 'format' => FORMAT_HTML, 'itemid' => 0];
|
||||
$policy1 = api::form_policydoc_add($formdata);
|
||||
$policy1sortorder = $DB->get_field('tool_policy', 'sortorder', ['id' => $policy1->get('policyid')]);
|
||||
|
||||
$formdata = api::form_policydoc_data(new policy_version(0));
|
||||
$formdata->name = 'Policy2';
|
||||
$formdata->summary_editor = ['text' => 'P2 summary', 'format' => FORMAT_HTML, 'itemid' => 0];
|
||||
$formdata->content_editor = ['text' => 'P2 content', 'format' => FORMAT_HTML, 'itemid' => 0];
|
||||
$policy2 = api::form_policydoc_add($formdata);
|
||||
$policy2sortorder = $DB->get_field('tool_policy', 'sortorder', ['id' => $policy2->get('policyid')]);
|
||||
|
||||
$this->assertTrue($policy1sortorder < $policy2sortorder);
|
||||
|
||||
$formdata = api::form_policydoc_data(new policy_version(0));
|
||||
$formdata->name = 'Policy3';
|
||||
$formdata->summary_editor = ['text' => 'P3 summary', 'format' => FORMAT_HTML, 'itemid' => 0];
|
||||
$formdata->content_editor = ['text' => 'P3 content', 'format' => FORMAT_HTML, 'itemid' => 0];
|
||||
$policy3 = api::form_policydoc_add($formdata);
|
||||
$policy3sortorder = $DB->get_field('tool_policy', 'sortorder', ['id' => $policy3->get('policyid')]);
|
||||
|
||||
$this->assertTrue($policy1sortorder < $policy2sortorder);
|
||||
$this->assertTrue($policy2sortorder < $policy3sortorder);
|
||||
|
||||
api::move_up($policy3->get('policyid'));
|
||||
|
||||
$policy1sortorder = $DB->get_field('tool_policy', 'sortorder', ['id' => $policy1->get('policyid')]);
|
||||
$policy2sortorder = $DB->get_field('tool_policy', 'sortorder', ['id' => $policy2->get('policyid')]);
|
||||
$policy3sortorder = $DB->get_field('tool_policy', 'sortorder', ['id' => $policy3->get('policyid')]);
|
||||
|
||||
$this->assertTrue($policy1sortorder < $policy3sortorder);
|
||||
$this->assertTrue($policy3sortorder < $policy2sortorder);
|
||||
|
||||
api::move_down($policy1->get('policyid'));
|
||||
|
||||
$policy1sortorder = $DB->get_field('tool_policy', 'sortorder', ['id' => $policy1->get('policyid')]);
|
||||
$policy2sortorder = $DB->get_field('tool_policy', 'sortorder', ['id' => $policy2->get('policyid')]);
|
||||
$policy3sortorder = $DB->get_field('tool_policy', 'sortorder', ['id' => $policy3->get('policyid')]);
|
||||
|
||||
$this->assertTrue($policy3sortorder < $policy1sortorder);
|
||||
$this->assertTrue($policy1sortorder < $policy2sortorder);
|
||||
|
||||
$orderedlist = [];
|
||||
foreach (api::list_policies() as $policy) {
|
||||
$orderedlist[] = $policy->id;
|
||||
}
|
||||
$this->assertEquals([$policy3->get('policyid'), $policy1->get('policyid'), $policy2->get('policyid')], $orderedlist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that list of policies can be filtered by audience
|
||||
*/
|
||||
public function test_list_policies_audience() {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$policy1 = $this->add_policy(['audience' => policy_version::AUDIENCE_LOGGEDIN]);
|
||||
$policy2 = $this->add_policy(['audience' => policy_version::AUDIENCE_GUESTS]);
|
||||
$policy3 = $this->add_policy();
|
||||
|
||||
api::make_current($policy1->get('id'));
|
||||
api::make_current($policy2->get('id'));
|
||||
api::make_current($policy3->get('id'));
|
||||
|
||||
$list = array_map(function ($version) {
|
||||
return $version->policyid;
|
||||
}, api::list_current_versions());
|
||||
$this->assertEquals([$policy1->get('policyid'), $policy2->get('policyid'), $policy3->get('policyid')],
|
||||
array_values($list));
|
||||
$ids = api::get_current_versions_ids();
|
||||
$this->assertEquals([$policy1->get('policyid') => $policy1->get('id'),
|
||||
$policy2->get('policyid') => $policy2->get('id'),
|
||||
$policy3->get('policyid') => $policy3->get('id')], $ids);
|
||||
|
||||
$list = array_map(function ($version) {
|
||||
return $version->policyid;
|
||||
}, api::list_current_versions(policy_version::AUDIENCE_LOGGEDIN));
|
||||
$this->assertEquals([$policy1->get('policyid'), $policy3->get('policyid')], array_values($list));
|
||||
$ids = api::get_current_versions_ids(policy_version::AUDIENCE_LOGGEDIN);
|
||||
$this->assertEquals([$policy1->get('policyid') => $policy1->get('id'),
|
||||
$policy3->get('policyid') => $policy3->get('id')], $ids);
|
||||
|
||||
$list = array_map(function ($version) {
|
||||
return $version->policyid;
|
||||
}, api::list_current_versions(policy_version::AUDIENCE_GUESTS));
|
||||
$this->assertEquals([$policy2->get('policyid'), $policy3->get('policyid')], array_values($list));
|
||||
$ids = api::get_current_versions_ids(policy_version::AUDIENCE_GUESTS);
|
||||
$this->assertEquals([$policy2->get('policyid') => $policy2->get('id'),
|
||||
$policy3->get('policyid') => $policy3->get('id')], $ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that creates a new policy for testing
|
||||
*
|
||||
* @param array $params
|
||||
* @return policy_version
|
||||
*/
|
||||
protected function add_policy($params = []) {
|
||||
static $counter = 0;
|
||||
$counter++;
|
||||
|
||||
$defaults = [
|
||||
'name' => 'Policy '.$counter,
|
||||
'summary_editor' => ['text' => "P$counter summary", 'format' => FORMAT_HTML, 'itemid' => 0],
|
||||
'content_editor' => ['text' => "P$counter content", 'format' => FORMAT_HTML, 'itemid' => 0],
|
||||
];
|
||||
|
||||
$params = (array)$params + $defaults;
|
||||
$formdata = api::form_policydoc_data(new policy_version(0));
|
||||
foreach ($params as $key => $value) {
|
||||
$formdata->$key = $value;
|
||||
}
|
||||
return api::form_policydoc_add($formdata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that prepare a policy document with some versions.
|
||||
*
|
||||
* @param int $numversions The number of policy versions to create.
|
||||
* @return array Array with all the policy versions created.
|
||||
*/
|
||||
protected function create_versions($numversions = 2) {
|
||||
// Prepare a policy document with some versions.
|
||||
$policy = self::add_policy([
|
||||
'name' => 'Test policy',
|
||||
'revision' => 'v1',
|
||||
]);
|
||||
|
||||
for ($i = 2; $i <= $numversions; $i++) {
|
||||
$formdata = api::form_policydoc_data($policy);
|
||||
$formdata->revision = 'v'.$i;
|
||||
api::form_policydoc_update_new($formdata);
|
||||
}
|
||||
|
||||
$list = api::list_policies($policy->get('policyid'));
|
||||
|
||||
return $list[0]->draftversions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test behaviour of the {@link api::can_user_view_policy_version()} method.
|
||||
*/
|
||||
public function test_can_user_view_policy_version() {
|
||||
global $CFG;
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$child = $this->getDataGenerator()->create_user();
|
||||
$parent = $this->getDataGenerator()->create_user();
|
||||
$this->getDataGenerator()->create_user();
|
||||
$officer = $this->getDataGenerator()->create_user();
|
||||
$manager = $this->getDataGenerator()->create_user();
|
||||
|
||||
$syscontext = context_system::instance();
|
||||
$childcontext = context_user::instance($child->id);
|
||||
|
||||
$roleminorid = create_role('Digital minor', 'digiminor', 'Not old enough to accept site policies themselves');
|
||||
$roleparentid = create_role('Parent', 'parent', 'Can accept policies on behalf of their child');
|
||||
$roleofficerid = create_role('Policy officer', 'policyofficer', 'Can see all acceptances but can\'t edit policy documents');
|
||||
$rolemanagerid = create_role('Policy manager', 'policymanager', 'Can manage policy documents');
|
||||
|
||||
assign_capability('tool/policy:accept', CAP_PROHIBIT, $roleminorid, $syscontext->id);
|
||||
assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $roleparentid, $syscontext->id);
|
||||
assign_capability('tool/policy:viewacceptances', CAP_ALLOW, $roleofficerid, $syscontext->id);
|
||||
assign_capability('tool/policy:managedocs', CAP_ALLOW, $rolemanagerid, $syscontext->id);
|
||||
|
||||
role_assign($roleminorid, $child->id, $syscontext->id);
|
||||
// Becoming a parent is easy. Being a good one is difficult.
|
||||
role_assign($roleparentid, $parent->id, $childcontext->id);
|
||||
role_assign($roleofficerid, $officer->id, $syscontext->id);
|
||||
role_assign($rolemanagerid, $manager->id, $syscontext->id);
|
||||
|
||||
accesslib_clear_all_caches_for_unit_testing();
|
||||
|
||||
// Prepare a policy document with some versions.
|
||||
list($policy1, $policy2, $policy3) = $this->create_versions(3);
|
||||
|
||||
// Normally users do not have access to policy drafts.
|
||||
$this->assertFalse(api::can_user_view_policy_version($policy1, null, $child->id));
|
||||
$this->assertFalse(api::can_user_view_policy_version($policy2, null, $parent->id));
|
||||
$this->assertFalse(api::can_user_view_policy_version($policy3, null, $CFG->siteguest));
|
||||
|
||||
// Officers and managers have access even to drafts.
|
||||
$this->assertTrue(api::can_user_view_policy_version($policy1, null, $officer->id));
|
||||
$this->assertTrue(api::can_user_view_policy_version($policy3, null, $manager->id));
|
||||
|
||||
// Current versions are public so that users can decide whether to even register on such a site.
|
||||
api::make_current($policy2->id);
|
||||
$policy1 = api::get_policy_version($policy1->id);
|
||||
$policy2 = api::get_policy_version($policy2->id);
|
||||
$policy3 = api::get_policy_version($policy3->id);
|
||||
|
||||
$this->assertFalse(api::can_user_view_policy_version($policy1, null, $child->id));
|
||||
$this->assertTrue(api::can_user_view_policy_version($policy2, null, $child->id));
|
||||
$this->assertTrue(api::can_user_view_policy_version($policy2, null, $CFG->siteguest));
|
||||
$this->assertFalse(api::can_user_view_policy_version($policy3, null, $child->id));
|
||||
|
||||
// Let the parent accept the policy on behalf of her child.
|
||||
$this->setUser($parent);
|
||||
api::accept_policies($policy2->id, $child->id);
|
||||
|
||||
// Release a new version of the policy.
|
||||
api::make_current($policy3->id);
|
||||
$policy1 = api::get_policy_version($policy1->id);
|
||||
$policy2 = api::get_policy_version($policy2->id);
|
||||
$policy3 = api::get_policy_version($policy3->id);
|
||||
|
||||
api::get_user_minors($parent->id);
|
||||
// They should now have access to the archived version (because they agreed) and the current one.
|
||||
$this->assertFalse(api::can_user_view_policy_version($policy1, null, $child->id));
|
||||
$this->assertFalse(api::can_user_view_policy_version($policy1, null, $parent->id));
|
||||
$this->assertTrue(api::can_user_view_policy_version($policy2, null, $child->id));
|
||||
$this->assertTrue(api::can_user_view_policy_version($policy2, null, $parent->id));
|
||||
$this->assertTrue(api::can_user_view_policy_version($policy3, null, $child->id));
|
||||
$this->assertTrue(api::can_user_view_policy_version($policy3, null, $parent->id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test behaviour of the {@link api::can_revoke_policies()} method.
|
||||
*/
|
||||
public function test_can_revoke_policies() {
|
||||
global $CFG;
|
||||
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$child = $this->getDataGenerator()->create_user();
|
||||
$parent = $this->getDataGenerator()->create_user();
|
||||
$officer = $this->getDataGenerator()->create_user();
|
||||
$manager = $this->getDataGenerator()->create_user();
|
||||
|
||||
$syscontext = context_system::instance();
|
||||
$childcontext = context_user::instance($child->id);
|
||||
|
||||
$roleminorid = create_role('Digital minor', 'digiminor', 'Not old enough to accept site policies themselves');
|
||||
$roleparentid = create_role('Parent', 'parent', 'Can accept policies on behalf of their child');
|
||||
$roleofficerid = create_role('Policy officer', 'policyofficer', 'Can see all acceptances but can\'t edit policy documents');
|
||||
$rolemanagerid = create_role('Policy manager', 'policymanager', 'Can manage policy documents');
|
||||
|
||||
assign_capability('tool/policy:accept', CAP_PROHIBIT, $roleminorid, $syscontext->id);
|
||||
assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $roleparentid, $syscontext->id);
|
||||
assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $roleofficerid, $syscontext->id);
|
||||
assign_capability('tool/policy:viewacceptances', CAP_ALLOW, $roleofficerid, $syscontext->id);
|
||||
assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $rolemanagerid, $syscontext->id);
|
||||
assign_capability('tool/policy:managedocs', CAP_ALLOW, $rolemanagerid, $syscontext->id);
|
||||
|
||||
role_assign($roleminorid, $child->id, $syscontext->id);
|
||||
// Becoming a parent is easy. Being a good one is difficult.
|
||||
role_assign($roleparentid, $parent->id, $childcontext->id);
|
||||
role_assign($roleofficerid, $officer->id, $syscontext->id);
|
||||
role_assign($rolemanagerid, $manager->id, $syscontext->id);
|
||||
|
||||
accesslib_clear_all_caches_for_unit_testing();
|
||||
|
||||
// Prepare a policy document with some versions.
|
||||
list($policy1, $policy2, $policy3) = $this->create_versions(3);
|
||||
|
||||
// Normally users do not have access to revoke policies.
|
||||
$this->setUser($user);
|
||||
$this->assertFalse(api::can_revoke_policies($user->id));
|
||||
$this->setUser($child);
|
||||
$this->assertFalse(api::can_revoke_policies($child->id));
|
||||
|
||||
// The parent can revoke the policy on behalf of her child (but not her own policies).
|
||||
$this->setUser($parent);
|
||||
$this->assertFalse(api::can_revoke_policies($parent->id));
|
||||
$this->assertTrue(api::can_revoke_policies($child->id));
|
||||
|
||||
// Officers and managers can revoke everything.
|
||||
$this->setUser($officer);
|
||||
$this->assertTrue(api::can_revoke_policies($officer->id));
|
||||
$this->assertTrue(api::can_revoke_policies($child->id));
|
||||
$this->assertTrue(api::can_revoke_policies($parent->id));
|
||||
$this->assertTrue(api::can_revoke_policies($manager->id));
|
||||
|
||||
$this->setUser($manager);
|
||||
$this->assertTrue(api::can_revoke_policies($manager->id));
|
||||
$this->assertTrue(api::can_revoke_policies($child->id));
|
||||
$this->assertTrue(api::can_revoke_policies($parent->id));
|
||||
$this->assertTrue(api::can_revoke_policies($officer->id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test {@link api::fix_revision_values()} behaviour.
|
||||
*/
|
||||
public function test_fix_revision_values() {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$versions = [
|
||||
(object) ['id' => 80, 'timecreated' => mktime(1, 1, 1, 12, 28, 2018), 'revision' => '', 'e' => '28 December 2018'],
|
||||
(object) ['id' => 70, 'timecreated' => mktime(1, 1, 1, 12, 27, 2018), 'revision' => '', 'e' => '27 December 2018 - v2'],
|
||||
(object) ['id' => 60, 'timecreated' => mktime(1, 1, 1, 12, 27, 2018), 'revision' => '', 'e' => '27 December 2018 - v1'],
|
||||
(object) ['id' => 50, 'timecreated' => mktime(0, 0, 0, 12, 26, 2018), 'revision' => '0', 'e' => '0'],
|
||||
(object) ['id' => 40, 'timecreated' => mktime(0, 0, 0, 12, 26, 2018), 'revision' => '1.1', 'e' => '1.1 - v2'],
|
||||
(object) ['id' => 30, 'timecreated' => mktime(0, 0, 0, 12, 26, 2018), 'revision' => '1.1', 'e' => '1.1 - v1'],
|
||||
(object) ['id' => 20, 'timecreated' => mktime(0, 0, 0, 12, 26, 2018), 'revision' => '', 'e' => '26 December 2018'],
|
||||
(object) ['id' => 10, 'timecreated' => mktime(17, 57, 00, 12, 25, 2018), 'revision' => '1.0', 'e' => '1.0'],
|
||||
];
|
||||
|
||||
api::fix_revision_values($versions);
|
||||
|
||||
foreach ($versions as $version) {
|
||||
$this->assertSame($version->revision, $version->e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that accepting policy updates 'policyagreed'
|
||||
*/
|
||||
public function test_accept_policies() {
|
||||
global $DB;
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$policy1 = $this->add_policy()->to_record();
|
||||
api::make_current($policy1->id);
|
||||
$policy2 = $this->add_policy()->to_record();
|
||||
api::make_current($policy2->id);
|
||||
|
||||
// Accept policy on behalf of somebody else.
|
||||
$user1 = $this->getDataGenerator()->create_user();
|
||||
$this->assertEquals(0, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
|
||||
|
||||
api::accept_policies([$policy1->id, $policy2->id], $user1->id);
|
||||
$this->assertEquals(1, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
|
||||
|
||||
// Now revoke.
|
||||
api::revoke_acceptance($policy1->id, $user1->id);
|
||||
$this->assertEquals(0, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
|
||||
|
||||
// Accept policies for oneself.
|
||||
$user2 = $this->getDataGenerator()->create_user();
|
||||
$this->setUser($user2);
|
||||
|
||||
$this->assertEquals(0, $DB->get_field('user', 'policyagreed', ['id' => $user2->id]));
|
||||
|
||||
api::accept_policies([$policy1->id]);
|
||||
$this->assertEquals(0, $DB->get_field('user', 'policyagreed', ['id' => $user2->id]));
|
||||
|
||||
api::accept_policies([$policy2->id]);
|
||||
$this->assertEquals(1, $DB->get_field('user', 'policyagreed', ['id' => $user2->id]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that activating a new policy resets everybody's policyagreed flag in the database.
|
||||
*/
|
||||
public function test_reset_policyagreed() {
|
||||
global $DB;
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$user1 = $this->getDataGenerator()->create_user();
|
||||
|
||||
// Introducing a new policy.
|
||||
list($policy1v1, $policy1v2) = $this->create_versions(2);
|
||||
api::make_current($policy1v1->id);
|
||||
$this->assertEquals(0, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
|
||||
api::accept_policies([$policy1v1->id], $user1->id);
|
||||
$this->assertEquals(1, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
|
||||
|
||||
// Introducing another policy.
|
||||
$policy2v1 = $this->add_policy()->to_record();
|
||||
api::make_current($policy2v1->id);
|
||||
$this->assertEquals(0, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
|
||||
api::accept_policies([$policy2v1->id], $user1->id);
|
||||
$this->assertEquals(1, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
|
||||
|
||||
// Updating an existing policy (major update).
|
||||
api::make_current($policy1v2->id);
|
||||
$this->assertEquals(0, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
|
||||
api::accept_policies([$policy1v2->id], $user1->id);
|
||||
$this->assertEquals(1, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
|
||||
|
||||
// Do not touch the flag if there is no new version (e.g. a minor update).
|
||||
api::make_current($policy2v1->id);
|
||||
api::make_current($policy1v2->id);
|
||||
$this->assertEquals(1, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
|
||||
|
||||
// Do not touch the flag if inactivating a policy.
|
||||
api::inactivate($policy1v2->policyid);
|
||||
$this->assertEquals(1, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
|
||||
|
||||
// Do not touch the flag if setting to draft a policy.
|
||||
api::revert_to_draft($policy1v2->id);
|
||||
$this->assertEquals(1, $DB->get_field('user', 'policyagreed', ['id' => $user1->id]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test behaviour of the {@link api::get_user_minors()} method.
|
||||
*/
|
||||
public function test_get_user_minors() {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// A mother having two children, each child having own father.
|
||||
$mother1 = $this->getDataGenerator()->create_user();
|
||||
$father1 = $this->getDataGenerator()->create_user();
|
||||
$father2 = $this->getDataGenerator()->create_user();
|
||||
$child1 = $this->getDataGenerator()->create_user();
|
||||
$child2 = $this->getDataGenerator()->create_user();
|
||||
|
||||
$syscontext = context_system::instance();
|
||||
$child1context = context_user::instance($child1->id);
|
||||
$child2context = context_user::instance($child2->id);
|
||||
|
||||
$roleparentid = create_role('Parent', 'parent', 'Can accept policies on behalf of their child');
|
||||
|
||||
assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $roleparentid, $syscontext->id);
|
||||
|
||||
role_assign($roleparentid, $mother1->id, $child1context->id);
|
||||
role_assign($roleparentid, $mother1->id, $child2context->id);
|
||||
role_assign($roleparentid, $father1->id, $child1context->id);
|
||||
role_assign($roleparentid, $father2->id, $child2context->id);
|
||||
|
||||
accesslib_clear_all_caches_for_unit_testing();
|
||||
|
||||
$mother1minors = api::get_user_minors($mother1->id);
|
||||
$this->assertEquals(2, count($mother1minors));
|
||||
|
||||
$father1minors = api::get_user_minors($father1->id);
|
||||
$this->assertEquals(1, count($father1minors));
|
||||
$this->assertEquals($child1->id, $father1minors[$child1->id]->id);
|
||||
|
||||
$father2minors = api::get_user_minors($father2->id);
|
||||
$this->assertEquals(1, count($father2minors));
|
||||
$this->assertEquals($child2->id, $father2minors[$child2->id]->id);
|
||||
|
||||
$this->assertEmpty(api::get_user_minors($child1->id));
|
||||
$this->assertEmpty(api::get_user_minors($child2->id));
|
||||
|
||||
$extradata = api::get_user_minors($mother1->id, ['policyagreed', 'deleted']);
|
||||
$this->assertTrue(property_exists($extradata[$child1->id], 'policyagreed'));
|
||||
$this->assertTrue(property_exists($extradata[$child1->id], 'deleted'));
|
||||
$this->assertTrue(property_exists($extradata[$child2->id], 'policyagreed'));
|
||||
$this->assertTrue(property_exists($extradata[$child2->id], 'deleted'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test behaviour of the {@link api::create_acceptances_user_created()} method.
|
||||
*/
|
||||
public function test_create_acceptances_user_created() {
|
||||
global $CFG, $DB;
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$CFG->sitepolicyhandler = 'tool_policy';
|
||||
|
||||
$policy = $this->add_policy()->to_record();
|
||||
api::make_current($policy->id);
|
||||
|
||||
// User has not accepted any policies.
|
||||
$user1 = $this->getDataGenerator()->create_user();
|
||||
\core\event\user_created::create_from_userid($user1->id)->trigger();
|
||||
|
||||
$this->assertEquals(0, $DB->count_records('tool_policy_acceptances',
|
||||
['userid' => $user1->id, 'policyversionid' => $policy->id]));
|
||||
|
||||
// User has accepted policies.
|
||||
$user2 = $this->getDataGenerator()->create_user();
|
||||
$DB->set_field('user', 'policyagreed', 1, ['id' => $user2->id]);
|
||||
\core\event\user_created::create_from_userid($user2->id)->trigger();
|
||||
|
||||
$this->assertEquals(1, $DB->count_records('tool_policy_acceptances',
|
||||
['userid' => $user2->id, 'policyversionid' => $policy->id]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that user can login if sitepolicyhandler is set but there are no policies.
|
||||
*/
|
||||
public function test_login_with_handler_without_policies() {
|
||||
global $CFG;
|
||||
|
||||
$this->resetAfterTest();
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$this->setUser($user);
|
||||
|
||||
$CFG->sitepolicyhandler = 'tool_policy';
|
||||
|
||||
require_login(null, false, null, false, true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
@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 "Users > 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 "Consent not given" "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 "Users > 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 "Consent not given" "link" in the "User One" "table_row"
|
||||
Then I should see "Give consent on behalf of user"
|
||||
And I should see "User One"
|
||||
And I should see "This site policy"
|
||||
And I should see "I acknowledge that I have received a request to give consent on behalf of user(s)."
|
||||
And I set the field "Remarks" to "Consent received from a parent"
|
||||
And I press "Give consent on behalf of user"
|
||||
And "Consent given on behalf of user" "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 "Consent not given" "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 should not see "Next"
|
||||
And I navigate to "Users > 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 "Consent not given" "link" in the "User One" "table_row"
|
||||
Then I should see "Give consent on behalf of user"
|
||||
And I should see "User One"
|
||||
And I should see "This site policy"
|
||||
And I should see "I acknowledge that I have received a request to give consent on behalf of user(s)."
|
||||
And I set the field "Remarks" to "Consent received from a parent"
|
||||
And I press "Give consent on behalf of user"
|
||||
And "Consent given on behalf of user" "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 "Consent not given" "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 "Users > 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 "Users > Privacy and policies > User agreements" in site administration
|
||||
And "Agreed" "icon" should exist in the "User One" "table_row"
|
||||
And "Consent not given" "icon" should not exist in the "User One" "table_row"
|
||||
And "Agreed" "icon" should exist in the "Max Manager" "table_row"
|
||||
And "Consent not given" "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 "Users > Privacy and policies > User agreements" in site administration
|
||||
And I click on "0 of 2" "link" in the "User Two" "table_row"
|
||||
And "Consent not given" "icon" should exist in the "This site policy" "table_row"
|
||||
And "Consent not given" "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 "Users > 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 "Users > Privacy and policies > User agreements" in site administration
|
||||
And I click on "Consent not given; click to give consent on behalf of user for This site policy" "link" in the "User One" "table_row"
|
||||
Then I should see "Give consent on behalf of user"
|
||||
And I should see "User One"
|
||||
And I should see "This site policy"
|
||||
And I should see "I acknowledge that I have received a request to give consent on behalf of user(s)."
|
||||
And I set the field "Remarks" to "Consent received from a parent"
|
||||
And I press "Give consent on behalf of user"
|
||||
And "Consent given on behalf of user" "icon" should exist in the "User One" "table_row"
|
||||
And "Consent not given; click to give consent on behalf of user for 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 "Consent given on behalf of user" "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 "Consent not given" "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 "Users > 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 "Users > Privacy and policies > User agreements" in site administration
|
||||
And I click on "Consent not given; click to give consent on behalf of user for This site policy" "link" in the "User One" "table_row"
|
||||
Then I should see "Give consent on behalf of user"
|
||||
And I should see "User One"
|
||||
And I should see "This site policy"
|
||||
And I should see "I acknowledge that I have received a request to give consent on behalf of user(s)."
|
||||
And I set the field "Remarks" to "Consent received from a parent"
|
||||
And I press "Give consent on behalf of user"
|
||||
And "Consent given on behalf of user" "icon" should exist in the "User One" "table_row"
|
||||
And "Consent not given; click to give consent on behalf of user for 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 "Consent given on behalf of user" "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 "Consent not given" "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"
|
||||
|
||||
Scenario: Agree on behalf of another user as an admin who is logged in as a manager
|
||||
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 log out
|
||||
And I log in as "admin"
|
||||
And I navigate to "Users > Accounts > Browse list of users" in site administration
|
||||
And I follow "Manager"
|
||||
And I follow "Log in as"
|
||||
And I press "Continue"
|
||||
And I navigate to "Users > 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 "Consent not given" "link" in the "User One" "table_row"
|
||||
Then I should see "Give consent on behalf of user"
|
||||
And I should see "User One"
|
||||
And I should see "This site policy"
|
||||
And I should see "I acknowledge that I have received a request to give consent on behalf of user(s)."
|
||||
And I set the field "Remarks" to "Consent received from a parent"
|
||||
And I press "Give consent on behalf of user"
|
||||
And "Consent given on behalf of user" "icon" should exist in the "User One" "table_row"
|
||||
And "Max Manager" "link" should not exist in the "User One" "table_row"
|
||||
And "Admin User" "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 "Consent not given" "icon" should exist in the "User Two" "table_row"
|
||||
@@ -0,0 +1,121 @@
|
||||
<?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:$/
|
||||
*
|
||||
* Supported table fields:
|
||||
*
|
||||
* - Name: Policy name (required).
|
||||
* - Revision: Revision name (policy version).
|
||||
* - Status: Policy version status - 'draft', 'active' or 'archived'. Defaults to 'active'.
|
||||
* - Audience: Target users - 'guest', 'all' or 'loggedin'. Default to 'all'.
|
||||
* - Type: 0 - site policy, 1 - privacy policy, 2 - third party policy, 99 - other.
|
||||
* - Summary: Policy summary text.
|
||||
* - Content: Policy full text.
|
||||
*
|
||||
* @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',
|
||||
'revision',
|
||||
'policy',
|
||||
'status',
|
||||
'audience',
|
||||
'type',
|
||||
'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'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,666 @@
|
||||
@tool @tool_policy
|
||||
Feature: User must accept policy managed by this plugin when logging in and signing up
|
||||
In order to record user agreement to use the site
|
||||
As a user
|
||||
I need to be able to accept site policy during sign up
|
||||
|
||||
Scenario: Accept policy on sign up, no site policy
|
||||
Given the following config values are set as admin:
|
||||
| registerauth | email |
|
||||
| passwordpolicy | 0 |
|
||||
| sitepolicyhandler | tool_policy |
|
||||
And I am on site homepage
|
||||
And I follow "Log in"
|
||||
When I press "Create new account"
|
||||
Then I should not see "I understand and agree"
|
||||
And I set the following fields to these values:
|
||||
| Username | user1 |
|
||||
| Password | user1 |
|
||||
| Email address | user1@address.invalid |
|
||||
| Email (again) | user1@address.invalid |
|
||||
| First name | User1 |
|
||||
| Surname | L1 |
|
||||
And I press "Create my new account"
|
||||
And I should see "Confirm your account"
|
||||
And I should see "An email should have been sent to your address at user1@address.invalid"
|
||||
And I confirm email for "user1"
|
||||
And I should see "Thanks, User1 L1"
|
||||
And I should see "Your registration has been confirmed"
|
||||
And I open my profile in edit mode
|
||||
And the field "First name" matches value "User1"
|
||||
And I log out
|
||||
# Confirm that user can login and browse the site (edit their profile).
|
||||
And I log in as "user1"
|
||||
And I open my profile in edit mode
|
||||
And the field "First name" matches value "User1"
|
||||
|
||||
Scenario: Accept policy on sign up, only draft policy
|
||||
Given the following config values are set as admin:
|
||||
| registerauth | email |
|
||||
| passwordpolicy | 0 |
|
||||
| sitepolicyhandler | tool_policy |
|
||||
And the following policies exist:
|
||||
| Policy | Name | Revision | Content | Summary | Status |
|
||||
| P1 | This site policy | | full text1 | short text1 | draft |
|
||||
| P1 | This privacy policy | | full text2 | short text2 | draft |
|
||||
And I am on site homepage
|
||||
And I follow "Log in"
|
||||
When I press "Create new account"
|
||||
Then I should not see "I understand and agree"
|
||||
And I set the following fields to these values:
|
||||
| Username | user1 |
|
||||
| Password | user1 |
|
||||
| Email address | user1@address.invalid |
|
||||
| Email (again) | user1@address.invalid |
|
||||
| First name | User1 |
|
||||
| Surname | L1 |
|
||||
And I press "Create my new account"
|
||||
And I should see "Confirm your account"
|
||||
And I should see "An email should have been sent to your address at user1@address.invalid"
|
||||
And I confirm email for "user1"
|
||||
And I should see "Thanks, User1 L1"
|
||||
And I should see "Your registration has been confirmed"
|
||||
And I open my profile in edit mode
|
||||
And the field "First name" matches value "User1"
|
||||
And I log out
|
||||
# Confirm that user can login and browse the site (edit their profile).
|
||||
And I log in as "user1"
|
||||
And I open my profile in edit mode
|
||||
And the field "First name" matches value "User1"
|
||||
|
||||
Scenario: Accept policy on sign up, one policy
|
||||
Given the following config values are set as admin:
|
||||
| registerauth | email |
|
||||
| passwordpolicy | 0 |
|
||||
| sitepolicyhandler | tool_policy |
|
||||
Given the following policies exist:
|
||||
| Policy | Name | Revision | Content | Summary | Status |
|
||||
| P1 | This site policy | | full text1 | short text1 | archived |
|
||||
| P1 | This site policy | | full text2 | short text2 | active |
|
||||
| P1 | This site policy | | full text3 | short text3 | draft |
|
||||
And I am on site homepage
|
||||
And I follow "Log in"
|
||||
When I press "Create new account"
|
||||
Then I should see "This site policy" in the "region-main" "region"
|
||||
And I should see "short text2"
|
||||
And I should see "full text2"
|
||||
And I press "Next"
|
||||
And I should see "Please agree to the following policies"
|
||||
And I should see "This site policy" in the "region-main" "region"
|
||||
And I should see "short text2"
|
||||
And I should not see "full text2"
|
||||
And I set the field "I agree to the This site policy" to "1"
|
||||
And I press "Next"
|
||||
And I should not see "I understand and agree"
|
||||
And I set the following fields to these values:
|
||||
| Username | user1 |
|
||||
| Password | user1 |
|
||||
| Email address | user1@address.invalid |
|
||||
| Email (again) | user1@address.invalid |
|
||||
| First name | User1 |
|
||||
| Surname | L1 |
|
||||
And I press "Create my new account"
|
||||
And I should see "Confirm your account"
|
||||
And I should see "An email should have been sent to your address at user1@address.invalid"
|
||||
And I confirm email for "user1"
|
||||
And I should see "Thanks, User1 L1"
|
||||
And I should see "Your registration has been confirmed"
|
||||
And I open my profile in edit mode
|
||||
And the field "First name" matches value "User1"
|
||||
And I log out
|
||||
# Confirm that user can login and browse the site.
|
||||
And I log in as "user1"
|
||||
And I follow "Profile" in the user menu
|
||||
# User can see his own agreements in the profile.
|
||||
And I follow "Policies and agreements"
|
||||
And "Agreed" "icon" should exist in the "This site policy" "table_row"
|
||||
And I log out
|
||||
|
||||
Scenario: Accept policy on sign up, multiple policies
|
||||
Given the following config values are set as admin:
|
||||
| registerauth | email |
|
||||
| passwordpolicy | 0 |
|
||||
| sitepolicyhandler | tool_policy |
|
||||
Given the following policies exist:
|
||||
| Name | Type | Revision | Content | Summary | Status | Audience |
|
||||
| This site policy | 0 | | full text2 | short text2 | active | all |
|
||||
| This privacy policy | 1 | | full text3 | short text3 | active | loggedin |
|
||||
| This guests policy | 0 | | full text4 | short text4 | active | guest |
|
||||
And I am on site homepage
|
||||
And I follow "Log in"
|
||||
When I press "Create new account"
|
||||
Then I should see "This site policy" in the "region-main" "region"
|
||||
And I should see "short text2"
|
||||
And I should see "full text2"
|
||||
And I press "Next"
|
||||
And I should see "This privacy policy" in the "region-main" "region"
|
||||
And I should see "short text3"
|
||||
And I should see "full text3"
|
||||
And I press "Next"
|
||||
And I should see "Please agree to the following policies"
|
||||
And I should see "This site policy" in the "region-main" "region"
|
||||
And I should see "short text2"
|
||||
And I should not see "full text2"
|
||||
And I should see "This privacy policy" in the "region-main" "region"
|
||||
And I should see "short text3"
|
||||
And I should not see "full text3"
|
||||
And I should not see "This guests policy" in the "region-main" "region"
|
||||
And I should not see "short text4"
|
||||
And I should not see "full text4"
|
||||
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 not see "I understand and agree"
|
||||
And I set the following fields to these values:
|
||||
| Username | user1 |
|
||||
| Password | user1 |
|
||||
| Email address | user1@address.invalid |
|
||||
| Email (again) | user1@address.invalid |
|
||||
| First name | User1 |
|
||||
| Surname | L1 |
|
||||
And I press "Create my new account"
|
||||
And I should see "Confirm your account"
|
||||
And I should see "An email should have been sent to your address at user1@address.invalid"
|
||||
And I confirm email for "user1"
|
||||
And I should see "Thanks, User1 L1"
|
||||
And I should see "Your registration has been confirmed"
|
||||
And I open my profile in edit mode
|
||||
And the field "First name" matches value "User1"
|
||||
And I log out
|
||||
# Confirm that user can login and browse the site.
|
||||
And I log in as "user1"
|
||||
And I follow "Profile" in the user menu
|
||||
# User can see his own agreements in the profile.
|
||||
And I follow "Policies and agreements"
|
||||
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 should not see "This guests policy"
|
||||
And I log out
|
||||
|
||||
Scenario: Accept policy on sign up and age verification
|
||||
Given the following config values are set as admin:
|
||||
| registerauth | email |
|
||||
| passwordpolicy | 0 |
|
||||
| sitepolicyhandler | tool_policy |
|
||||
| agedigitalconsentverification | 1 |
|
||||
Given the following policies exist:
|
||||
| Name | Revision | Content | Summary | Status |
|
||||
| This site policy | | full text2 | short text2 | active |
|
||||
And I am on site homepage
|
||||
And I follow "Log in"
|
||||
When I press "Create new account"
|
||||
Then I should see "Age and location verification"
|
||||
And I set the field "What is your age?" to "16"
|
||||
And I set the field "In which country do you live?" to "DZ"
|
||||
And I press "Proceed"
|
||||
And I should see "This site policy"
|
||||
And I should see "short text2"
|
||||
And I should see "full text2"
|
||||
And I press "Next"
|
||||
And I should see "Please agree to the following policies"
|
||||
And I should see "This site policy"
|
||||
And I should see "short text2"
|
||||
And I should not see "full text2"
|
||||
And I set the field "I agree to the This site policy" to "1"
|
||||
And I press "Next"
|
||||
And I should not see "I understand and agree"
|
||||
And I set the following fields to these values:
|
||||
| Username | user1 |
|
||||
| Password | user1 |
|
||||
| Email address | user1@address.invalid |
|
||||
| Email (again) | user1@address.invalid |
|
||||
| First name | User1 |
|
||||
| Surname | L1 |
|
||||
And I press "Create my new account"
|
||||
And I should see "Confirm your account"
|
||||
And I should see "An email should have been sent to your address at user1@address.invalid"
|
||||
And I confirm email for "user1"
|
||||
And I should see "Thanks, User1 L1"
|
||||
And I should see "Your registration has been confirmed"
|
||||
And I open my profile in edit mode
|
||||
And the field "First name" matches value "User1"
|
||||
And I log out
|
||||
# Confirm that user can login and browse the site.
|
||||
And I log in as "user1"
|
||||
And I follow "Profile" in the user menu
|
||||
# User can see his own agreements in the profile.
|
||||
And I follow "Policies and agreements"
|
||||
And "Agreed" "icon" should exist in the "This site policy" "table_row"
|
||||
And I log out
|
||||
|
||||
Scenario: Accept policy on sign up, do not accept all policies
|
||||
Given the following config values are set as admin:
|
||||
| registerauth | email |
|
||||
| passwordpolicy | 0 |
|
||||
| sitepolicyhandler | tool_policy |
|
||||
And the following policies exist:
|
||||
| Name | Type | Revision | Content | Summary | Status | Audience |
|
||||
| This site policy | 0 | | full text2 | short text2 | active | all |
|
||||
| This privacy policy | 1 | | full text3 | short text3 | active | loggedin |
|
||||
And I am on site homepage
|
||||
And I follow "Log in"
|
||||
And I press "Create new account"
|
||||
And I should see "This site policy"
|
||||
And I press "Next"
|
||||
And I should see "This privacy policy"
|
||||
And I press "Next"
|
||||
And I should see "Please agree to the following policies"
|
||||
And I should see "This site policy"
|
||||
And I should see "This privacy policy"
|
||||
# Confirm that a notification is displayed if none of the policies are accepted.
|
||||
When I set the field "I agree to the This site policy" to "0"
|
||||
And I set the field "I agree to the This privacy policy" to "0"
|
||||
And I press "Next"
|
||||
Then I should see "Please agree to the following policies"
|
||||
And I should see "Before continuing you must agree to all these policies."
|
||||
# Confirm that a notification is displayed if only some policies are accepted.
|
||||
When 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 "0"
|
||||
Then I should see "Please agree to the following policies"
|
||||
And I should see "Before continuing you must agree to all these policies."
|
||||
|
||||
Scenario: Accept policy on login, do not accept all policies
|
||||
Given the following config values are set as admin:
|
||||
| registerauth | email |
|
||||
| passwordpolicy | 0 |
|
||||
| sitepolicyhandler | tool_policy |
|
||||
And the following policies exist:
|
||||
| Name | Type | Revision | Content | Summary | Status | Audience |
|
||||
| This site policy | 0 | | full text2 | short text2 | active | all |
|
||||
| This privacy policy | 1 | | full text3 | short text3 | active | loggedin |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| user1 | User | 1 | user1@example.com |
|
||||
And I log in as "user1"
|
||||
And I should see "This site policy"
|
||||
And I press "Next"
|
||||
And I should see "This privacy policy"
|
||||
And I press "Next"
|
||||
And I should see "Please agree to the following policies"
|
||||
And I should see "This site policy"
|
||||
And I should see "This privacy policy"
|
||||
# Confirm that a notification is displayed if none of the policies are accepted.
|
||||
When I set the field "I agree to the This site policy" to "0"
|
||||
And I set the field "I agree to the This privacy policy" to "0"
|
||||
And I press "Next"
|
||||
Then I should see "Please agree to the following policies"
|
||||
And I should see "Before continuing you must agree to all these policies."
|
||||
# Confirm that a notification is displayed if only some policies are accepted.
|
||||
When 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 "0"
|
||||
Then I should see "Please agree to the following policies"
|
||||
And I should see "Before continuing you must agree to all these policies."
|
||||
# Confirm that user can not browse the site (edit their profile).
|
||||
When I follow "Profile" in the user menu
|
||||
Then I should see "Please agree to the following policies"
|
||||
|
||||
Scenario: Accept policy on login, accept all policies
|
||||
Given the following config values are set as admin:
|
||||
| registerauth | email |
|
||||
| passwordpolicy | 0 |
|
||||
| sitepolicyhandler | tool_policy |
|
||||
And the following policies exist:
|
||||
| Name | Type | Revision | Content | Summary | Status | Audience |
|
||||
| This site policy | 0 | | full text2 | short text2 | active | all |
|
||||
| This privacy policy | 1 | | full text3 | short text3 | active | loggedin |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| user1 | User | 1 | user1@example.com |
|
||||
And I log in as "user1"
|
||||
And I should see "This site policy"
|
||||
And I press "Next"
|
||||
And I should see "This privacy policy"
|
||||
And I press "Next"
|
||||
And I should see "Please agree to the following policies"
|
||||
And I should see "This site policy"
|
||||
And I should see "This privacy policy"
|
||||
# User accepts all policies.
|
||||
When 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"
|
||||
Then I should not see "Please agree to the following policies"
|
||||
And I should not see "Before continuing you must agree to all these policies."
|
||||
# Confirm that user can login and browse the site (edit their profile).
|
||||
When I open my profile in edit mode
|
||||
Then the field "First name" matches value "User"
|
||||
And I log out
|
||||
# Confirm when logging again as user, the policies are not displayed.
|
||||
When I log in as "user1"
|
||||
Then I should not see "This site policy"
|
||||
And I should not see "This privacy policy"
|
||||
And I should not see "Please agree to the following policies"
|
||||
# Confirm that user can login and browse the site (edit their profile).
|
||||
When I open my profile in edit mode
|
||||
Then the field "First name" matches value "User"
|
||||
|
||||
Scenario: Accept policy on login, accept new policy documents
|
||||
Given the following config values are set as admin:
|
||||
| registerauth | email |
|
||||
| passwordpolicy | 0 |
|
||||
| sitepolicyhandler | tool_policy |
|
||||
And the following policies exist:
|
||||
| Name | Type | Revision | Content | Summary | Status | Audience |
|
||||
| This site policy | 0 | | full text2 | short text2 | active | all |
|
||||
| This privacy policy | 1 | | full text3 | short text3 | active | loggedin |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| user1 | User | 1 | user1@example.com |
|
||||
And I log in as "user1"
|
||||
And I should see "This site policy"
|
||||
And I press "Next"
|
||||
And I should see "This privacy policy"
|
||||
And I press "Next"
|
||||
And I should see "Please agree to the following policies"
|
||||
And I should see "This site policy"
|
||||
And I should see "This privacy policy"
|
||||
# User accepts all policies.
|
||||
When 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"
|
||||
Then I should not see "Please agree to the following policies"
|
||||
# Confirm that user can login and browse the site (edit their profile).
|
||||
When I open my profile in edit mode
|
||||
Then the field "First name" matches value "User"
|
||||
And I log out
|
||||
# Create new policy document.
|
||||
And I log in as "admin"
|
||||
And I navigate to "Manage policies" node in "Site administration > Privacy and policies"
|
||||
And I should see "Policies and agreements"
|
||||
And I should see "New policy"
|
||||
And I follow "New policy"
|
||||
And I set the following fields to these values:
|
||||
| Name | This third parties policy |
|
||||
| Type | Third parties policy |
|
||||
| User consent | All users |
|
||||
| Summary | short text4 |
|
||||
| Full policy | full text4 |
|
||||
| Active | 1 |
|
||||
When I press "Save"
|
||||
Then I should see "Policies and agreements"
|
||||
And I should see "This third parties policy"
|
||||
And I log out
|
||||
# Confirm when logging again as user, the new policies are displayed.
|
||||
When I log in as "user1"
|
||||
And I should not see "This site policy"
|
||||
And I should not see "This privacy policy"
|
||||
Then I should see "This third parties policy"
|
||||
And I press "Next"
|
||||
And I should see "Please agree to the following policies"
|
||||
And I should see "This third parties policy"
|
||||
And I set the field "This third parties policy" to "1"
|
||||
And I press "Next"
|
||||
# Confirm that user can login and browse the site (edit their profile).
|
||||
When I open my profile in edit mode
|
||||
Then the field "First name" matches value "User"
|
||||
|
||||
Scenario: Accept policy on login, accept new policy version
|
||||
Given the following config values are set as admin:
|
||||
| registerauth | email |
|
||||
| passwordpolicy | 0 |
|
||||
| sitepolicyhandler | tool_policy |
|
||||
And the following policies exist:
|
||||
| Name | Type | Revision | Content | Summary | Status | Audience |
|
||||
| This site policy | 0 | | full text2 | short text2 | active | all |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| user1 | User | 1 | user1@example.com |
|
||||
And I log in as "user1"
|
||||
And I should see "This site policy"
|
||||
And I press "Next"
|
||||
And I should see "Please agree to the following policies"
|
||||
And I should see "This site policy"
|
||||
# User accepts policy.
|
||||
When I set the field "I agree to the This site policy" to "1"
|
||||
And I press "Next"
|
||||
Then I should not see "Please agree to the following policies"
|
||||
# Confirm that user can login and browse the site (edit their profile).
|
||||
When I open my profile in edit mode
|
||||
Then the field "First name" matches value "User"
|
||||
And I log out
|
||||
# Create new version of the policy document.
|
||||
And I log in as "admin"
|
||||
And I navigate to "Manage policies" node in "Site administration > Privacy and policies"
|
||||
When I follow "Actions"
|
||||
Then I should see "View"
|
||||
And I should see "Edit"
|
||||
And I should see "Set status to \"Inactive\""
|
||||
When I follow "Edit"
|
||||
Then I should see "Editing policy"
|
||||
And I set the field "Name" to "This site policy new version"
|
||||
And I set the field "Summary" to "short text2 new version"
|
||||
And I set the field "Full policy" to "full text2 new version"
|
||||
And I press "Save"
|
||||
And I log out
|
||||
# Confirm that the user has to agree to the new version of the policy.
|
||||
When I log in as "user1"
|
||||
Then I should see "This site policy new version"
|
||||
And I should see "short text2 new version"
|
||||
And I should see "full text2 new version"
|
||||
When I press "Next"
|
||||
Then I should see "Please agree to the following policies"
|
||||
And I should see "This site policy new version"
|
||||
And I should see "short text2 new version"
|
||||
# User accepts policy.
|
||||
And I set the field "I agree to the This site policy new version" to "1"
|
||||
When I press "Next"
|
||||
Then I should not see "Please agree to the following policies"
|
||||
# Confirm that user can login and browse the site (edit their profile).
|
||||
When I open my profile in edit mode
|
||||
Then the field "First name" matches value "User"
|
||||
|
||||
@javascript
|
||||
Scenario: Accept policy on login as guest
|
||||
Given the following config values are set as admin:
|
||||
| registerauth | email |
|
||||
| passwordpolicy | 0 |
|
||||
| sitepolicyhandler | tool_policy |
|
||||
And the following policies exist:
|
||||
| Name | Type | Revision | Content | Summary | Status | Audience |
|
||||
| This site policy | 0 | | full text2 | short text2 | active | all |
|
||||
| This privacy policy | 1 | | full text3 | short text3 | active | loggedin |
|
||||
| This guests policy | 0 | | full text4 | short text4 | active | guest |
|
||||
And I am on site homepage
|
||||
And I change window size to "large"
|
||||
And I follow "Log in"
|
||||
When I press "Log in as a guest"
|
||||
Then I should see "If you continue browsing this website, you agree to our policies"
|
||||
# Confirm when navigating, the pop-up policies are displayed.
|
||||
When I follow "Home"
|
||||
Then I should see "If you continue browsing this website, you agree to our policies"
|
||||
And I should see "This site policy"
|
||||
And I should see "This guests policy"
|
||||
And I should not see "This privacy policy"
|
||||
# Confirm when clicking on the policy links, the policy content is displayed.
|
||||
When I click on "This site policy" "link"
|
||||
Then I should see "full text2"
|
||||
And I click on "Close" "button"
|
||||
And I should not see "full text2"
|
||||
When I click on "This guests policy" "link"
|
||||
Then I should see "full text4"
|
||||
And I click on "Close" "button"
|
||||
And I should not see "full text4"
|
||||
# Confirm when agreeing to policies the pop-up is no longer displayed.
|
||||
When I follow "Continue"
|
||||
Then I should not see "If you continue browsing this website, you agree to our policies"
|
||||
|
||||
Scenario: Accept policy on sign up, after completing sign up attempt to create another account
|
||||
Given the following config values are set as admin:
|
||||
| registerauth | email |
|
||||
| passwordpolicy | 0 |
|
||||
| sitepolicyhandler | tool_policy |
|
||||
Given the following policies exist:
|
||||
| Name | Type | Revision | Content | Summary | Status | Audience |
|
||||
| This site policy | 0 | | full text2 | short text2 | active | all |
|
||||
| This privacy policy | 1 | | full text3 | short text3 | active | loggedin |
|
||||
| This guests policy | 0 | | full text4 | short text4 | active | guest |
|
||||
And I am on site homepage
|
||||
And I follow "Log in"
|
||||
When I press "Create new account"
|
||||
Then I should see "This site policy" in the "region-main" "region"
|
||||
And I should see "short text2"
|
||||
And I should see "full text2"
|
||||
When I press "Next"
|
||||
Then I should see "This privacy policy" in the "region-main" "region"
|
||||
And I should see "short text3"
|
||||
And I should see "full text3"
|
||||
When I press "Next"
|
||||
Then I should see "Please agree to the following policies"
|
||||
And I should see "This site policy" in the "region-main" "region"
|
||||
And I should see "short text2"
|
||||
And I should see "This privacy policy" in the "region-main" "region"
|
||||
And I should see "short text3"
|
||||
And I should not see "This guests policy" in the "region-main" "region"
|
||||
And I should not see "short text4"
|
||||
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"
|
||||
When I press "Next"
|
||||
Then I should not see "I understand and agree"
|
||||
And I should see "New account"
|
||||
And I set the following fields to these values:
|
||||
| Username | user1 |
|
||||
| Password | user1 |
|
||||
| Email address | user1@address.invalid |
|
||||
| Email (again) | user1@address.invalid |
|
||||
| First name | User1 |
|
||||
| Surname | L1 |
|
||||
When I press "Create my new account"
|
||||
Then I should see "Confirm your account"
|
||||
And I should see "An email should have been sent to your address at user1@address.invalid"
|
||||
And I follow "Log in"
|
||||
When I press "Create new account"
|
||||
# Confirm that the user can view and accept policies when attempting to create another account.
|
||||
Then I should see "This site policy" in the "region-main" "region"
|
||||
And I should see "short text2"
|
||||
And I should see "full text2"
|
||||
When I press "Next"
|
||||
Then I should see "This privacy policy" in the "region-main" "region"
|
||||
And I should see "short text3"
|
||||
And I should see "full text3"
|
||||
When I press "Next"
|
||||
Then I should see "Please agree to the following policies"
|
||||
And I should see "This site policy" in the "region-main" "region"
|
||||
And I should see "short text2"
|
||||
And I should not see "full text2"
|
||||
And I should see "This privacy policy" in the "region-main" "region"
|
||||
And I should see "short text3"
|
||||
And I should not see "full text3"
|
||||
And I should not see "This guests policy" in the "region-main" "region"
|
||||
And I should not see "short text4"
|
||||
And I should not see "full text4"
|
||||
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"
|
||||
When I press "Next"
|
||||
Then I should not see "I understand and agree"
|
||||
And I should see "New account"
|
||||
|
||||
Scenario: Accept policy while being logged in as another user
|
||||
Given the following config values are set as admin:
|
||||
| sitepolicyhandler | tool_policy |
|
||||
And the following policies exist:
|
||||
| Name | Type | Revision | Content | Summary | Status | Audience |
|
||||
| This site policy | 0 | | full text2 | short text2 | active | all |
|
||||
| This privacy policy | 1 | | full text3 | short text3 | active | loggedin |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| user1 | User | 1 | user1@example.com |
|
||||
When I log in as "admin"
|
||||
And I navigate to "Users > Accounts > Browse list of users" in site administration
|
||||
And I follow "User 1"
|
||||
And I follow "Log in as"
|
||||
Then I should see "You are logged in as User 1"
|
||||
And I press "Continue"
|
||||
And I should see "Please read our This site policy"
|
||||
And I press "Next"
|
||||
And I should see "Please read our This privacy policy"
|
||||
And I press "Next"
|
||||
And I should see "Viewing this page on behalf of User 1"
|
||||
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 log out
|
||||
And I log in as "user1"
|
||||
And I follow "Profile" in the user menu
|
||||
And I follow "Policies and agreements"
|
||||
And "Admin User" "link" should exist in the "This site policy" "table_row"
|
||||
And "Admin User" "link" should exist in the "This privacy policy" "table_row"
|
||||
|
||||
Scenario: Log in as another user without capability to accept policies on their behalf
|
||||
Given the following config values are set as admin:
|
||||
| sitepolicyhandler | tool_policy |
|
||||
And the following policies exist:
|
||||
| Name | Type | Revision | Content | Summary | Status | Audience |
|
||||
| This site policy | 0 | | full text2 | short text2 | active | all |
|
||||
| This privacy policy | 1 | | full text3 | short text3 | active | loggedin |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| user1 | User | 1 | user1@example.com |
|
||||
| manager | Max | Manager | man@example.com |
|
||||
And the following "role assigns" exist:
|
||||
| user | role | contextlevel | reference |
|
||||
| manager | manager | System | |
|
||||
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 "Users > Accounts > Browse list of users" in site administration
|
||||
And I follow "User 1"
|
||||
And I follow "Log in as"
|
||||
Then I should see "You are logged in as User 1"
|
||||
And I press "Continue"
|
||||
And I should see "Policies and agreements"
|
||||
And I should see "No permission to agree to the policies on behalf of this user"
|
||||
And I should see "Sorry, you do not have the required permission to agree to the following policies on behalf of User 1"
|
||||
|
||||
Scenario: Accept policy on sign up as a guest, one policy
|
||||
Given the following config values are set as admin:
|
||||
| registerauth | email |
|
||||
| passwordpolicy | 0 |
|
||||
| sitepolicyhandler | tool_policy |
|
||||
Given the following policies exist:
|
||||
| Policy | Name | Revision | Content | Summary | Status |
|
||||
| P1 | This site policy | | full text1 | short text1 | archived |
|
||||
| P1 | This site policy | | full text2 | short text2 | active |
|
||||
| P1 | This site policy | | full text3 | short text3 | draft |
|
||||
And I am on site homepage
|
||||
And I follow "Log in"
|
||||
# First log in as a guest
|
||||
And I press "Log in as a guest"
|
||||
# Now sign up
|
||||
And I follow "Log in"
|
||||
When I press "Create new account"
|
||||
Then I should see "This site policy"
|
||||
And I should see "short text2"
|
||||
And I should see "full text2"
|
||||
And I press "Next"
|
||||
And I should see "Please agree to the following policies"
|
||||
And I should see "This site policy"
|
||||
And I should see "short text2"
|
||||
And I should not see "full text2"
|
||||
And I set the field "I agree to the This site policy" to "1"
|
||||
And I press "Next"
|
||||
And I should not see "I understand and agree"
|
||||
And I set the following fields to these values:
|
||||
| Username | user1 |
|
||||
| Password | user1 |
|
||||
| Email address | user1@address.invalid |
|
||||
| Email (again) | user1@address.invalid |
|
||||
| First name | User1 |
|
||||
| Surname | L1 |
|
||||
And I press "Create my new account"
|
||||
And I should see "Confirm your account"
|
||||
And I should see "An email should have been sent to your address at user1@address.invalid"
|
||||
And I confirm email for "user1"
|
||||
And I should see "Thanks, User1 L1"
|
||||
And I should see "Your registration has been confirmed"
|
||||
And I open my profile in edit mode
|
||||
And the field "First name" matches value "User1"
|
||||
And I log out
|
||||
# Confirm that user can login and browse the site.
|
||||
And I log in as "user1"
|
||||
And I follow "Profile" in the user menu
|
||||
# User can see his own agreements in the profile.
|
||||
And I follow "Policies and agreements"
|
||||
And "Agreed" "icon" should exist in the "This site policy" "table_row"
|
||||
And I log out
|
||||
@@ -0,0 +1,258 @@
|
||||
@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 "Users > 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 "manager"
|
||||
And I navigate to "Users > 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 "Users > 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 "Users > 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 "Users > 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 "Users > 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 "manager"
|
||||
And I navigate to "Users > 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 "manager"
|
||||
And I navigate to "Users > 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 agree to 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 "Users > 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 "You are about to inactivate policy"
|
||||
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 "Users > 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
|
||||
@@ -0,0 +1,232 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* External policy webservice API tests.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Sara Arjona <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
require_once($CFG->libdir . '/externallib.php');
|
||||
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
|
||||
require_once($CFG->dirroot . '/user/externallib.php');
|
||||
|
||||
use tool_policy\api;
|
||||
use tool_policy\external;
|
||||
use tool_mobile\external as external_mobile;
|
||||
|
||||
/**
|
||||
* External policy webservice API tests.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Sara Arjona <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tool_policy_external_testcase extends externallib_advanced_testcase {
|
||||
|
||||
/**
|
||||
* Setup function- we will create some policy docs.
|
||||
*/
|
||||
public function setUp() {
|
||||
$this->resetAfterTest(true);
|
||||
$this->setAdminUser();
|
||||
|
||||
// Prepare a policy document with some versions.
|
||||
$formdata = api::form_policydoc_data(new \tool_policy\policy_version(0));
|
||||
$formdata->name = 'Test policy';
|
||||
$formdata->revision = 'v1';
|
||||
$formdata->summary_editor = ['text' => 'summary', 'format' => FORMAT_HTML, 'itemid' => 0];
|
||||
$formdata->content_editor = ['text' => 'content', 'format' => FORMAT_HTML, 'itemid' => 0];
|
||||
$this->policy1 = api::form_policydoc_add($formdata);
|
||||
|
||||
$formdata = api::form_policydoc_data($this->policy1);
|
||||
$formdata->revision = 'v2';
|
||||
$this->policy2 = api::form_policydoc_update_new($formdata);
|
||||
|
||||
$formdata = api::form_policydoc_data($this->policy1);
|
||||
$formdata->revision = 'v3';
|
||||
$this->policy3 = api::form_policydoc_update_new($formdata);
|
||||
|
||||
api::make_current($this->policy2->get('id'));
|
||||
|
||||
// Create users.
|
||||
$this->child = $this->getDataGenerator()->create_user();
|
||||
$this->parent = $this->getDataGenerator()->create_user();
|
||||
$this->adult = $this->getDataGenerator()->create_user();
|
||||
|
||||
$syscontext = context_system::instance();
|
||||
$childcontext = context_user::instance($this->child->id);
|
||||
|
||||
$roleminorid = create_role('Digital minor', 'digiminor', 'Not old enough to accept site policies themselves');
|
||||
$roleparentid = create_role('Parent', 'parent', 'Can accept policies on behalf of their child');
|
||||
|
||||
assign_capability('tool/policy:accept', CAP_PROHIBIT, $roleminorid, $syscontext->id);
|
||||
assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $roleparentid, $syscontext->id);
|
||||
|
||||
role_assign($roleminorid, $this->child->id, $syscontext->id);
|
||||
role_assign($roleparentid, $this->parent->id, $childcontext->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for the get_policy_version() function.
|
||||
*/
|
||||
public function test_get_policy_version() {
|
||||
$this->setUser($this->adult);
|
||||
|
||||
// View current policy version.
|
||||
$result = external::get_policy_version($this->policy2->get('id'));
|
||||
$result = external_api::clean_returnvalue(external::get_policy_version_returns(), $result);
|
||||
$this->assertCount(1, $result['result']);
|
||||
$this->assertEquals($this->policy1->get('name'), $result['result']['policy']['name']);
|
||||
$this->assertEquals($this->policy1->get('content'), $result['result']['policy']['content']);
|
||||
|
||||
// View draft policy version.
|
||||
$result = external::get_policy_version($this->policy3->get('id'));
|
||||
$result = external_api::clean_returnvalue(external::get_policy_version_returns(), $result);
|
||||
$this->assertCount(0, $result['result']);
|
||||
$this->assertCount(1, $result['warnings']);
|
||||
$this->assertEquals(array_pop($result['warnings'])['warningcode'], 'errorusercantviewpolicyversion');
|
||||
|
||||
// Add test for non existing versionid.
|
||||
$result = external::get_policy_version(999);
|
||||
$result = external_api::clean_returnvalue(external::get_policy_version_returns(), $result);
|
||||
$this->assertCount(0, $result['result']);
|
||||
$this->assertCount(1, $result['warnings']);
|
||||
$this->assertEquals(array_pop($result['warnings'])['warningcode'], 'errorpolicyversionnotfound');
|
||||
|
||||
// View previous non-accepted version in behalf of a child.
|
||||
$this->setUser($this->parent);
|
||||
$result = external::get_policy_version($this->policy1->get('id'), $this->child->id);
|
||||
$result = external_api::clean_returnvalue(external::get_policy_version_returns(), $result);
|
||||
$this->assertCount(0, $result['result']);
|
||||
$this->assertCount(1, $result['warnings']);
|
||||
$this->assertEquals(array_pop($result['warnings'])['warningcode'], 'errorusercantviewpolicyversion');
|
||||
|
||||
// Let the parent accept the policy on behalf of her child and view it again.
|
||||
api::accept_policies($this->policy1->get('id'), $this->child->id);
|
||||
$result = external::get_policy_version($this->policy1->get('id'), $this->child->id);
|
||||
$result = external_api::clean_returnvalue(external::get_policy_version_returns(), $result);
|
||||
$this->assertCount(1, $result['result']);
|
||||
$this->assertEquals($this->policy1->get('name'), $result['result']['policy']['name']);
|
||||
$this->assertEquals($this->policy1->get('content'), $result['result']['policy']['content']);
|
||||
|
||||
// Only parent is able to view the child policy version accepted by her child.
|
||||
$this->setUser($this->adult);
|
||||
$result = external::get_policy_version($this->policy1->get('id'), $this->child->id);
|
||||
$result = external_api::clean_returnvalue(external::get_policy_version_returns(), $result);
|
||||
$this->assertCount(0, $result['result']);
|
||||
$this->assertCount(1, $result['warnings']);
|
||||
$this->assertEquals(array_pop($result['warnings'])['warningcode'], 'errorusercantviewpolicyversion');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test tool_mobile\external callback to site_policy_handler.
|
||||
*/
|
||||
public function test_get_config_with_site_policy_handler() {
|
||||
global $CFG;
|
||||
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
// Set the handler for the site policy, make sure it substitutes link to the sitepolicy.
|
||||
$CFG->sitepolicyhandler = 'tool_policy';
|
||||
$sitepolicymanager = new core_privacy\local\sitepolicy\manager();
|
||||
$result = external_mobile::get_config();
|
||||
$result = external_api::clean_returnvalue(external_mobile::get_config_returns(), $result);
|
||||
$toolsitepolicy = $sitepolicymanager->get_embed_url();
|
||||
foreach (array_values($result['settings']) as $r) {
|
||||
if ($r['name'] == 'sitepolicy') {
|
||||
$configsitepolicy = $r['value'];
|
||||
}
|
||||
}
|
||||
$this->assertEquals($toolsitepolicy, $configsitepolicy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for core_privacy\sitepolicy\manager::accept() when site policy handler is set.
|
||||
*/
|
||||
public function test_agree_site_policy_with_handler() {
|
||||
global $CFG, $DB, $USER;
|
||||
|
||||
$this->resetAfterTest(true);
|
||||
$user = self::getDataGenerator()->create_user();
|
||||
$this->setUser($user);
|
||||
|
||||
// Set mock site policy handler. See function tool_phpunit_site_policy_handler() below.
|
||||
$CFG->sitepolicyhandler = 'tool_policy';
|
||||
$this->assertEquals(0, $USER->policyagreed);
|
||||
$sitepolicymanager = new core_privacy\local\sitepolicy\manager();
|
||||
|
||||
// Make sure user can not login.
|
||||
$toolconsentpage = $sitepolicymanager->get_redirect_url();
|
||||
$this->expectException('moodle_exception');
|
||||
$this->expectExceptionMessage(get_string('sitepolicynotagreed', 'error', $toolconsentpage->out()));
|
||||
core_user_external::validate_context(context_system::instance());
|
||||
|
||||
// Call WS to agree to the site policy. It will call tool_policy handler.
|
||||
$result = core_user_external::agree_site_policy();
|
||||
$result = external_api::clean_returnvalue(core_user_external::agree_site_policy_returns(), $result);
|
||||
$this->assertTrue($result['status']);
|
||||
$this->assertCount(0, $result['warnings']);
|
||||
$this->assertEquals(1, $USER->policyagreed);
|
||||
$this->assertEquals(1, $DB->get_field('user', 'policyagreed', array('id' => $USER->id)));
|
||||
|
||||
// Try again, we should get a warning.
|
||||
$result = core_user_external::agree_site_policy();
|
||||
$result = external_api::clean_returnvalue(core_user_external::agree_site_policy_returns(), $result);
|
||||
$this->assertFalse($result['status']);
|
||||
$this->assertCount(1, $result['warnings']);
|
||||
$this->assertEquals('alreadyagreed', $result['warnings'][0]['warningcode']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for core_privacy\sitepolicy\manager::accept() when site policy handler is set.
|
||||
*/
|
||||
public function test_checkcanaccept_with_handler() {
|
||||
global $CFG;
|
||||
|
||||
$this->resetAfterTest(true);
|
||||
$CFG->sitepolicyhandler = 'tool_policy';
|
||||
$syscontext = context_system::instance();
|
||||
$sitepolicymanager = new core_privacy\local\sitepolicy\manager();
|
||||
|
||||
$adult = $this->getDataGenerator()->create_user();
|
||||
|
||||
$child = $this->getDataGenerator()->create_user();
|
||||
$rolechildid = create_role('Child', 'child', 'Not old enough to accept site policies themselves');
|
||||
assign_capability('tool/policy:accept', CAP_PROHIBIT, $rolechildid, $syscontext->id);
|
||||
role_assign($rolechildid, $child->id, $syscontext->id);
|
||||
|
||||
// Default user can accept policies.
|
||||
$this->setUser($adult);
|
||||
$result = external_mobile::get_config();
|
||||
$result = external_api::clean_returnvalue(external_mobile::get_config_returns(), $result);
|
||||
$toolsitepolicy = $sitepolicymanager->accept();
|
||||
$this->assertTrue($toolsitepolicy);
|
||||
|
||||
// Child user can not accept policies.
|
||||
$this->setUser($child);
|
||||
$result = external_mobile::get_config();
|
||||
$result = external_api::clean_returnvalue(external_mobile::get_config_returns(), $result);
|
||||
$this->expectException('required_capability_exception');
|
||||
$sitepolicymanager->accept();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,313 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Privacy provider tests.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @category test
|
||||
* @copyright 2018 Sara Arjona <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
use core_privacy\local\metadata\collection;
|
||||
use tool_policy\privacy\provider;
|
||||
use tool_policy\api;
|
||||
use tool_policy\policy_version;
|
||||
use core_privacy\local\request\approved_contextlist;
|
||||
use core_privacy\local\request\writer;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Privacy provider tests class.
|
||||
*
|
||||
* @copyright 2018 Sara Arjona <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tool_policy_privacy_provider_testcase extends \core_privacy\tests\provider_testcase {
|
||||
/** @var stdClass The user object. */
|
||||
protected $user;
|
||||
|
||||
/** @var stdClass The manager user object. */
|
||||
protected $manager;
|
||||
|
||||
/**
|
||||
* Setup function. Will create a user.
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$generator = $this->getDataGenerator();
|
||||
$this->user = $generator->create_user();
|
||||
|
||||
// Create manager user.
|
||||
$this->manager = $generator->create_user();
|
||||
$syscontext = context_system::instance();
|
||||
$rolemanagerid = create_role('Policy manager', 'policymanager', 'Can manage policy documents');
|
||||
assign_capability('tool/policy:managedocs', CAP_ALLOW, $rolemanagerid, $syscontext->id);
|
||||
assign_capability('tool/policy:acceptbehalf', CAP_ALLOW, $rolemanagerid, $syscontext->id);
|
||||
role_assign($rolemanagerid, $this->manager->id, $syscontext->id);
|
||||
accesslib_clear_all_caches_for_unit_testing();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getting the context for the user ID related to this plugin.
|
||||
*/
|
||||
public function test_get_contexts_for_userid() {
|
||||
global $CFG;
|
||||
|
||||
// When there are no policies or agreements context list is empty.
|
||||
$contextlist = \tool_policy\privacy\provider::get_contexts_for_userid($this->manager->id);
|
||||
$this->assertEmpty($contextlist);
|
||||
$contextlist = \tool_policy\privacy\provider::get_contexts_for_userid($this->user->id);
|
||||
$this->assertEmpty($contextlist);
|
||||
|
||||
// Create a policy.
|
||||
$this->setUser($this->manager);
|
||||
$CFG->sitepolicyhandler = 'tool_policy';
|
||||
$policy = $this->add_policy();
|
||||
api::make_current($policy->get('id'));
|
||||
|
||||
// After creating a policy, there should be manager context.
|
||||
$contextlist = \tool_policy\privacy\provider::get_contexts_for_userid($this->manager->id);
|
||||
$this->assertEquals(1, $contextlist->count());
|
||||
|
||||
// But when there are no agreements, user context list is empty.
|
||||
$contextlist = \tool_policy\privacy\provider::get_contexts_for_userid($this->user->id);
|
||||
$this->assertEmpty($contextlist);
|
||||
|
||||
// Agree to the policy.
|
||||
$this->setUser($this->user);
|
||||
api::accept_policies([$policy->get('id')]);
|
||||
|
||||
// There should be user context.
|
||||
$contextlist = \tool_policy\privacy\provider::get_contexts_for_userid($this->user->id);
|
||||
$this->assertEquals(1, $contextlist->count());
|
||||
}
|
||||
|
||||
public function test_export_agreements() {
|
||||
global $CFG;
|
||||
|
||||
$otheruser = $this->getDataGenerator()->create_user();
|
||||
$otherusercontext = \context_user::instance($otheruser->id);
|
||||
|
||||
// Create policies and agree to them as manager.
|
||||
$this->setUser($this->manager);
|
||||
$managercontext = \context_user::instance($this->manager->id);
|
||||
$systemcontext = \context_system::instance();
|
||||
$agreementsubcontext = [
|
||||
get_string('privacyandpolicies', 'admin'),
|
||||
get_string('useracceptances', 'tool_policy')
|
||||
];
|
||||
$versionsubcontext = [
|
||||
get_string('policydocuments', 'tool_policy')
|
||||
];
|
||||
$CFG->sitepolicyhandler = 'tool_policy';
|
||||
$policy1 = $this->add_policy();
|
||||
api::make_current($policy1->get('id'));
|
||||
$policy2 = $this->add_policy();
|
||||
api::make_current($policy2->get('id'));
|
||||
api::accept_policies([$policy1->get('id'), $policy2->get('id')]);
|
||||
|
||||
// Agree to the policies for oneself.
|
||||
$this->setUser($this->user);
|
||||
$usercontext = \context_user::instance($this->user->id);
|
||||
api::accept_policies([$policy1->get('id'), $policy2->get('id')]);
|
||||
|
||||
// Request export for this user.
|
||||
$contextlist = provider::get_contexts_for_userid($this->user->id);
|
||||
$this->assertCount(1, $contextlist);
|
||||
$this->assertEquals([$usercontext->id], $contextlist->get_contextids());
|
||||
|
||||
$approvedcontextlist = new approved_contextlist($this->user, 'tool_policy', [$usercontext->id]);
|
||||
provider::export_user_data($approvedcontextlist);
|
||||
|
||||
// User can not see manager's agreements but can see his own.
|
||||
$writer = writer::with_context($managercontext);
|
||||
$this->assertFalse($writer->has_any_data());
|
||||
|
||||
$writer = writer::with_context($usercontext);
|
||||
$this->assertTrue($writer->has_any_data());
|
||||
|
||||
// Test policy 1.
|
||||
$subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy1->to_record())]);
|
||||
$datauser = $writer->get_data($subcontext);
|
||||
$this->assertEquals($policy1->get('name'), $datauser->name);
|
||||
$this->assertEquals($this->user->id, $datauser->agreedby);
|
||||
$this->assertEquals(strip_tags($policy1->get('summary')), strip_tags($datauser->summary));
|
||||
$this->assertEquals(strip_tags($policy1->get('content')), strip_tags($datauser->content));
|
||||
|
||||
// Test policy 2.
|
||||
$subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy2->to_record())]);
|
||||
$datauser = $writer->get_data($subcontext);
|
||||
$this->assertEquals($policy2->get('name'), $datauser->name);
|
||||
$this->assertEquals($this->user->id, $datauser->agreedby);
|
||||
$this->assertEquals(strip_tags($policy2->get('summary')), strip_tags($datauser->summary));
|
||||
$this->assertEquals(strip_tags($policy2->get('content')), strip_tags($datauser->content));
|
||||
}
|
||||
|
||||
public function test_export_agreements_for_other() {
|
||||
global $CFG;
|
||||
|
||||
$managercontext = \context_user::instance($this->manager->id);
|
||||
$systemcontext = \context_system::instance();
|
||||
$usercontext = \context_user::instance($this->user->id);
|
||||
|
||||
// Create policies and agree to them as manager.
|
||||
$this->setUser($this->manager);
|
||||
$agreementsubcontext = [
|
||||
get_string('privacyandpolicies', 'admin'),
|
||||
get_string('useracceptances', 'tool_policy')
|
||||
];
|
||||
$versionsubcontext = [
|
||||
get_string('policydocuments', 'tool_policy')
|
||||
];
|
||||
$CFG->sitepolicyhandler = 'tool_policy';
|
||||
$policy1 = $this->add_policy();
|
||||
api::make_current($policy1->get('id'));
|
||||
$policy2 = $this->add_policy();
|
||||
api::make_current($policy2->get('id'));
|
||||
api::accept_policies([$policy1->get('id'), $policy2->get('id')]);
|
||||
|
||||
// Agree to the other user's policies.
|
||||
api::accept_policies([$policy1->get('id'), $policy2->get('id')], $this->user->id, 'My note');
|
||||
|
||||
// Request export for the manager.
|
||||
$contextlist = provider::get_contexts_for_userid($this->manager->id);
|
||||
$this->assertCount(3, $contextlist);
|
||||
$this->assertEquals(
|
||||
[$managercontext->id, $usercontext->id, $systemcontext->id],
|
||||
$contextlist->get_contextids(),
|
||||
'',
|
||||
0.0,
|
||||
1,
|
||||
true
|
||||
);
|
||||
|
||||
$approvedcontextlist = new approved_contextlist($this->user, 'tool_policy', [$usercontext->id]);
|
||||
provider::export_user_data($approvedcontextlist);
|
||||
|
||||
// The user context has data.
|
||||
$writer = writer::with_context($usercontext);
|
||||
$this->assertTrue($writer->has_any_data());
|
||||
|
||||
// Test policy 1.
|
||||
$writer = writer::with_context($usercontext);
|
||||
$subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy1->to_record())]);
|
||||
$datauser = $writer->get_data($subcontext);
|
||||
$this->assertEquals($policy1->get('name'), $datauser->name);
|
||||
$this->assertEquals($this->manager->id, $datauser->agreedby);
|
||||
$this->assertEquals(strip_tags($policy1->get('summary')), strip_tags($datauser->summary));
|
||||
$this->assertEquals(strip_tags($policy1->get('content')), strip_tags($datauser->content));
|
||||
|
||||
// Test policy 2.
|
||||
$subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy2->to_record())]);
|
||||
$datauser = $writer->get_data($subcontext);
|
||||
$this->assertEquals($policy2->get('name'), $datauser->name);
|
||||
$this->assertEquals($this->manager->id, $datauser->agreedby);
|
||||
$this->assertEquals(strip_tags($policy2->get('summary')), strip_tags($datauser->summary));
|
||||
$this->assertEquals(strip_tags($policy2->get('content')), strip_tags($datauser->content));
|
||||
}
|
||||
|
||||
public function test_export_created_policies() {
|
||||
global $CFG;
|
||||
|
||||
// Create policies and agree to them as manager.
|
||||
$this->setUser($this->manager);
|
||||
$managercontext = \context_user::instance($this->manager->id);
|
||||
$systemcontext = \context_system::instance();
|
||||
$agreementsubcontext = [
|
||||
get_string('privacyandpolicies', 'admin'),
|
||||
get_string('useracceptances', 'tool_policy')
|
||||
];
|
||||
$versionsubcontext = [
|
||||
get_string('policydocuments', 'tool_policy')
|
||||
];
|
||||
$CFG->sitepolicyhandler = 'tool_policy';
|
||||
$policy1 = $this->add_policy();
|
||||
api::make_current($policy1->get('id'));
|
||||
$policy2 = $this->add_policy();
|
||||
api::make_current($policy2->get('id'));
|
||||
api::accept_policies([$policy1->get('id'), $policy2->get('id')]);
|
||||
|
||||
// Agree to the policies for oneself.
|
||||
$contextlist = provider::get_contexts_for_userid($this->manager->id);
|
||||
$this->assertCount(2, $contextlist);
|
||||
$this->assertEquals([$managercontext->id, $systemcontext->id], $contextlist->get_contextids(), '', 0.0, 1, true);
|
||||
|
||||
$approvedcontextlist = new approved_contextlist($this->manager, 'tool_policy', $contextlist->get_contextids());
|
||||
provider::export_user_data($approvedcontextlist);
|
||||
|
||||
// User has agreed to policies.
|
||||
$writer = writer::with_context($managercontext);
|
||||
$this->assertTrue($writer->has_any_data());
|
||||
|
||||
// Test policy 1.
|
||||
$subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy1->to_record())]);
|
||||
$datauser = $writer->get_data($subcontext);
|
||||
$this->assertEquals($policy1->get('name'), $datauser->name);
|
||||
$this->assertEquals($this->manager->id, $datauser->agreedby);
|
||||
$this->assertEquals(strip_tags($policy1->get('summary')), strip_tags($datauser->summary));
|
||||
$this->assertEquals(strip_tags($policy1->get('content')), strip_tags($datauser->content));
|
||||
|
||||
// Test policy 2.
|
||||
$subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy2->to_record())]);
|
||||
$datauser = $writer->get_data($subcontext);
|
||||
$this->assertEquals($policy2->get('name'), $datauser->name);
|
||||
$this->assertEquals($this->manager->id, $datauser->agreedby);
|
||||
$this->assertEquals(strip_tags($policy2->get('summary')), strip_tags($datauser->summary));
|
||||
$this->assertEquals(strip_tags($policy2->get('content')), strip_tags($datauser->content));
|
||||
|
||||
// User can see policy documents.
|
||||
$writer = writer::with_context($systemcontext);
|
||||
$this->assertTrue($writer->has_any_data());
|
||||
|
||||
$subcontext = array_merge($versionsubcontext, [get_string('policynamedversion', 'tool_policy', $policy1->to_record())]);
|
||||
$dataversion = $writer->get_data($subcontext);
|
||||
$this->assertEquals($policy1->get('name'), $dataversion->name);
|
||||
$this->assertEquals(get_string('yes'), $dataversion->createdbyme);
|
||||
|
||||
$subcontext = array_merge($versionsubcontext, [get_string('policynamedversion', 'tool_policy', $policy2->to_record())]);
|
||||
$dataversion = $writer->get_data($subcontext);
|
||||
$this->assertEquals($policy2->get('name'), $dataversion->name);
|
||||
$this->assertEquals(get_string('yes'), $dataversion->createdbyme);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that creates a new policy for testing
|
||||
*
|
||||
* @param array $params
|
||||
* @return policy_version
|
||||
*/
|
||||
protected function add_policy($params = []) {
|
||||
static $counter = 0;
|
||||
$counter++;
|
||||
|
||||
$defaults = [
|
||||
'name' => 'Policy '.$counter,
|
||||
'summary_editor' => ['text' => "P$counter summary", 'format' => FORMAT_HTML, 'itemid' => 0],
|
||||
'content_editor' => ['text' => "P$counter content", 'format' => FORMAT_HTML, 'itemid' => 0],
|
||||
];
|
||||
|
||||
$params = (array)$params + $defaults;
|
||||
$formdata = \tool_policy\api::form_policydoc_data(new policy_version(0));
|
||||
foreach ($params as $key => $value) {
|
||||
$formdata->$key = $value;
|
||||
}
|
||||
return api::form_policydoc_add($formdata);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0"?>
|
||||
<libraries>
|
||||
<library>
|
||||
<location>amd/src/jquery-eu-cookie-law-popup.js</location>
|
||||
<name>jQuery EU Cookie Law popups</name>
|
||||
<license>MIT</license>
|
||||
<version>1.0.1</version>
|
||||
<licenseversion></licenseversion>
|
||||
</library>
|
||||
</libraries>
|
||||
@@ -0,0 +1,54 @@
|
||||
<?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_pagelayout('standard');
|
||||
$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();
|
||||
@@ -0,0 +1,29 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Plugin version and other meta-data are defined here.
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 David Mudrák <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017111311;
|
||||
$plugin->requires = 2017111302; // Moodle 3.4.2 (Build: 20180319) and upwards.
|
||||
$plugin->component = 'tool_policy';
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* View current document policy version.
|
||||
*
|
||||
* Script parameters:
|
||||
* versionid=<int> Policy version id, defaults to the current one.
|
||||
* policyid=<int> Policy document id, defaults to the one matching the version.
|
||||
* returnurl=<local url> URL to continue to after reading the policy document.
|
||||
* behalfid=<id> The user id to view the policy version as (such as child's id).
|
||||
* manage=<bool> View the policy as a part of the management UI (managedocs.php).
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Sara Arjona ([email protected])
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
use tool_policy\api;
|
||||
use tool_policy\output\page_viewdoc;
|
||||
|
||||
// Do not check for the site policies in require_login() to avoid the redirect loop.
|
||||
define('NO_SITEPOLICY_CHECK', true);
|
||||
|
||||
// @codingStandardsIgnoreLine See the {@link page_viewdoc} for the access control checks.
|
||||
require(__DIR__.'/../../../config.php');
|
||||
|
||||
$versionid = optional_param('versionid', null, PARAM_INT);
|
||||
$policyid = $versionid ? optional_param('policyid', null, PARAM_INT) : required_param('policyid', PARAM_INT);
|
||||
$returnurl = optional_param('returnurl', null, PARAM_LOCALURL);
|
||||
$behalfid = optional_param('behalfid', null, PARAM_INT);
|
||||
$manage = optional_param('manage', false, PARAM_BOOL);
|
||||
$numpolicy = optional_param('numpolicy', null, PARAM_INT);
|
||||
$totalpolicies = optional_param('totalpolicies', null, PARAM_INT);
|
||||
|
||||
$PAGE->set_context(context_system::instance());
|
||||
$PAGE->set_pagelayout('standard');
|
||||
|
||||
$viewpage = new page_viewdoc($policyid, $versionid, $returnurl, $behalfid, $manage, $numpolicy, $totalpolicies);
|
||||
|
||||
$output = $PAGE->get_renderer('tool_policy');
|
||||
|
||||
echo $output->header();
|
||||
echo $output->render($viewpage);
|
||||
echo $output->footer();
|
||||
@@ -0,0 +1,43 @@
|
||||
<?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 all document policy with a version, one under another.
|
||||
*
|
||||
* Script parameters:
|
||||
* -
|
||||
*
|
||||
* @package tool_policy
|
||||
* @copyright 2018 Sara Arjona ([email protected])
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
use tool_policy\api;
|
||||
use tool_policy\output\page_viewalldoc;
|
||||
|
||||
// Do not check for the site policies in require_login() to avoid the redirect loop.
|
||||
define('NO_SITEPOLICY_CHECK', true);
|
||||
|
||||
// @codingStandardsIgnoreLine See the {@link page_viewalldoc} for the access control checks.
|
||||
require(__DIR__.'/../../../config.php');
|
||||
|
||||
$viewallpage = new page_viewalldoc();
|
||||
|
||||
$output = $PAGE->get_renderer('tool_policy');
|
||||
|
||||
echo $output->header();
|
||||
echo $output->render($viewallpage);
|
||||
echo $output->footer();
|
||||