Skip to content

Commit

Permalink
Merge branch 'MDL-63013-master-prioritypolicy' of git://github.com/mu…
Browse files Browse the repository at this point in the history
…drd8mz/moodle
  • Loading branch information
stronk7 committed Sep 26, 2018
2 parents 201d21e + 7fb0e8a commit 659d9fe
Show file tree
Hide file tree
Showing 14 changed files with 387 additions and 30 deletions.
2 changes: 2 additions & 0 deletions admin/tool/policy/classes/form/policydoc.php
Expand Up @@ -89,6 +89,8 @@ public function definition() {
api::policy_content_field_options());
$mform->addRule('content_editor', null, 'required', null, 'client');

$mform->addElement('selectyesno', 'agreementstyle', get_string('policypriorityagreement', 'tool_policy'));

if (!$formdata->id || $formdata->status == policy_version::STATUS_DRAFT) {
// Creating a new version or editing a draft/archived version.
$mform->addElement('hidden', 'minorchange');
Expand Down
84 changes: 63 additions & 21 deletions admin/tool/policy/classes/output/page_agreedocs.php
Expand Up @@ -51,6 +51,9 @@ 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 List of policy version ids that were displayed to the user to agree with. */
protected $listdocs = null;

/** @var array $agreedocs List of policy identifiers which the user has agreed using the form. */
protected $agreedocs = null;

Expand All @@ -75,22 +78,20 @@ class page_agreedocs implements renderable, templatable {
/**
* Prepare the page for rendering.
*
* @param array $agreedocs Array with the policy identifiers which the user has agreed using the form.
* @param array $listdocs List of policy version ids that were displayed to the user to agree with.
* @param array $agreedocs List of policy version ids that the user actually agreed with.
* @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) {
public function __construct(array $listdocs, array $agreedocs = [], $behalfid = 0, $action = null) {
global $USER;
$realuser = manager::get_realuser();

$this->listdocs = $listdocs;
$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);
Expand Down Expand Up @@ -124,12 +125,14 @@ protected function accept_and_revoke_policies() {
// 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);
if (in_array($policy->id, $this->listdocs)) {
if (in_array($policy->id, $this->agreedocs)) {
// Save policy version doc to accept it.
$acceptversionids[] = $policy->id;
} else {
// If the policy was displayed but not agreed, revoke the eventually given acceptance.
api::revoke_acceptance($policy->id, $this->behalfid);
}
}
}
// Accept all policy docs saved in $acceptversionids.
Expand Down Expand Up @@ -158,15 +161,26 @@ protected function accept_and_revoke_policies() {
} else {
// New user.
if (!empty($this->action) && confirm_sesskey()) {
// The form has been sent.
$currentpolicyversionids = [];
$presignupcache = \cache::make('core', 'presignup');
$acceptances = $presignupcache->get('tool_policy_policyversionidsagreed');
if (!$acceptances) {
$acceptances = [];
}
foreach ($this->policies as $policy) {
$currentpolicyversionids[] = $policy->id;
if (in_array($policy->id, $this->listdocs)) {
if (in_array($policy->id, $this->agreedocs)) {
$acceptances[] = $policy->id;
} else {
$acceptances = array_values(array_diff($acceptances, [$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);
$this->signupuserpolicyagreed = empty(array_diff($currentpolicyversionids, $acceptances));
$presignupcache->set('tool_policy_userpolicyagreed', $this->signupuserpolicyagreed);
$presignupcache->set('tool_policy_policyversionidsagreed', $acceptances);
} 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);
Expand All @@ -190,18 +204,41 @@ protected function accept_and_revoke_policies() {
* @param moodle_url $returnurl URL to return after shown the policy docs.
*/
protected function redirect_to_policies($userid, $returnurl = null) {

// Make a list of all policies that the user has not accepted yet.
$allpolicies = $this->policies;

if ($this->isexistinguser) {
$acceptances = api::get_user_acceptances($userid);
foreach ($allpolicies as $policy) {
foreach ($allpolicies as $ix => $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)]);
unset($allpolicies[$ix]);
}
}
} else {
$presignupcache = \cache::make('core', 'presignup');
$acceptances = $presignupcache->get('tool_policy_policyversionidsagreed');
if ($acceptances) {
foreach ($allpolicies as $ix => $policy) {
if (in_array($policy->id, $acceptances)) {
unset($allpolicies[$ix]);
}
}
}
}

