MDL-62309 tool_policy: Update user acceptances reports

This adds support for optional policies to the user acceptance reports.
Distinguished are "Pending" acceptances (we did not hear yet) from
"Declined" (user did not agree). The status workflow updated to support
new transitions: pending -> declined and declined -> accepted.
This commit is contained in:
David Mudrák
2018-10-22 08:49:36 +02:00
parent 56390aa246
commit 4a742e4f94
14 changed files with 468 additions and 279 deletions
+5 -7
View File
@@ -39,6 +39,10 @@ $context = context_system::instance();
$PAGE->set_context($context);
$PAGE->set_url(new moodle_url('/admin/tool/policy/accept.php'));
if (!in_array($action, ['accept', 'decline', 'revoke'])) {
throw new moodle_exception('invalidaccessparameter');
}
if ($returnurl) {
$returnurl = new moodle_url($returnurl);
} else if (count($userids) == 1) {
@@ -59,14 +63,8 @@ if ($form->is_cancelled()) {
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);
echo $output->heading(get_string('statusformtitle'.$action, 'tool_policy'));
$form->display();
echo $output->footer();
+1 -1
View File
@@ -1 +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.currentTrigger=null,i.prototype.triggers={SINGLE:"a[data-action=acceptmodal]",BULK:"input[data-action=acceptmodal]"},i.prototype.init=function(){a(this.triggers.SINGLE).on("click",function(b){b.preventDefault(),this.currentTrigger=a(b.currentTarget);var c=a(b.currentTarget).attr("href"),d=c.slice(c.indexOf("?")+1);this.showFormModal(d)}.bind(this)),a(this.triggers.BULK).on("click",function(c){c.preventDefault(),this.currentTrigger=a(c.currentTarget);var d=a(c.currentTarget).closest("form");if(d.find('input[type=checkbox][name="userids[]"]:checked').length){var f=d.serialize();this.showFormModal(f)}else b.get_strings(this.stringKeys).done(function(a){e.alert("",a[2],a[3])})}.bind(this))},i.prototype.showFormModal=function(a){for(var d,f=a.split("&"),g=0;g<f.length;g++){var h=f[g].split("=");"action"==h[0]&&(d=h[1])}b.get_strings(this.stringKeys).done(function(b){var e,f;"revoke"==d?(e=b[4],f=b[5]):(e=b[0],f=b[1]),c.create({type:c.types.SAVE_CANCEL,title:e,body:""}).done(function(b){this.modal=b,this.setupFormModal(a,f)}.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(),this.currentTrigger.focus()},{getInstance:function(a){return new i(a)}}});
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.currentTrigger=null,i.prototype.triggers={SINGLE:"a[data-action=acceptmodal]",BULK:"input[data-action=acceptmodal]"},i.prototype.init=function(){a(this.triggers.SINGLE).on("click",function(b){b.preventDefault(),this.currentTrigger=a(b.currentTarget);var c=a(b.currentTarget).attr("href"),d=c.slice(c.indexOf("?")+1);this.showFormModal(d)}.bind(this)),a(this.triggers.BULK).on("click",function(c){c.preventDefault(),this.currentTrigger=a(c.currentTarget);var d=a(c.currentTarget).closest("form");if(d.find('input[type=checkbox][name="userids[]"]:checked').length){var f=d.serialize();this.showFormModal(f)}else b.get_strings([{key:"notice"},{key:"selectusersforconsent",component:"tool_policy"},{key:"ok"}]).then(function(a){e.alert(a[0],a[1],a[2])}).fail(e.exception)}.bind(this))},i.prototype.showFormModal=function(a){for(var d,f=a.split("&"),g=0;g<f.length;g++){var h=f[g].split("=");"action"==h[0]&&(d=h[1])}b.get_strings([{key:"statusformtitleaccept",component:"tool_policy"},{key:"iagreetothepolicy",component:"tool_policy"},{key:"statusformtitlerevoke",component:"tool_policy"},{key:"irevokethepolicy",component:"tool_policy"},{key:"statusformtitledecline",component:"tool_policy"},{key:"declinethepolicy",component:"tool_policy"}]).then(function(b){var e,f;return"accept"==d?(e=b[0],f=b[1]):"revoke"==d?(e=b[2],f=b[3]):"decline"==d&&(e=b[4],f=b[5]),c.create({type:c.types.SAVE_CANCEL,title:e,body:""}).done(function(b){this.modal=b,this.setupFormModal(a,f)}.bind(this))}.bind(this))["catch"](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(),this.currentTrigger.focus()},{getInstance:function(a){return new i(a)}}});
+25 -40
View File
@@ -52,36 +52,6 @@ define(['jquery', 'core/str', 'core/modal_factory', 'core/modal_events', 'core/n
*/
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'
}
];
/**
* @var {object} currentTrigger The triggered HTML jQuery object
* @private
@@ -121,9 +91,14 @@ define(['jquery', 'core/str', 'core/modal_factory', 'core/modal_events', 'core/n
var formData = form.serialize();
this.showFormModal(formData);
} else {
Str.get_strings(this.stringKeys).done(function(strings) {
Notification.alert('', strings[2], strings[3]);
});
Str.get_strings([
{key: 'notice'},
{key: 'selectusersforconsent', component: 'tool_policy'},
{key: 'ok'}
]).then(function(strings) {
Notification.alert(strings[0], strings[1], strings[2]);
return;
}).fail(Notification.exception);
}
}.bind(this));
};
@@ -143,18 +118,28 @@ define(['jquery', 'core/str', 'core/modal_factory', 'core/modal_events', 'core/n
}
}
// Fetch the title string.
Str.get_strings(this.stringKeys).done(function(strings) {
Str.get_strings([
{key: 'statusformtitleaccept', component: 'tool_policy'},
{key: 'iagreetothepolicy', component: 'tool_policy'},
{key: 'statusformtitlerevoke', component: 'tool_policy'},
{key: 'irevokethepolicy', component: 'tool_policy'},
{key: 'statusformtitledecline', component: 'tool_policy'},
{key: 'declinethepolicy', component: 'tool_policy'}
]).then(function(strings) {
var title;
var saveText;
if (action == 'revoke') {
title = strings[4];
saveText = strings[5];
} else {
if (action == 'accept') {
title = strings[0];
saveText = strings[1];
} else if (action == 'revoke') {
title = strings[2];
saveText = strings[3];
} else if (action == 'decline') {
title = strings[4];
saveText = strings[5];
}
// Create the modal.
ModalFactory.create({
return ModalFactory.create({
type: ModalFactory.types.SAVE_CANCEL,
title: title,
body: ''
@@ -163,7 +148,7 @@ define(['jquery', 'core/str', 'core/modal_factory', 'core/modal_events', 'core/n
this.setupFormModal(formData, saveText);
}.bind(this));
}.bind(this))
.fail(Notification.exception);
.catch(Notification.exception);
};
/**
+24 -26
View File
@@ -177,21 +177,23 @@ class acceptances_table extends \table_sql {
$filterstatus = $this->acceptancesfilter->get_status_filter();
if ($filterstatus == 1) {
$this->sql->from .= " $join AND a{$v}.status=1";
} else if ($filterstatus == 2) {
$this->sql->from .= " $join AND a{$v}.status=0";
} 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->from .= " LEFT JOIN {user} m ON m.id = a{$v}.usermodified AND m.id <> u.id AND a{$v}.status IS NOT NULL";
$this->sql->params['versionid' . $v] = $v;
if ($filterstatus === 0) {
$this->sql->where .= " AND (a{$v}.status IS NULL OR a{$v}.status = 0)";
$this->sql->where .= " AND a{$v}.status IS NULL";
}
$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('status' . $v, get_string('response', 'tool_policy'));
$this->add_column_header('timemodified', get_string('responseon', 'tool_policy'));
$this->add_column_header('usermodified' . $v, get_string('responseby', 'tool_policy'));
$this->add_column_header('note', get_string('acceptancenote', 'tool_policy'), false);
}
@@ -207,11 +209,13 @@ class acceptances_table extends \table_sql {
$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 if ($filterstatus == 2) {
$this->sql->from .= " {$join} AND a{$v}.status=0";
} else {
$this->sql->from .= " LEFT {$join}";
}
$this->sql->params['versionid' . $v] = $v;
$this->add_column_header('status' . $v, $versionname, true, 'mdl-align');
$this->add_column_header('status' . $v, $versionname);
$statusall[] = "COALESCE(a{$v}.status, 0)";
}
$this->sql->fields .= ",".join('+', $statusall)." AS statusall";
@@ -219,7 +223,7 @@ class acceptances_table extends \table_sql {
if ($filterstatus === 0) {
$statussql = [];
foreach ($this->versionids as $v => $versionname) {
$statussql[] = "a{$v}.status IS NULL OR a{$v}.status = 0";
$statussql[] = "a{$v}.status IS NULL";
}
$this->sql->where .= " AND (u.policyagreed = 0 OR ".join(" OR ", $statussql).")";
}
@@ -420,7 +424,7 @@ class acceptances_table extends \table_sql {
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}]",
echo \html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'versionids[]',
'value' => $versionid]);
}
}
@@ -433,6 +437,7 @@ class acceptances_table extends \table_sql {
public function wrap_html_finish() {
global $PAGE;
if ($this->canagreeany) {
echo \html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'action', 'value' => 'accept']);
echo \html_writer::empty_tag('input', ['type' => 'submit', 'data-action' => 'acceptmodal',
'value' => get_string('consentbulk', 'tool_policy'), 'class' => 'btn btn-primary m-t-1']);
$PAGE->requires->js_call_amd('tool_policy/acceptmodal', 'getInstance', [\context_system::instance()->id]);
@@ -529,10 +534,15 @@ class acceptances_table extends \table_sql {
$onbehalf = false;
$versions = $versionid ? [$versionid => $this->versionids[$versionid]] : $this->versionids; // List of versions.
$accepted = []; // List of versionids that user has accepted.
$declined = [];
foreach ($versions as $v => $name) {
if (!empty($row->{'status' . $v})) {
$accepted[] = $v;
if ($row->{'status' . $v} !== null) {
if (empty($row->{'status' . $v})) {
$declined[] = $v;
} else {
$accepted[] = $v;
}
$agreedby = $row->{'usermodified' . $v};
if ($agreedby && $agreedby != $row->id) {
$onbehalf = true;
@@ -540,25 +550,13 @@ class acceptances_table extends \table_sql {
}
}
if ($versionid) {
$str = new \lang_string($accepted ? 'yes' : 'no');
} else {
$str = new \lang_string('acceptancecount', 'tool_policy', (object)[
'agreedcount' => count($accepted),
'policiescount' => count($versions)
]);
}
$ua = new user_agreement($row->id, $accepted, $declined, $this->get_return_url(), $versions, $onbehalf, $row->canaccept);
if ($this->is_downloading()) {
return $str->out();
return $ua->export_for_download();
} 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;
return $this->output->render($ua);
}
}
+2 -2
View File
@@ -760,14 +760,14 @@ class api {
if (isset($acceptances[$policy->currentversion->id])) {
$policy->currentversion->acceptance = $acceptances[$policy->currentversion->id];
} else {
$policy->currentversion->acceptance = 0;
$policy->currentversion->acceptance = null;
}
$versions[] = $policy->currentversion;
}
foreach ($policy->archivedversions as $version) {
if ($version->audience != policy_version::AUDIENCE_GUESTS
&& static::can_user_view_policy_version($version, $userid)) {
$version->acceptance = isset($acceptances[$version->id]) ? $acceptances[$version->id] : 0;
$version->acceptance = isset($acceptances[$version->id]) ? $acceptances[$version->id] : null;
$versions[] = $version;
}
}
@@ -44,7 +44,7 @@ class accept_policy extends \moodleform {
* Defines the form fields.
*/
public function definition() {
global $PAGE;
global $PAGE, $USER;
$mform = $this->_form;
if (empty($this->_customdata['userids']) || !is_array($this->_customdata['userids'])) {
@@ -53,10 +53,10 @@ class accept_policy extends \moodleform {
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');
$action = $this->_customdata['action'];
$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);
$usernames = $this->validate_and_get_users($userids, $action);
$versionnames = $this->validate_and_get_versions($versionids);
foreach ($usernames as $userid => $name) {
@@ -78,22 +78,36 @@ class accept_policy extends \moodleform {
get_string('policydochdrpolicy', 'tool_policy');
$mform->addElement('static', 'policy', $policyacceptancelabel, join(', ', $versionnames));
if ($revoke) {
if ($action === 'revoke') {
$mform->addElement('static', 'ack', '', get_string('revokeacknowledgement', 'tool_policy'));
$mform->addElement('hidden', 'action', 'revoke');
$mform->setType('action', PARAM_ALPHA);
} else {
} else if ($action === 'accept') {
$mform->addElement('static', 'ack', '', get_string('acceptanceacknowledgement', 'tool_policy'));
$mform->addElement('hidden', 'action', 'accept');
} else if ($action === 'decline') {
$mform->addElement('static', 'ack', '', get_string('declineacknowledgement', 'tool_policy'));
$mform->addElement('hidden', 'action', 'decline');
} else {
throw new \moodle_exception('invalidaccessparameter');
}
$mform->setType('action', PARAM_ALPHA);
if (count($usernames) == 1 && isset($usernames[$USER->id])) {
// No need to display the acknowledgement if the users are giving/revoking acceptance on their own.
$mform->removeElement('ack');
}
$mform->addElement('textarea', 'note', get_string('acceptancenote', 'tool_policy'));
$mform->setType('note', PARAM_NOTAGS);
if (!empty($this->_customdata['showbuttons'])) {
if ($revoke) {
if ($action === 'revoke') {
$this->add_action_buttons(true, get_string('irevokethepolicy', 'tool_policy'));
} else {
} else if ($action === 'accept') {
$this->add_action_buttons(true, get_string('iagreetothepolicy', 'tool_policy'));
} else if ($action === 'decline') {
$this->add_action_buttons(true, get_string('declinethepolicy', 'tool_policy'));
}
}
@@ -104,11 +118,12 @@ class accept_policy extends \moodleform {
* Validate userids and return usernames
*
* @param array $userids
* @param boolean $revoke True if policies will be revoked; false when policies will be accepted.
* @param string $action accept|decline|revoke
* @return array (userid=>username)
*/
protected function validate_and_get_users($userids, $revoke = false) {
protected function validate_and_get_users($userids, $action) {
global $DB;
$usernames = [];
list($sql, $params) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
$params['usercontextlevel'] = CONTEXT_USER;
@@ -126,10 +141,12 @@ class accept_policy extends \moodleform {
throw new \moodle_exception('noguest');
}
\context_helper::preload_from_record($user);
if ($revoke) {
if ($action === 'revoke') {
api::can_revoke_policies($userid, true);
} else {
} else if ($action === 'accept') {
api::can_accept_policies($userid, true);
} else if ($action === 'decline') {
api::can_decline_policies($userid, true);
}
$usernames[$userid] = fullname($user);
}
@@ -166,14 +183,15 @@ class accept_policy extends \moodleform {
*/
public function process() {
if ($data = $this->get_data()) {
$revoke = (!empty($data->action) && $data->action == 'revoke');
foreach ($data->userids as $userid) {
if ($revoke) {
if ($data->action === 'revoke') {
foreach ($data->versionids as $versionid) {
\tool_policy\api::revoke_acceptance($versionid, $userid, $data->note);
}
} else {
} else if ($data->action === 'accept') {
\tool_policy\api::accept_policies($data->versionids, $userid, $data->note);
} else if ($data->action === 'decline') {
\tool_policy\api::decline_policies($data->versionids, $userid, $data->note);
}
}
}
@@ -98,12 +98,17 @@ class acceptances implements renderable, templatable {
'returnurl' => $returnurl->out(false),
]))->out(false);
if (!empty($version->acceptance->status)) {
if ($version->acceptance !== null) {
$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 ($version->acceptance->status == 1) {
$version->agreement = new user_agreement($this->userid, [$version->id], [], $returnurl,
[$version->id => $version->name], $onbehalf);
} else {
$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');
@@ -114,7 +119,7 @@ class acceptances implements renderable, templatable {
}
$version->note = format_text($acceptance->note);
} else if ($version->iscurrent) {
$version->agreement = new user_agreement($this->userid, [], $returnurl, [$version->id => $version->name]);
$version->agreement = new user_agreement($this->userid, [], [], $returnurl, [$version->id => $version->name]);
}
if (isset($version->agreement)) {
$version->agreement = $version->agreement->export_for_template($output);
@@ -94,11 +94,9 @@ class acceptances_filter implements \templatable, \renderable {
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];
$value = (int)$parts[2];
break;
case self::FILTER_ROLE:
$value = (int)$parts[2];
@@ -408,8 +406,9 @@ class acceptances_filter implements \templatable, \renderable {
// Status.
$statuses = [
self::FILTER_STATUS.':2' => get_string('filterstatusdeclined', 'tool_policy'),
self::FILTER_STATUS.':1' => get_string('filterstatusyes', 'tool_policy'),
self::FILTER_STATUS.':0' => get_string('filterstatusno', 'tool_policy'),
self::FILTER_STATUS.':0' => get_string('filterstatuspending', 'tool_policy'),
];
if (($currentstatus = $this->get_status_filter()) !== null) {
$selectedoptions[] = $key = self::FILTER_STATUS . ':' . $currentstatus;
@@ -56,6 +56,9 @@ class user_agreement implements \templatable, \renderable {
/** @var array */
protected $accepted;
/** @var array */
protected $declined;
/** @var bool */
protected $canaccept;
@@ -67,24 +70,34 @@ class user_agreement implements \templatable, \renderable {
*
* @param int $userid
* @param array $accepted list of ids of accepted versions
* @param array $declined list of ids of declined 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 $canaccept does the current user have permission to accept/decline 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,
public function __construct($userid, array $accepted, array $declined, moodle_url $pageurl, $versions, $onbehalf = false,
$canaccept = null, $canrevoke = null) {
// Make sure that all ids in $accepted and $declined are present in $versions.
if (array_diff(array_merge($accepted, $declined), array_keys($versions))) {
throw new \coding_exception('Policy version ids mismatch');
}
$this->userid = $userid;
$this->onbehalf = $onbehalf;
$this->pageurl = $pageurl;
$this->versions = $versions;
$this->accepted = $accepted;
$this->declined = $declined;
$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) {
if (count($this->accepted) > 0 && $canrevoke === null) {
$this->canrevoke = \tool_policy\api::can_revoke_policies($this->userid);
}
}
@@ -96,35 +109,237 @@ class user_agreement implements \templatable, \renderable {
* @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,
$data = (object)[
'statusicon' => '',
'statustext' => '',
'statuslink' => '',
'actions' => [],
];
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;
if (count($this->versions) == 1) {
// We represent one particular policy's agreement status.
$versionname = reset($this->versions);
$versionid = key($this->versions);
$actionaccept = (object)[
'text' => get_string('useracceptanceactionaccept', 'tool_policy'),
'title' => get_string('useracceptanceactionacceptone', 'tool_policy', $versionname),
'data' => 'acceptmodal',
'url' => (new \moodle_url('/admin/tool/policy/accept.php', [
'userids[]' => $this->userid,
'versionids[]' => $versionid,
'action' => 'accept',
'returnurl' => $this->pageurl->out_as_local_url(false),
]))->out(false),
];
$actionrevoke = (object)[
'text' => get_string('useracceptanceactionrevoke', 'tool_policy'),
'title' => get_string('useracceptanceactionrevokeone', 'tool_policy', $versionname),
'data' => 'acceptmodal',
'url' => (new \moodle_url('/admin/tool/policy/accept.php', [
'userids[]' => $this->userid,
'versionids[]' => $versionid,
'action' => 'revoke',
'returnurl' => $this->pageurl->out_as_local_url(false),
]))->out(false),
];
$actiondecline = (object)[
'text' => get_string('useracceptanceactiondecline', 'tool_policy'),
'title' => get_string('useracceptanceactiondeclineone', 'tool_policy', $versionname),
'data' => 'acceptmodal',
'url' => (new \moodle_url('/admin/tool/policy/accept.php', [
'userids[]' => $this->userid,
'versionids[]' => $versionid,
'action' => 'decline',
'returnurl' => $this->pageurl->out_as_local_url(false),
]))->out(false),
];
if ($this->accepted) {
$data->statusicon = 'agreed';
if ($this->onbehalf) {
$data->statustext = get_string('acceptancestatusacceptedbehalf', 'tool_policy');
} else {
$data->statustext = get_string('acceptancestatusaccepted', 'tool_policy');
}
if ($this->canrevoke) {
$data->actions[] = $actionrevoke;
}
} else if ($this->declined) {
$data->statusicon = 'declined';
if ($this->onbehalf) {
$data->statustext = get_string('acceptancestatusdeclinedbehalf', 'tool_policy');
} else {
$data->statustext = get_string('acceptancestatusdeclined', 'tool_policy');
}
if ($this->canaccept) {
$data->actions[] = $actionaccept;
}
} else {
$data->statusicon = 'pending';
$data->statustext = get_string('acceptancestatuspending', 'tool_policy');
if ($this->canaccept) {
$data->actions[] = $actionaccept;
$data->actions[] = $actiondecline;
}
}
$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;
} else if (count($this->versions) > 1) {
// We represent the summary status for multiple policies.
$data->actions[] = (object)[
'text' => get_string('useracceptanceactiondetails', 'tool_policy'),
'url' => (new \moodle_url('/admin/tool/policy/user.php', [
'userid' => $this->userid,
'returnurl' => $this->pageurl->out_as_local_url(false),
]))->out(false),
];
// Prepare the action link to accept all pending policies.
$accepturl = new \moodle_url('/admin/tool/policy/accept.php', [
'userids[]' => $this->userid,
'action' => 'accept',
'returnurl' => $this->pageurl->out_as_local_url(false),
]);
foreach (array_diff(array_keys($this->versions), $this->accepted, $this->declined) as $ix => $versionid) {
$accepturl->param('versionids['.$ix.']', $versionid);
}
$actionaccept = (object)[
'text' => get_string('useracceptanceactionaccept', 'tool_policy'),
'title' => get_string('useracceptanceactionacceptpending', 'tool_policy'),
'data' => 'acceptmodal',
'url' => $accepturl->out(false),
];
// Prepare the action link to revoke all agreed policies.
$revokeurl = new \moodle_url('/admin/tool/policy/accept.php', [
'userids[]' => $this->userid,
'action' => 'revoke',
'returnurl' => $this->pageurl->out_as_local_url(false),
]);
foreach ($this->accepted as $ix => $versionid) {
$revokeurl->param('versionids['.$ix.']', $versionid);
}
$actionrevoke = (object)[
'text' => get_string('useracceptanceactionrevoke', 'tool_policy'),
'title' => get_string('useracceptanceactionrevokeall', 'tool_policy'),
'data' => 'acceptmodal',
'url' => $revokeurl->out(false),
];
// Prepare the action link to decline all pending policies.
$declineurl = new \moodle_url('/admin/tool/policy/accept.php', [
'userids[]' => $this->userid,
'action' => 'decline',
'returnurl' => $this->pageurl->out_as_local_url(false),
]);
foreach (array_diff(array_keys($this->versions), $this->accepted, $this->declined) as $ix => $versionid) {
$declineurl->param('versionids['.$ix.']', $versionid);
}
$actiondecline = (object)[
'text' => get_string('useracceptanceactiondecline', 'tool_policy'),
'title' => get_string('useracceptanceactiondeclinepending', 'tool_policy'),
'data' => 'acceptmodal',
'url' => $declineurl->out(false),
];
$countversions = count($this->versions);
$countaccepted = count($this->accepted);
$countdeclined = count($this->declined);
if ($countaccepted == $countversions) {
// All policies accepted.
$data->statusicon = 'agreed';
$data->statustext = get_string('acceptancestatusaccepted', 'tool_policy');
if ($this->canrevoke) {
$data->actions[] = $actionrevoke;
}
} else if ($countdeclined == $countversions) {
// All policies declined.
$data->statusicon = 'declined';
$data->statustext = get_string('acceptancestatusdeclined', 'tool_policy');
} else if ($countaccepted + $countdeclined == $countversions) {
// All policies responded, only some of them accepted.
$data->statusicon = 'partial';
$data->statustext = get_string('acceptancestatuspartial', 'tool_policy');
if ($this->accepted && $this->canrevoke) {
$data->actions[] = $actionrevoke;
}
} else {
// Some policies are pending.
$data->statusicon = 'pending';
$data->statustext = get_string('acceptancestatuspending', 'tool_policy');
if ($this->canaccept) {
$data->actions[] = $actionaccept;
$data->actions[] = $actiondecline;
}
}
$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;
}
}
/**
* Describe the status with a plain text for downloading purposes.
*
* @return string
*/
public function export_for_download() {
if (count($this->versions) == 1) {
if ($this->accepted) {
if ($this->onbehalf) {
return get_string('acceptancestatusacceptedbehalf', 'tool_policy');
} else {
return get_string('acceptancestatusaccepted', 'tool_policy');
}
} else if ($this->declined) {
if ($this->onbehalf) {
return get_string('acceptancestatusdeclinedbehalf', 'tool_policy');
} else {
return get_string('acceptancestatusdeclined', 'tool_policy');
}
} else {
return get_string('acceptancestatuspending', 'tool_policy');
}
} else if (count($this->versions) > 1) {
if (count($this->accepted) == count($this->versions)) {
return get_string('acceptancestatusaccepted', 'tool_policy');
} else if (count($this->declined) == count($this->versions)) {
return get_string('acceptancestatusdeclined', 'tool_policy');
} else if (count($this->accepted) > 0 || count($this->declined) > 0) {
return get_string('acceptancestatuspartial', 'tool_policy');
} else {
return get_string('acceptancestatuspending', 'tool_policy');
}
}
}
}
+29 -19
View File
@@ -26,38 +26,32 @@
defined('MOODLE_INTERNAL') || die();
$string['acceptanceacknowledgement'] = 'I acknowledge that I have received a request to give consent on behalf of the above user(s).';
$string['acceptancecount'] = '{$a->agreedcount} of {$a->policiescount}';
$string['acceptancenote'] = 'Remarks';
$string['acceptancepolicies'] = 'Policies';
$string['acceptancessavedsucessfully'] = 'The agreements have been saved successfully.';
$string['acceptancestatusaccepted'] = 'Accepted';
$string['acceptancestatusacceptedbehalf'] = 'Accepted on user\'s behalf';
$string['acceptancestatusdeclined'] = 'Declined';
$string['acceptancestatusdeclinedbehalf'] = 'Declined on user\'s behalf';
$string['acceptancestatusoverall'] = 'Overall';
$string['acceptancestatuspartial'] = 'Partially accepted';
$string['acceptancestatuspending'] = 'Pending';
$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['backtoprevious'] = 'Go back to previous page';
$string['backtotop'] = 'Back to top';
$string['cachedef_policy_optional'] = 'Cache of the optional/compulsory flag for policy versions';
$string['consentbulk'] = 'Consent';
$string['consentdetails'] = 'Give consent on behalf of user(s)';
$string['consentpagetitle'] = 'Consent';
$string['contactdpo'] = 'For any questions about the policies please contact the privacy officer.';
$string['dataproc'] = 'Personal data processing';
$string['declineacknowledgement'] = 'I acknowledge that I have received a request to decline consent on behalf of the above user(s).';
$string['declinethepolicy'] = 'Decline user consent';
$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';
@@ -72,14 +66,15 @@ $string['filterrevision'] = 'Version: {$a}';
$string['filterrevisionstatus'] = 'Version: {$a->name} ({$a->status})';
$string['filterrole'] = 'Role: {$a}';
$string['filters'] = 'Filters';
$string['filterstatusno'] = 'Status: Not agreed';
$string['filterstatusdeclined'] = 'Status: Declined';
$string['filterstatuspending'] = 'Status: Pending';
$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['idontagree'] = 'No thanks, I do not agree';
$string['idontagree'] = 'No thanks, I decline {$a}';
$string['iagreetothepolicy'] = 'Give consent';
$string['inactivate'] = 'Set status to "Inactive"';
$string['inactivating'] = 'Inactivating a policy';
@@ -93,7 +88,7 @@ $string['minorchangeinfo'] = 'A minor change does not alter the meaning of the p
$string['managepolicies'] = 'Manage policies';
$string['movedown'] = 'Move down';
$string['moveup'] = 'Move up';
$string['mustagreetocontinue'] = 'Before continuing you must agree to all these policies.';
$string['mustagreetocontinue'] = 'Before continuing you need to acknowledge all these policies.';
$string['newpolicy'] = 'New policy';
$string['newversion'] = 'New version';
$string['noactivepolicies'] = 'There are no policies with an active version.';
@@ -165,18 +160,33 @@ $string['privacy:metadata:versions:contentformat'] = 'The format of the content
$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['response'] = 'Response';
$string['responseby'] = 'Respondent';
$string['responseon'] = 'Date';
$string['revokeacknowledgement'] = 'I acknowledge that I have received a request to withdraw consent on behalf of the above 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['selectusersforconsent'] = 'Select users to give consent on behalf of.';
$string['settodraft'] = 'Create a new draft';
$string['status'] = 'Policy status';
$string['statusformtitleaccept'] = 'Accepting policy';
$string['statusformtitledecline'] = 'Declining policy';
$string['statusformtitlerevoke'] = 'Withdrawing policy';
$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['useracceptanceactionaccept'] = 'Accept';
$string['useracceptanceactionacceptone'] = 'Accept {$a}';
$string['useracceptanceactionacceptpending'] = 'Accept pending policies';
$string['useracceptanceactiondecline'] = 'Decline';
$string['useracceptanceactiondeclineone'] = 'Decline {$a}';
$string['useracceptanceactiondeclinepending'] = 'Decline pending policies';
$string['useracceptanceactiondetails'] = 'Details';
$string['useracceptanceactionrevoke'] = 'Withdraw';
$string['useracceptanceactionrevokeall'] = 'Withdraw accepted policies';
$string['useracceptanceactionrevokeone'] = 'Withdraw acceptance of {$a}';
$string['useracceptancecount'] = '{$a->agreedcount} of {$a->userscount} ({$a->percent}%)';
$string['useracceptancecountna'] = 'N/A';
$string['useracceptances'] = 'User agreements';
@@ -80,10 +80,10 @@
<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>
<th>{{#str}} response, tool_policy {{/str}}</th>
<th>{{#str}} responseon, tool_policy {{/str}}</th>
{{#hasonbehalfagreements}}
<th>{{#str}} agreedby, tool_policy {{/str}}</th>
<th>{{#str}} responseby, tool_policy {{/str}}</th>
<th>{{#str}} acceptancenote, tool_policy {{/str}}</th>
{{/hasonbehalfagreements}}
<th></th>
@@ -26,67 +26,30 @@
-
Context variables required for this template:
* status
* onbehalf
* canaccept
* acceptlink
* statusicon
* statustext
* actions
- url
- data
- text
- title
Example context (json):
{
"status": false,
"onbehalf": false,
"canaccept": true,
"canrevoke": true,
"acceptlink": "/",
"revokelink": "/",
"singleversion": false,
"versionname": ""
"statusicon": "accepted",
"statustext": "Accepted",
"actions": {
"url": "/admin/tool/policy/accept.php?param=value",
"data": "acceptmodal",
"text": "Withdraw",
"title": "Withdraw acceptance of Site policy"
}
}
}}
{{#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}}
<span class="tool_policy-user_agreement-icon">{{#pix}} {{statusicon}}, tool_policy{{/pix}}</span>
<span class="tool_policy-user_agreement-status">{{statustext}}</span>
<span class="tool_policy-user_agreement-actions">
{{#actions}}
<a href="{{url}}" title="{{title}}" data-action="{{data}}"><small>{{text}}</small></a>
{{/actions}}
</span>
@@ -41,9 +41,9 @@ Feature: Viewing acceptances reports and accepting on behalf of other users
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"
And "Accepted" "text" should exist in the "User One" "table_row"
And "Accepted" "text" should exist in the "Max Manager" "table_row"
And "Pending" "text" 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"
@@ -57,17 +57,17 @@ Feature: Viewing acceptances reports and accepting on behalf of other users
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"
And I click on "Accept This site policy" "link" in the "User One" "table_row"
Then I should see "Accepting policy"
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 the above user(s)."
And I set the field "Remarks" to "Consent received from a parent"
And I press "Give consent"
And "Consent given on behalf of user" "icon" should exist in the "User One" "table_row"
And "Accepted on user's behalf" "text" 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"
And "Pending" "text" should exist in the "User Two" "table_row"
@javascript
Scenario: Agree on behalf of another user as a manager, single policy, javascript on
@@ -83,17 +83,17 @@ Feature: Viewing acceptances reports and accepting on behalf of other users
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"
And I click on "Accept This site policy" "link" in the "User One" "table_row"
Then I should see "Give consent"
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 the above user(s)."
And I set the field "Remarks" to "Consent received from a parent"
And I press "Give consent"
And "Consent given on behalf of user" "icon" should exist in the "User One" "table_row"
And "Accepted on user's behalf" "text" 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"
And "Pending" "text" 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"
@@ -119,19 +119,19 @@ Feature: Viewing acceptances reports and accepting on behalf of other users
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 "Accepted" "text" should exist in the "User One" "table_row"
And "Pending" "text" should not exist in the "User One" "table_row"
And "Accepted" "text" should exist in the "Max Manager" "table_row"
And "Pending" "text" should exist in the "User Two" "table_row"
And "Accepted" "text" should not exist in the "User Two" "table_row"
And I click on "Details" "link" in the "User One" "table_row"
And "Accepted" "text" should exist in the "This site policy" "table_row"
And "Accepted" "text" 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"
And I click on "Details" "link" in the "User Two" "table_row"
And "Pending" "text" should exist in the "This site policy" "table_row"
And "Pending" "text" 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"
@@ -150,20 +150,20 @@ Feature: Viewing acceptances reports and accepting on behalf of other users
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"
And I click on "Accept This site policy" "link" in the "User One" "table_row"
Then I should see "Accepting policy"
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 the above user(s)."
And I set the field "Remarks" to "Consent received from a parent"
And I press "Give consent"
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 "Accepted on user's behalf" "text" should exist in the "User One" "table_row"
And "Pending" "text" should exist in the "User One" "table_row"
And I click on "Details" "link" in the "User One" "table_row"
And "Accepted on user's behalf" "text" 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"
And "Pending" "text" should exist in the "This privacy policy" "table_row"
@javascript
Scenario: Agree on behalf of another user as a manager, multiple policies, javascript on
@@ -183,20 +183,20 @@ Feature: Viewing acceptances reports and accepting on behalf of other users
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"
And I click on "Accept This site policy" "link" in the "User One" "table_row"
Then I should see "Give consent"
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 the above user(s)."
And I set the field "Remarks" to "Consent received from a parent"
And I press "Give consent"
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 "Accepted on user's behalf" "text" should exist in the "User One" "table_row"
And "Pending" "text" should exist in the "User One" "table_row"
And I click on "Details" "link" in the "User One" "table_row"
And "Accepted on user's behalf" "text" 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"
And "Pending" "text" 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"
@@ -207,14 +207,14 @@ Feature: Viewing acceptances reports and accepting on behalf of other users
# 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"
And "Accepted" "text" 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
Scenario: Policies and agreements profile link visible also for users who can access on behalf of others
Given I log in as "admin"
And I set the following system permissions of "Manager" role:
| capability | permission |
@@ -248,18 +248,18 @@ Feature: Viewing acceptances reports and accepting on behalf of other users
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"
And I click on "Accept This site policy" "link" in the "User One" "table_row"
Then I should see "Accepting policy"
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 the above user(s)."
And I set the field "Remarks" to "Consent received from a parent"
And I press "Give consent"
And "Consent given on behalf of user" "icon" should exist in the "User One" "table_row"
And "Accepted on user's behalf" "text" 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"
And "Pending" "text" should exist in the "User Two" "table_row"
@javascript
Scenario: Bulk agree on behalf of another users as a manager, multiple policies, javascript on
@@ -281,16 +281,14 @@ Feature: Viewing acceptances reports and accepting on behalf of other users
And I navigate to "Users > Privacy and policies > User agreements" in site administration
And I click on "Select" "checkbox" in the "User One" "table_row"
And I press "Consent"
And I should see "Give consent on behalf of user(s)"
And I should see "Accepting policy"
And I should see "One"
And I press "Cancel"
And I should not see "Give consent on behalf of user(s)"
And I should not see "Accepting policy"
And I click on "Select" "checkbox" in the "User Two" "table_row"
And I press "Consent"
And I should see "Give consent on behalf of user(s)"
And I should see "Accepting policy"
And I should see "User One, User Two"
When I press "Give consent"
Then "Consent given on behalf of user" "icon" should exist in the "User One" "table_row"
And I should see "2 of 2" in the "User One" "table_row"
And "Consent given on behalf of user" "icon" should exist in the "User Two" "table_row"
And I should see "2 of 2" in the "User Two" "table_row"
Then "Accepted on user's behalf" "text" should exist in the "User One" "table_row"
And "Accepted on user's behalf" "text" should exist in the "User Two" "table_row"
+23 -23
View File
@@ -113,7 +113,7 @@ Feature: User must accept policy managed by this plugin when logging in and sign
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 "Accepted" "text" should exist in the "This site policy" "table_row"
And I log out
Scenario: Accept policy on sign up, multiple policies
@@ -172,8 +172,8 @@ Feature: User must accept policy managed by this plugin when logging in and sign
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 "Accepted" "text" should exist in the "This site policy" "table_row"
And "Accepted" "text" should exist in the "This privacy policy" "table_row"
And I should not see "This guests policy"
And I log out
@@ -225,7 +225,7 @@ Feature: User must accept policy managed by this plugin when logging in and sign
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 "Accepted" "text" should exist in the "This site policy" "table_row"
And I log out
Scenario: Accept policy on sign up, do not accept all policies
@@ -252,12 +252,12 @@ Feature: User must accept policy managed by this plugin when logging in and sign
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."
And I should see "Before continuing you need to acknowledge 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."
And I should see "Before continuing you need to acknowledge all these policies."
Scenario: Accept policy on login, do not accept all policies
Given the following config values are set as admin:
@@ -284,12 +284,12 @@ Feature: User must accept policy managed by this plugin when logging in and sign
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."
And I should see "Before continuing you need to acknowledge 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."
And I should see "Before continuing you need to acknowledge 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"
@@ -319,7 +319,7 @@ Feature: User must accept policy managed by this plugin when logging in and sign
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."
And I should not see "Before continuing you need to acknowledge 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"
@@ -661,7 +661,7 @@ Feature: User must accept policy managed by this plugin when logging in and sign
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 "Accepted" "text" should exist in the "This site policy" "table_row"
And I log out
Scenario: Accepting policies on sign up, multiple policies with different style of giving ageement.
@@ -730,10 +730,10 @@ Feature: User must accept policy managed by this plugin when logging in and sign
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 "Privacy policy" "table_row"
And "Agreed" "icon" should exist in the "Cookies policy" "table_row"
And "Agreed" "icon" should exist in the "Terms of Service" "table_row"
And "Agreed" "icon" should exist in the "Digital maturity declaration" "table_row"
And "Accepted" "text" should exist in the "Privacy policy" "table_row"
And "Accepted" "text" should exist in the "Cookies policy" "table_row"
And "Accepted" "text" should exist in the "Terms of Service" "table_row"
And "Accepted" "text" should exist in the "Digital maturity declaration" "table_row"
And I log out
Scenario: Accepting policies on login, multiple policies with different style of giving ageement.
@@ -788,10 +788,10 @@ Feature: User must accept policy managed by this plugin when logging in and sign
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 "Privacy policy" "table_row"
And "Agreed" "icon" should exist in the "Cookies policy" "table_row"
And "Agreed" "icon" should exist in the "Terms of Service" "table_row"
And "Agreed" "icon" should exist in the "Digital maturity declaration" "table_row"
And "Accepted" "text" should exist in the "Privacy policy" "table_row"
And "Accepted" "text" should exist in the "Cookies policy" "table_row"
And "Accepted" "text" should exist in the "Terms of Service" "table_row"
And "Accepted" "text" should exist in the "Digital maturity declaration" "table_row"
And I log out
Scenario: Accepting policies on login, all and loggedin policies to be accepted on their own page.
@@ -822,9 +822,9 @@ Feature: User must accept policy managed by this plugin when logging in and sign
And I press "I agree to the Terms of Service"
And I follow "Profile" in the user menu
And I follow "Policies and agreements"
And "Agreed" "icon" should exist in the "Privacy policy" "table_row"
And "Agreed" "icon" should exist in the "Terms of Service" "table_row"
And "Agreed" "icon" should exist in the "Digital maturity declaration" "table_row"
And "Accepted" "text" should exist in the "Privacy policy" "table_row"
And "Accepted" "text" should exist in the "Terms of Service" "table_row"
And "Accepted" "text" should exist in the "Digital maturity declaration" "table_row"
And "Cookies policy" "table_row" should not exist
And I log out
@@ -872,8 +872,8 @@ Feature: User must accept policy managed by this plugin when logging in and sign
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 "Digital maturity declaration" "table_row"
And "Agreed" "icon" should exist in the "Cookies policy" "table_row"
And "Accepted" "text" should exist in the "Digital maturity declaration" "table_row"
And "Accepted" "text" should exist in the "Cookies policy" "table_row"
And "Privacy policy" "table_row" should not exist
And "Terms of Service" "table_row" should not exist
And I log out