--- /dev/null
+/**
+ *
+ * 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;
+});
+
+});
--- /dev/null
+// 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 (sara@moodle.com)
+ * @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;
+ });
+ }
+ }).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();
+ }
+ };
+});
--- /dev/null
+<?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 (sara@moodle.com)
+ * @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 (sara@moodle.com)
+ * @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');
+ }
+}
--- /dev/null
+<?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 <sara@moodle.com>
+ * @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 <sara@moodle.com>
+ * @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;
+ }
+}
--- /dev/null
+<?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 <sara@moodle.com>
+ * @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_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 <sara@moodle.com>
+ * @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 = [];
+
+ /**
+ * 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;
+
+ $this->agreedocs = $agreedocs;
+ if (empty($this->agreedocs)) {
+ $this->agreedocs = [];
+ }
+
+ $this->behalfid = $behalfid;
+ $this->action = $action;
+
+ if (!empty($this->behalfid) && $USER->id != $this->behalfid) {
+ $this->behalfuser = core_user::get_user($this->behalfid, '*');
+ // If behalf user doesn't exist, behalfid parameter will be ignored.
+ if ($this->behalfuser === false) {
+ $this->behalfid = 0;
+ }
+ }
+
+ $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 (!empty($USER->id)) {
+ // 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)) {
+ // There are no policies to agree to. Update the policyagreed value to avoid display empty consent page.
+ $currentuser = (!empty($this->behalfuser)) ? $this->behalfuser : $USER;
+ // Check for updating when the user policyagreed is false.
+ if (!$currentuser->policyagreed) {
+ api::update_policyagreed($currentuser);
+ }
+ } else if (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 array $userid User identifier who wants to access to the consent page.
+ * @param url $returnurl URL to return after shown the policy docs.
+ */
+ protected function redirect_to_policies($userid, $returnurl = null) {
+ global $USER;
+
+ $acceptances = api::get_user_acceptances($userid);
+ $allpolicies = $this->policies;
+ if (!empty($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 $SESSION->wantsurl if defined or to $CFG->wwwroot if not.
+ */
+ protected function redirect_to_previous_url() {
+ global $SESSION, $CFG;
+
+ if (!empty($SESSION->wantsurl)) {
+ $returnurl = $SESSION->wantsurl;
+ unset($SESSION->wantsurl);
+ } else {
+ $returnurl = $CFG->wwwroot.'/';
+ }
+
+ redirect($returnurl);
+ }
+
+ /**
+ * Sets up the global $PAGE and performs the access checks.
+ *
+ * @param int $userid
+ */
+ protected function prepare_global_page_access($userid) {
+ global $PAGE, $SESSION, $SITE, $USER;
+
+ // Guest users or not logged users (but the users during the signup process) are not allowed to access to this page.
+ $newsignupuser = !empty($SESSION->wantsurl) && strpos($SESSION->wantsurl, 'login/signup.php') !== false;
+ if (isguestuser() || (empty($USER->id) && !$newsignupuser)) {
+ $this->redirect_to_previous_url();
+ }
+
+ // Check for correct user capabilities.
+ if (!empty($USER->id)) {
+ // For existing users, it's needed to check if they have the capability for accepting policies.
+ if (empty($this->behalfid) || $this->behalfid == $USER->id) {
+ require_capability('tool/policy:accept', context_system::instance());
+ } else {
+ $usercontext = \context_user::instance($this->behalfid);
+ require_capability('tool/policy:acceptbehalf', $usercontext);
+ }
+ } else {
+ // For new users, the behalfid parameter is ignored.
+ if ($this->behalfid != $USER->id) {
+ redirect(new moodle_url('/admin/tool/policy/index.php'));
+ }
+ }
+
+ // If the current user has the $USER->policyagreed = 1 or $userpolicyagreed = 1
+ // and $SESSION->wantsurl is defined, redirect to the return page.
+ $hasagreedsignupuser = empty($USER->id) && $this->signupuserpolicyagreed;
+ $hasagreedloggeduser = $USER->id == $userid && !empty($USER->policyagreed);
+ if (!is_siteadmin() && ($hasagreedsignupuser || ($hasagreedloggeduser && !empty($SESSION->wantsurl)))) {
+ $this->redirect_to_previous_url();
+ }
+
+ $myparams = [];
+ if (!empty($USER->id) && !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_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'));
+ }
+
+ /**
+ * Prepare user acceptances.
+ *
+ * @param int $userid
+ */
+ protected function prepare_user_acceptances($userid) {
+ global $USER;
+
+ // Get all the policy version acceptances for this user.
+ $acceptances = api::get_user_acceptances($userid);
+ $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 (!empty($userid)) {
+ // Existing user.
+ $versionagreed = false;
+ $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 (!empty($USER->id) && !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);
+ }
+
+ return $data;
+ }
+
+}
--- /dev/null
+<?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 <sara@moodle.com>
+ * @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 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 <sara@moodle.com>
+ * @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;
+
+ $this->behalfid = $behalfid;
+ if (!empty($this->behalfid) && $USER->id != $this->behalfid) {
+ $this->behalfuser = core_user::get_user($this->behalfid, '*');
+ // If behalf user doesn't exist, behalfid parameter will be ignored.
+ if ($this->behalfuser === false) {
+ $this->behalfid = 0;
+ }
+ }
+
+ if (!empty($USER->id)) {
+ // For existing users, it's needed to check if they have the capability for accepting policies.
+ if (empty($this->behalfid) || $this->behalfid == $USER->id) {
+ $this->haspermissionagreedocs = has_capability('tool/policy:accept', context_system::instance());
+ } else {
+ $usercontext = \context_user::instance($this->behalfid);
+ $this->haspermissionagreedocs = has_capability('tool/policy:acceptbehalf', $usercontext);
+ }
+ }
+
+ $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;
+ }
+}
--- /dev/null
+<?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 <sara@moodle.com>
+ * @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 <sara@moodle.com>
+ * @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_policies();
+ $this->prepare_global_page_access();
+ }
+
+ /**
+ * Loads the policy versions to display on the page.
+ *
+ */
+ protected function prepare_policies() {
+ global $USER;
+
+ if (isguestuser() || empty($USER->id)) {
+ $audience = policy_version::AUDIENCE_GUESTS;
+ } else {
+ $audience = policy_version::AUDIENCE_LOGGEDIN;
+ }
+ $this->policies = api::list_current_versions($audience);
+ }
+
+ /**
+ * 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);
+
+ return $data;
+ }
+}
--- /dev/null
+<?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 <sara@moodle.com>
+ * @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 <sara@moodle.com>
+ * @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)) {
+ // TODO Make this nicer error message.
+ throw new \moodle_exception('err_no_active_version', '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,
+ 'editurl' => ($this->manage && $this->policy->status != policy_version::STATUS_ARCHIVED) ? (new moodle_url('/admin/tool/policy/editpolicydoc.php',
+ ['policyid' => $this->policy->policyid, 'versionid' => $this->policy->id]))->out(false) : null,
+ 'numpolicy' => $this->numpolicy ? : null,
+ 'totalpolicies' => $this->totalpolicies ? : null,
+ ];
+
+ $data->policy = clone($this->policy);
+
+ return $data;
+ }
+}
--- /dev/null
+<?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 (sara@moodle.com)
+ * @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 (sara@moodle.com)
+ * @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,
+ ],
+ ],
+ ];
+ }
+}
--- /dev/null
+<?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 <sara@moodle.com>
+ * @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 <sara@moodle.com>
+ * @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);
+ }
+ }
+}
--- /dev/null
+<?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 (sara@moodle.com)
+ * @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',
+ ],
+];
--- /dev/null
+<?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 (sara@moodle.com)
+ * @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');
+
+$action = optional_param('action', null, PARAM_ALPHA);
+$agreedocs = optional_param_array('agreedoc', null, PARAM_INT);
+$behalfid = optional_param('userid', null, PARAM_INT);
+
+$PAGE->set_context(context_system::instance());
+$PAGE->set_url('/admin/tool/policy/index.php');
+$PAGE->set_popup_notification_allowed(false);
+
+$haspermissionagreedocs = false;
+if (!empty($USER->id)) {
+ // Existing user.
+ if (empty($behalfid) || $behalfid == $USER->id) {
+ $haspermissionagreedocs = has_capability('tool/policy:accept', context_system::instance());
+ } else {
+ $usercontext = \context_user::instance($behalfid);
+ $haspermissionagreedocs = has_capability('tool/policy:acceptbehalf', $usercontext);
+ }
+} else {
+ // New user.
+ $haspermissionagreedocs = true;
+}
+
+if (!$haspermissionagreedocs) {
+ $outputpage = new \tool_policy\output\page_nopermission($behalfid);
+} else {
+ $outputpage = new \tool_policy\output\page_agreedocs($agreedocs, $behalfid, $action);
+}
+
+$output = $PAGE->get_renderer('tool_policy');
+
+echo $output->header();
+echo $output->render($outputpage);
+echo $output->footer();
--- /dev/null
+/* eupopup styles */
+.eupopup-body li {
+ display: inline;
+}
+
+.eupopup-body li:before {
+ content: ", ";
+}
+
+.eupopup-body li:first-child:before {
+ content: "";
+}
+
+.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-closebutton:hover,
+.eupopup-closebutton:active {
+ text-decoration: none;
+}
+
+.eupopup-head {
+ font-size: 1.2em;
+ font-weight: bold;
+ padding: 7px;
+}
+
+.eupopup-body ul {
+ padding: 0;
+ margin: 0 0 3px;
+}
+
+.eupopup-buttons {
+ padding: 7px 0 5px 0;
+}
+
+.eupopup-button_1 {
+ font-weight: bold;
+ font-size: 14px;
+}
+
+.eupopup-button_2 {
+ display: none;
+}
+
+.eupopup-button {
+ margin: 0 10px;
+ color: #f6a21d;
+}
+
+.eupopup-button:hover,
+.eupopup-button:focus {
+ text-decoration: underline;
+ color: #f6a21d;
+}
+
+.policy-heading .policy-viewdoc-buttons {
+ text-align: center;
+ margin: 15px;
+}
+
+#page-admin-tool-policy-acceptances .colselect {
+ max-width: 15px;
+}
--- /dev/null
+{{!
+ 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}}
--- /dev/null
+{{!
+ 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}}">
+ <input type="hidden" name="action" value="agreedocs">
+
+{{#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" value={{#quote}}{{#str}} next {{/str}}{{/quote}}>
+<input type="reset" class="btn btn-secondary" value={{#quote}}{{#str}} cancel {{/str}}{{/quote}}>
+
+</form>
+
+{{#js}}
+// Initialise the JS for the modal window which displays the policy versions.
+require(['tool_policy/policyactions'], function(ActionsMod) {
+ ActionsMod.init();
+});
+{{/js}}
--- /dev/null
+{{!
+ 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": "admin@yoursite.com"
+ }
+}}
+
+{{^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}}
--- /dev/null
+{{!
+ 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": [
+ {
+ "name": "Terms & conditions",
+ "summary": "Policy <u>summary</u>",
+ "content": "Policy <em>content</em>"
+ },
+ {
+ "name": "Privacy",
+ "summary": "We keep your information private",
+ "content": "Very private"
+ }
+ ]
+ }
+}}
+
+{{#policies }}
+ <div class="policy_version m-b-3">
+ <div class="clearfix m-t-2">
+ <h1>{{{name}}}</h1>
+ </div>
+ <div class="policy_document_summary clearfix m-b-1">
+ {{{summary}}}
+ </div>
+ <div class="policy_document_content m-t-2">
+ {{{content}}}
+ </div>
+ <hr>
+ </div>
+
+{{/policies }}
--- /dev/null
+{{!
+ 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>
--- /dev/null
+<?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 <sara@moodle.com>
+ * @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 <sara@moodle.com>
+ * @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();
+ }
+}
--- /dev/null
+<?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>
--- /dev/null
+<?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 (sara@moodle.com)
+ * @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();
--- /dev/null
+<?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 (sara@moodle.com)
+ * @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();