if (!empty($allpolicies)) {
// Check if some of the to-be-accepted policies should be agreed on their own page.
foreach ($allpolicies as $policy) {
if ($policy->agreementstyle == policy_version::AGREEMENTSTYLE_OWNPAGE) {
if (empty($returnurl)) {
$returnurl = (new moodle_url('/admin/tool/policy/index.php'))->out_as_local_url(false);
}
$urlparams = ['versionid' => $policy->id, 'returnurl' => $returnurl];
redirect(new moodle_url('/admin/tool/policy/view.php', $urlparams));
}
}

$currentpolicyversionids = [];
foreach ($allpolicies as $policy) {
$currentpolicyversionids[] = $policy->id;
Expand Down Expand Up @@ -232,6 +269,8 @@ protected function redirect_to_policies($userid, $returnurl = null) {
];
redirect(new moodle_url('/admin/tool/policy/view.php', $urlparams));
}
} else {
$this->redirect_to_previous_url();
}
}

Expand Down Expand Up @@ -401,7 +440,10 @@ public function export_for_template(renderer_base $output) {
}
}

$data->policies = array_values($this->policies);
// Filter out policies already shown on their own page, keep just policies to be shown here on the consent page.
$data->policies = array_values(array_filter($this->policies, function ($policy) {
return $policy->agreementstyle == policy_version::AGREEMENTSTYLE_CONSENTPAGE;
}));

// If viewing docs in behalf of other user, get his/her full name and profile link.
if (!empty($this->behalfuser)) {
Expand Down
13 changes: 13 additions & 0 deletions admin/tool/policy/classes/output/page_viewdoc.php
Expand Up @@ -151,6 +151,7 @@ protected function prepare_global_page_access() {
* @return stdClass
*/
public function export_for_template(renderer_base $output) {
global $USER;

$data = (object) [
'pluginbaseurl' => (new moodle_url('/admin/tool/policy'))->out(false),
Expand All @@ -163,6 +164,18 @@ public function export_for_template(renderer_base $output) {
$data->editurl = (new moodle_url('/admin/tool/policy/editpolicydoc.php', $paramsurl))->out(false);
}

if ($this->policy->agreementstyle == policy_version::AGREEMENTSTYLE_OWNPAGE) {
if (!api::is_user_version_accepted($USER->id, $this->policy->id)) {
unset($data->returnurl);
$data->accepturl = (new moodle_url('/admin/tool/policy/index.php', [
'listdoc[]' => $this->policy->id,
'agreedoc[]' => $this->policy->id,
'submit' => 'accept',
'sesskey' => sesskey(),
]))->out(false);
}
}

$data->policy = clone($this->policy);

return $data;
Expand Down
14 changes: 14 additions & 0 deletions admin/tool/policy/classes/policy_version.php
Expand Up @@ -69,6 +69,12 @@ class policy_version extends persistent {
/** @var int Policy version has been archived. */
const STATUS_ARCHIVED = 2;

/** @var int Policy to be accepted together with others on the consent page. */
const AGREEMENTSTYLE_CONSENTPAGE = 0;

/** @var int Policy to be accepted on its own page before reaching the consent page. */
const AGREEMENTSTYLE_OWNPAGE = 1;

/**
* Return the definition of the properties of this model.
*
Expand Down Expand Up @@ -106,6 +112,14 @@ protected static function define_properties() {
'policyid' => [
'type' => PARAM_INT,
],
'agreementstyle' => [
'type' => PARAM_INT,
'choices' => [
self::AGREEMENTSTYLE_CONSENTPAGE,
self::AGREEMENTSTYLE_OWNPAGE,
],
'default' => self::AGREEMENTSTYLE_CONSENTPAGE,
],
'revision' => [
'type' => PARAM_TEXT,
'default' => '',
Expand Down
3 changes: 2 additions & 1 deletion admin/tool/policy/db/install.xml
@@ -1,5 +1,5 @@
<?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."
<XMLDB PATH="admin/tool/policy/db" VERSION="20180829" 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"
>
Expand All @@ -26,6 +26,7 @@
<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="agreementstyle" TYPE="int" LENGTH="3" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="How this agreement should flow: 0 - on the consent page, 1 - on a separate page before reaching the consent page."/>
<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"/>
Expand Down
53 changes: 53 additions & 0 deletions admin/tool/policy/db/upgrade.php
@@ -0,0 +1,53 @@
<?php
// This file is part of Moodle - https://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 upgrade steps are defined here.
*
* @package tool_policy
* @category upgrade
* @copyright 2018 David Mudrák <david@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

defined('MOODLE_INTERNAL') || die();

/**
* Execute the plugin upgrade steps from the given old version.
*
* @param int $oldversion
* @return bool
*/
function xmldb_tool_policy_upgrade($oldversion) {
global $DB;

$dbman = $DB->get_manager();

if ($oldversion < 2018082900) {
// Add field agreementstyle to the table tool_policy_versions.
$table = new xmldb_table('tool_policy_versions');
$field = new xmldb_field('agreementstyle', XMLDB_TYPE_INTEGER, '3', null, XMLDB_NOTNULL, null, '0', 'policyid');

if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}

upgrade_plugin_savepoint(true, 2018082900, 'tool', 'policy');
}

return true;
}

12 changes: 9 additions & 3 deletions admin/tool/policy/index.php
Expand Up @@ -18,7 +18,8 @@
* Show a user the policy documents to be agreed to.
*
* Script parameters:
* agreedoc=<array> Policy version id which have been accepted by the user.
* listdoc=<array> List of policy version ids that were displayed to the user to accept.
* agreedoc=<array> List of policy version ids that were accepted by the user.
* behalfid=<id> The user id to view the policy version as (such as child's id).
*
* @package tool_policy
Expand All @@ -37,14 +38,19 @@

$submit = optional_param('submit', null, PARAM_NOTAGS);
$cancel = optional_param('cancel', null, PARAM_NOTAGS);
$agreedocs = optional_param_array('agreedoc', null, PARAM_INT);
$listdocs = optional_param_array('listdoc', [], PARAM_INT);
$agreedocs = optional_param_array('agreedoc', [], 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 (array_diff($agreedocs, $listdocs)) {
throw new moodle_exception('invalidaccessparameter');
}

if (isloggedin() && !isguestuser()) {
// Existing user.
$haspermissionagreedocs = api::can_accept_policies($behalfid);
Expand All @@ -61,7 +67,7 @@
if (!$behalfid && \core\session\manager::is_loggedinas()) {
$behalfid = $USER->id;
}
$outputpage = new \tool_policy\output\page_agreedocs($agreedocs, $behalfid, $submit);
$outputpage = new \tool_policy\output\page_agreedocs($listdocs, $agreedocs, $behalfid, $submit);
}

$output = $PAGE->get_renderer('tool_policy');
Expand Down
1 change: 1 addition & 0 deletions admin/tool/policy/lang/en/tool_policy.php
Expand Up @@ -129,6 +129,7 @@
$string['policydoctype99'] = 'Other policy';
$string['policydocuments'] = 'Policy documents';
$string['policynamedversion'] = 'Policy {$a->name} (version {$a->revision} - {$a->id})';
$string['policypriorityagreement'] = 'Show policy before showing other policies';
$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';
Expand Down
10 changes: 7 additions & 3 deletions admin/tool/policy/lib.php
Expand Up @@ -85,9 +85,13 @@ function tool_policy_before_standard_html_head() {
&& empty($USER->policyagreed)
&& (isguestuser() || !isloggedin())) {
$output = $PAGE->get_renderer('tool_policy');
$page = new \tool_policy\output\guestconsent();

$message = $output->render($page);
try {
$page = new \tool_policy\output\guestconsent();
$message = $output->render($page);
} catch (dml_read_exception $e) {
// During upgrades, the new plugin code with new SQL could be in place but the DB not upgraded yet.
$message = null;
}
}

return $message;
Expand Down
1 change: 1 addition & 0 deletions admin/tool/policy/templates/page_agreedocs.mustache
Expand Up @@ -92,6 +92,7 @@
<div class="agreedoc-form m-t-1">
<div class="agreedoc-checkbox">
<label>
<input value="{{id}}" name="listdoc[]" type="hidden" >
<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>
Expand Down
6 changes: 5 additions & 1 deletion admin/tool/policy/templates/page_viewdoc.mustache
Expand Up @@ -38,7 +38,8 @@
"content": "Policy <em>content</em>"
},
"returnurl": "#",
"editurl": "#"
"editurl": "#",
"accepturl": "#"
}
}}

Expand Down Expand Up @@ -88,6 +89,9 @@
{{#editurl}}
<a role="button" href="{{editurl}}" class="btn">{{#str}} edit {{/str}}</a>
{{/editurl}}
{{#accepturl}}
<a role="button" href="{{accepturl}}" class="btn btn-primary">{{#str}} iagree, tool_policy, {{{policy.name}}} {{/str}}</a>
{{/accepturl}}

<div class="pull-right">
<a href="#top">
Expand Down
2 changes: 2 additions & 0 deletions admin/tool/policy/tests/behat/behat_tool_policy.php
Expand Up @@ -51,6 +51,7 @@ class behat_tool_policy extends behat_base {
* - Type: 0 - site policy, 1 - privacy policy, 2 - third party policy, 99 - other.
* - Summary: Policy summary text.
* - Content: Policy full text.
* - Agreement style (agreementstyle): 0 - On the consent page, 1 - On its own page
*
* @param TableNode $data
*/
Expand All @@ -69,6 +70,7 @@ public function the_following_policies_exist(TableNode $data) {
'type',
'content',
'summary',
'agreementstyle',
];

// Associative array "policy identifier" => id in the database .
Expand Down

0 comments on commit 659d9fe

Please sign in to comment.