MDL-61307 core_privacy: Define and test providers
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file defines the core_privacy\local\metadata\collection class object.
|
||||
*
|
||||
* The collection class is used to organize a collection of types
|
||||
* objects, which contains the privacy field details of a component.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\local\metadata;
|
||||
|
||||
use core_privacy\local\metadata\types\type;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* A collection of metadata items.
|
||||
*
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class collection {
|
||||
|
||||
/**
|
||||
* @var string The component that the items in the collection belong to.
|
||||
*/
|
||||
protected $component;
|
||||
|
||||
/**
|
||||
* @var array The collection of metadata items.
|
||||
*/
|
||||
protected $collection = [];
|
||||
|
||||
/**
|
||||
* Constructor for a component's privacy collection class.
|
||||
*
|
||||
* @param string $component component name.
|
||||
*/
|
||||
public function __construct($component) {
|
||||
$this->component = $component;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to add an object that implements type interface to the current collection.
|
||||
*
|
||||
* @param type $type to add to collection.
|
||||
* @return $this
|
||||
*/
|
||||
public function add_type(type $type) {
|
||||
$this->collection[] = $type;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to add a database table which contains user data to this collection.
|
||||
*
|
||||
* @param string $name the name of the database table.
|
||||
* @param array $privacyfields An associative array of fieldname to description.
|
||||
* @param string $summary A description of what the table is used for.
|
||||
* @return $this
|
||||
*/
|
||||
public function add_database_table($name, array $privacyfields, $summary = '') {
|
||||
$this->add_type(new types\database_table($name, $privacyfields, $summary));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to link a subsystem to the component.
|
||||
*
|
||||
* @param string $name the name of the subsystem to link.
|
||||
* @param string $summary A description of what is stored within this subsystem.
|
||||
* @return $this
|
||||
*/
|
||||
public function link_subsystem($name, $summary = '') {
|
||||
$this->add_type(new types\subsystem_link($name, $summary));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to link a plugin to the component.
|
||||
*
|
||||
* @param string $name the name of the plugin to link.
|
||||
* @param string $summary A description of what tis stored within this plugin.
|
||||
* @return $this
|
||||
*/
|
||||
public function link_plugintype($name, $summary = '') {
|
||||
$this->add_type(new types\plugintype_link($name, $summary));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to indicate that data may be exported to an external location.
|
||||
*
|
||||
* @param string $name A name for the type of data exported.
|
||||
* @param array $privacyfields A list of fields with their description.
|
||||
* @param string $summary A description of what the table is used for. This is a language string identifier
|
||||
* within the component.
|
||||
* @return $this
|
||||
*/
|
||||
public function link_external_location($name, array $privacyfields, $summary = '') {
|
||||
$this->add_type(new types\external_location($name, $privacyfields, $summary));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a type of user preference to the collection.
|
||||
*
|
||||
* Typically this is a single user preference, but in some cases the
|
||||
* name of a user preference fits a particular format.
|
||||
*
|
||||
* @param string $name The name of the user preference.
|
||||
* @param string $summary A description of what the preference is used for.
|
||||
* @return $this
|
||||
*/
|
||||
public function add_user_preference($name, $summary = '') {
|
||||
$this->add_type(new types\user_preference($name, $summary));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to return the current component name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_component() {
|
||||
return $this->component;
|
||||
}
|
||||
|
||||
/**
|
||||
* The content of this collection.
|
||||
*
|
||||
* @return types\type[]
|
||||
*/
|
||||
public function get_collection() {
|
||||
return $this->collection;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file contains the core_privacy\nodata interface.
|
||||
*
|
||||
* Plugins implement this interface to declare that they don't store any personal information.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
*
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\local\metadata;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
interface null_provider {
|
||||
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_reason() : string ;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* INterface for main metadata provider interface.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\local\metadata;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* INterface for main metadata provider interface.
|
||||
*
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
interface provider {
|
||||
|
||||
/**
|
||||
* Returns meta data about this system.
|
||||
*
|
||||
* @param collection $collection The initialised collection to add items to.
|
||||
* @return collection A listing of user data stored through this system.
|
||||
*/
|
||||
public static function get_metadata(collection $collection) : collection ;
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file defines an item of metadata which encapsulates a database table.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Zig Tan <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\local\metadata\types;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The database_table type.
|
||||
*
|
||||
* @copyright 2018 Zig Tan <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class database_table implements type {
|
||||
|
||||
/**
|
||||
* @var string Database table name.
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* @var array Fields which contain user information within the table.
|
||||
*/
|
||||
protected $privacyfields;
|
||||
|
||||
/**
|
||||
* @var string A description of what this table is used for.
|
||||
*/
|
||||
protected $summary;
|
||||
|
||||
/**
|
||||
* Constructor to create a new database_table type.
|
||||
*
|
||||
* @param string $name The name of the database table being described.
|
||||
* @param array $privacyfields A list of fields with their description.
|
||||
* @param string $summary A description of what the table is used for.
|
||||
*/
|
||||
public function __construct($name, array $privacyfields = [], $summary = '') {
|
||||
if (debugging('', DEBUG_DEVELOPER)) {
|
||||
if (empty($privacyfields)) {
|
||||
debugging("Table '{$name}' was supplied without any fields.", DEBUG_DEVELOPER);
|
||||
}
|
||||
|
||||
foreach ($privacyfields as $key => $field) {
|
||||
$teststring = clean_param($field, PARAM_STRINGID);
|
||||
if ($teststring !== $field) {
|
||||
debugging("Field '{$key}' passed for table '{$name}' has an invalid langstring identifier: '{$field}'",
|
||||
DEBUG_DEVELOPER);
|
||||
}
|
||||
}
|
||||
|
||||
$teststring = clean_param($summary, PARAM_STRINGID);
|
||||
if ($teststring !== $summary) {
|
||||
debugging("Summary information for the '{$name}' table has an invalid langstring identifier: '{$summary}'",
|
||||
DEBUG_DEVELOPER);
|
||||
}
|
||||
}
|
||||
|
||||
$this->name = $name;
|
||||
$this->privacyfields = $privacyfields;
|
||||
$this->summary = $summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the database table.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_name() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* The list of fields within the table which contain user data, with a description of each field.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_privacy_fields() {
|
||||
return $this->privacyfields;
|
||||
}
|
||||
|
||||
/**
|
||||
* A summary of what this table is used for.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_summary() {
|
||||
return $this->summary;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file defines an item of metadata which encapsulates data which is exported to an external location.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\local\metadata\types;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The external_location type.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class external_location implements type {
|
||||
|
||||
/**
|
||||
* @var string The name to describe the type of information exported.
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* @var array The list of data names and descriptions exported.
|
||||
*/
|
||||
protected $privacyfields;
|
||||
|
||||
/**
|
||||
* @var string A description of what this table is used for.
|
||||
* This is a language string identifier.
|
||||
*/
|
||||
protected $summary;
|
||||
|
||||
/**
|
||||
* Constructor to create a new external_location type.
|
||||
*
|
||||
* @param string $name A name for the type of data exported.
|
||||
* @param array $privacyfields A list of fields with their description.
|
||||
* @param string $summary A description of what the table is used for. This is a language string identifier
|
||||
* within the component.
|
||||
*/
|
||||
public function __construct($name, array $privacyfields = [], $summary = '') {
|
||||
if (debugging('', DEBUG_DEVELOPER)) {
|
||||
if (empty($privacyfields)) {
|
||||
debugging("Location '{$name}' was supplied without any fields.", DEBUG_DEVELOPER);
|
||||
}
|
||||
|
||||
foreach ($privacyfields as $key => $field) {
|
||||
$teststring = clean_param($field, PARAM_STRINGID);
|
||||
if ($teststring !== $field) {
|
||||
debugging("Field '{$key}' passed for location '{$name}' has an invalid langstring identifier: '{$field}'",
|
||||
DEBUG_DEVELOPER);
|
||||
}
|
||||
}
|
||||
|
||||
$teststring = clean_param($summary, PARAM_STRINGID);
|
||||
if ($teststring !== $summary) {
|
||||
debugging("Summary information for the '{$name}' location has an invalid langstring identifier: '{$summary}'",
|
||||
DEBUG_DEVELOPER);
|
||||
}
|
||||
}
|
||||
|
||||
$this->name = $name;
|
||||
$this->privacyfields = $privacyfields;
|
||||
$this->summary = $summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name to describe the type of information exported.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_name() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of fields which contain user data, with a description of each field.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_privacy_fields() {
|
||||
return $this->privacyfields;
|
||||
}
|
||||
|
||||
/**
|
||||
* A summary of what this type of exported data is used for.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_summary() {
|
||||
return $this->summary;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file defines a link to another Moodle plugin.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Zig Tan <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\local\metadata\types;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The plugintype link.
|
||||
*
|
||||
* @copyright 2018 Zig Tan <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class plugintype_link implements type {
|
||||
|
||||
/**
|
||||
* @var The name of the core plugintype to link.
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* @var string A description of what this plugintype is used to store.
|
||||
*/
|
||||
protected $summary;
|
||||
|
||||
/**
|
||||
* Constructor for the plugintype_link.
|
||||
*
|
||||
* @param string $name The name of the plugintype to link.
|
||||
* @param string $summary A description of what is stored within this plugintype.
|
||||
*/
|
||||
public function __construct($name, $summary = '') {
|
||||
if (debugging('', DEBUG_DEVELOPER)) {
|
||||
$teststring = clean_param($summary, PARAM_STRINGID);
|
||||
if ($teststring !== $summary) {
|
||||
debugging("Summary information for use of the '{$name}' plugintype " .
|
||||
"has an invalid langstring identifier: '{$summary}'",
|
||||
DEBUG_DEVELOPER);
|
||||
}
|
||||
}
|
||||
|
||||
$this->name = $name;
|
||||
$this->summary = $summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to return the name of this plugintype_link type.
|
||||
*
|
||||
* @return string $name
|
||||
*/
|
||||
public function get_name() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* A plugintype link does not define any fields itself.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_privacy_fields() : array {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A summary of what this plugintype is used for.
|
||||
*
|
||||
* @return string $summary
|
||||
*/
|
||||
public function get_summary() {
|
||||
return $this->summary;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file defines a link to another Moodle subsystem.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Zig Tan <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\local\metadata\types;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The subsystem link type.
|
||||
*
|
||||
* @copyright 2018 Zig Tan <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class subsystem_link implements type {
|
||||
|
||||
/**
|
||||
* @var The name of the core subsystem to link.
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* @var string A description of what this subsystem is used to store.
|
||||
*/
|
||||
protected $summary;
|
||||
|
||||
/**
|
||||
* Constructor for the subsystem_link.
|
||||
*
|
||||
* @param string $name The name of the subsystem to link.
|
||||
* @param string $summary A description of what is stored within this subsystem.
|
||||
*/
|
||||
public function __construct($name, $summary = '') {
|
||||
if (debugging('', DEBUG_DEVELOPER)) {
|
||||
$teststring = clean_param($summary, PARAM_STRINGID);
|
||||
if ($teststring !== $summary) {
|
||||
debugging("Summary information for use of the '{$name}' subsystem " .
|
||||
"has an invalid langstring identifier: '{$summary}'",
|
||||
DEBUG_DEVELOPER);
|
||||
}
|
||||
}
|
||||
|
||||
$this->name = $name;
|
||||
$this->summary = $summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to return the name of this subsystem_link type.
|
||||
*
|
||||
* @return string $name
|
||||
*/
|
||||
public function get_name() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* A subsystem link does not define any fields itself.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_privacy_fields() : array {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A summary of what this subsystem is used for.
|
||||
*
|
||||
* @return string $summary
|
||||
*/
|
||||
public function get_summary() {
|
||||
return $this->summary;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* The base type interface which encapsulates a set of data held by a component with Moodle.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Zig Tan <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\local\metadata\types;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The base type interface which all metadata types must implement.
|
||||
*
|
||||
* @copyright 2018 Zig Tan <[email protected]>
|
||||
* @package core_privacy
|
||||
*/
|
||||
interface type {
|
||||
|
||||
/**
|
||||
* Get the name describing this type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_name();
|
||||
|
||||
/**
|
||||
* A list of the fields and their usage description.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_privacy_fields();
|
||||
|
||||
/**
|
||||
* A summary of what the metalink type is used for.
|
||||
*
|
||||
* @return string $summary
|
||||
*/
|
||||
public function get_summary();
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file defines an item of metadata which encapsulates a user's preferences.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_privacy\local\metadata\types;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The user_preference type.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class user_preference implements type {
|
||||
|
||||
/**
|
||||
* @var The name of this user preference.
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* @var A description of what this user preference means.
|
||||
*/
|
||||
protected $summary;
|
||||
|
||||
/**
|
||||
* Constructor to create a new user_preference types.
|
||||
*
|
||||
* @param string $name The name of the user preference.
|
||||
* @param string $summary A description of what the preference is used for.
|
||||
*/
|
||||
public function __construct($name, $summary = '') {
|
||||
if (debugging('', DEBUG_DEVELOPER)) {
|
||||
$teststring = clean_param($summary, PARAM_STRINGID);
|
||||
if ($teststring !== $summary) {
|
||||
debugging("Summary information for use of the '{$name}' subsystem " .
|
||||
" has an invalid langstring identifier: '{$summary}'",
|
||||
DEBUG_DEVELOPER);
|
||||
}
|
||||
}
|
||||
|
||||
$this->name = $name;
|
||||
$this->summary = $summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the user preference.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_name() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* A user preference encapsulates a single field and has no sub-fields.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_privacy_fields() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A summary of what this user preference is used for.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_summary() {
|
||||
return $this->summary;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* An implementation of a contextlist which has been filtered and approved.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_privacy\local\request;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* An implementation of a contextlist which has been filtered and approved.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class approved_contextlist extends contextlist_base {
|
||||
|
||||
/**
|
||||
* @var \stdClass The user this contextlist belongs to.
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* Create a new approved contextlist.
|
||||
*
|
||||
* @param \stdClass $user The user record.
|
||||
* @param string $component the frankenstyle component name.
|
||||
* @param \int[] $contextids The list of contextids present in this list.
|
||||
*/
|
||||
public function __construct(\stdClass $user, string $component, array $contextids) {
|
||||
$this->set_user($user);
|
||||
$this->set_component($component);
|
||||
$this->set_contextids($contextids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the user which owns this request.
|
||||
*
|
||||
* @param \stdClass $user The user record.
|
||||
* @return $this
|
||||
*/
|
||||
protected function set_user(\stdClass $user) : approved_contextlist {
|
||||
$this->user = $user;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user which requested their data.
|
||||
*
|
||||
* @return \stdClass
|
||||
*/
|
||||
public function get_user() : \stdClass {
|
||||
return $this->user;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file contains the interface required to implmeent a content writer.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\local\request;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The interface for a Moodle content writer.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
*/
|
||||
interface content_writer {
|
||||
|
||||
/**
|
||||
* Constructor for the content writer.
|
||||
*
|
||||
* Note: The writer_factory must be passed.
|
||||
* @param writer $writer The factory.
|
||||
*/
|
||||
public function __construct(writer $writer);
|
||||
|
||||
/**
|
||||
* Set the context for the current item being processed.
|
||||
*
|
||||
* @param \context $context The context to use
|
||||
* @return content_writer
|
||||
*/
|
||||
public function set_context(\context $context) : content_writer ;
|
||||
|
||||
/**
|
||||
* Export the supplied data within the current context, at the supplied subcontext.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @param \stdClass $data The data to be exported
|
||||
* @return content_writer
|
||||
*/
|
||||
public function export_data(array $subcontext, \stdClass $data) : content_writer ;
|
||||
|
||||
/**
|
||||
* Export metadata about the supplied subcontext.
|
||||
*
|
||||
* Metadata consists of a key/value pair and a description of the value.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @param string $name The metadata name.
|
||||
* @param string $value The metadata value.
|
||||
* @param string $description The description of the value.
|
||||
* @return content_writer
|
||||
*/
|
||||
public function export_metadata(array $subcontext, string $name, $value, string $description) : content_writer ;
|
||||
|
||||
/**
|
||||
* Export a piece of related data.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @param string $name The name of the file to be exported.
|
||||
* @param \stdClass $data The related data to export.
|
||||
* @return content_writer
|
||||
*/
|
||||
public function export_related_data(array $subcontext, $name, $data) : content_writer ;
|
||||
|
||||
/**
|
||||
* Export a piece of data in a custom format.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @param string $filename The name of the file to be exported.
|
||||
* @param string $filecontent The content to be exported.
|
||||
* @return content_writer
|
||||
*/
|
||||
public function export_custom_file(array $subcontext, $filename, $filecontent) : content_writer ;
|
||||
|
||||
/**
|
||||
* Prepare a text area by processing pluginfile URLs within it.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @param string $component The name of the component that the files belong to.
|
||||
* @param string $filearea The filearea within that component.
|
||||
* @param string $itemid Which item those files belong to.
|
||||
* @param string $text The text to be processed
|
||||
* @return string The processed string
|
||||
*/
|
||||
public function rewrite_pluginfile_urls(array $subcontext, $component, $filearea, $itemid, $text) : string;
|
||||
|
||||
/**
|
||||
* Export all files within the specified component, filearea, itemid combination.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @param string $component The name of the component that the files belong to.
|
||||
* @param string $filearea The filearea within that component.
|
||||
* @param string $itemid Which item those files belong to.
|
||||
* @return content_writer
|
||||
*/
|
||||
public function export_area_files(array $subcontext, $component, $filearea, $itemid) : content_writer ;
|
||||
|
||||
/**
|
||||
* Export the specified file in the target location.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @param \stored_file $file The file to be exported.
|
||||
* @return content_writer
|
||||
*/
|
||||
public function export_file(array $subcontext, \stored_file $file) : content_writer ;
|
||||
|
||||
/**
|
||||
* Export the specified user preference.
|
||||
*
|
||||
* @param string $component The name of the component.
|
||||
* @param string $key The name of th key to be exported.
|
||||
* @param string $value The value of the preference
|
||||
* @param string $description A description of the value
|
||||
* @return content_writer
|
||||
*/
|
||||
public function export_user_preference(string $component, string $key, string $value, string $description) : content_writer ;
|
||||
|
||||
/**
|
||||
* Perform any required finalisation steps and return the location of the finalised export.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function finalise_content() : string ;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Privacy Fetch Result Set.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_privacy\local\request;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Privacy Fetch Result Set.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class contextlist extends contextlist_base {
|
||||
|
||||
/**
|
||||
* Add a set of contexts from SQL.
|
||||
*
|
||||
* The SQL should only return a list of context IDs.
|
||||
*
|
||||
* @param string $sql The SQL which will fetch the list of * context IDs
|
||||
* @param array $params The set of SQL parameters
|
||||
* @return $this
|
||||
*/
|
||||
public function add_from_sql(string $sql, array $params) : contextlist {
|
||||
global $DB;
|
||||
|
||||
$fields = \context_helper::get_preload_record_columns_sql('ctx');
|
||||
$wrapper = "SELECT {$fields} FROM {context} ctx WHERE id IN ({$sql})";
|
||||
$contexts = $DB->get_recordset_sql($wrapper, $params);
|
||||
|
||||
$contextids = [];
|
||||
foreach ($contexts as $context) {
|
||||
$contextids[] = $context->ctxid;
|
||||
\context_helper::preload_from_record($context);
|
||||
}
|
||||
|
||||
$this->set_contextids(array_merge($this->get_contextids(), $contextids));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the component for this contextlist.
|
||||
*
|
||||
* @param string $component the frankenstyle component name.
|
||||
*/
|
||||
public function set_component($component) {
|
||||
parent::set_component($component);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Base implementation of a contextlist.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_privacy\local\request;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Base implementation of a contextlist used to store a set of contexts.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
abstract class contextlist_base implements
|
||||
// Implement an Iterator to fetch the Context objects.
|
||||
\Iterator,
|
||||
|
||||
// Implement the Countable interface to allow the number of returned results to be queried easily.
|
||||
\Countable {
|
||||
|
||||
/**
|
||||
* @var array List of context IDs.
|
||||
*
|
||||
* Note: this must not be updated using set_contextids only as this
|
||||
* ensures uniqueness.
|
||||
*/
|
||||
private $contextids = [];
|
||||
|
||||
/**
|
||||
* @var string component the frankenstyle component name.
|
||||
*/
|
||||
protected $component = '';
|
||||
|
||||
/**
|
||||
* @var int Current position of the iterator.
|
||||
*/
|
||||
protected $iteratorposition = 0;
|
||||
|
||||
/**
|
||||
* Set the contextids.
|
||||
*
|
||||
* @param array $contextids The list of contexts.
|
||||
*/
|
||||
protected function set_contextids(array $contextids) {
|
||||
$this->contextids = array_unique($contextids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of context IDs that relate to this request.
|
||||
*
|
||||
* @return int[]
|
||||
*/
|
||||
public function get_contextids() : array {
|
||||
return $this->contextids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the complete list of context objects that relate to this
|
||||
* request.
|
||||
*
|
||||
* @return \contect[]
|
||||
*/
|
||||
public function get_contexts() : array {
|
||||
$contexts = [];
|
||||
foreach ($this->contextids as $contextid) {
|
||||
$contexts[] = \context::instance_by_id($contextid);
|
||||
}
|
||||
|
||||
return $contexts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the component for this contextlist.
|
||||
*
|
||||
* @param string $component the frankenstyle component name.
|
||||
*/
|
||||
protected function set_component($component) {
|
||||
$this->component = $component;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the component to which this contextlist belongs.
|
||||
*
|
||||
* @return string the component name associated with this contextlist.
|
||||
*/
|
||||
public function get_component() : string {
|
||||
return $this->component;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current context.
|
||||
*
|
||||
* @return \context
|
||||
*/
|
||||
public function current() {
|
||||
return \context::instance_by_id($this->contextids[$this->iteratorposition]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the key of the current element.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function key() {
|
||||
return $this->iteratorposition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move to the next context in the list.
|
||||
*/
|
||||
public function next() {
|
||||
++$this->iteratorposition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the current position is valid.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function valid() {
|
||||
return isset($this->contextids[$this->iteratorposition]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewind to the first found context.
|
||||
*
|
||||
* The list of contexts is uniqued during the rewind.
|
||||
* The rewind is called at the start of most iterations.
|
||||
*/
|
||||
public function rewind() {
|
||||
$this->iteratorposition = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of contexts.
|
||||
*/
|
||||
public function count() {
|
||||
return count($this->contextids);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file defines the contextlist_collection class object.
|
||||
*
|
||||
* The contextlist_collection is used to organize a collection of contextlists.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\local\request;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* A collection of contextlist items.
|
||||
*
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class contextlist_collection implements \Iterator, \Countable {
|
||||
|
||||
/**
|
||||
* @var int $userid The ID of the user that the contextlist collection belongs to.
|
||||
*/
|
||||
protected $userid = null;
|
||||
|
||||
/**
|
||||
* @var array $contextlists the internal array of contextlist objects.
|
||||
*/
|
||||
protected $contextlists = [];
|
||||
|
||||
/**
|
||||
* @var int Current position of the iterator.
|
||||
*/
|
||||
protected $iteratorposition = 0;
|
||||
|
||||
/**
|
||||
* Constructor to create a new contextlist_collection.
|
||||
*
|
||||
* @param int $userid The userid to which this collection belongs.
|
||||
*/
|
||||
public function __construct($userid) {
|
||||
$this->userid = $userid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ID of the user whose collection this is.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_userid() : int {
|
||||
return $this->userid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a contextlist to this collection.
|
||||
*
|
||||
* @param contextlist_base $contextlist the contextlist to export.
|
||||
* @return $this
|
||||
*/
|
||||
public function add_contextlist(contextlist_base $contextlist) {
|
||||
$component = $contextlist->get_component();
|
||||
if (empty($component)) {
|
||||
throw new \moodle_exception("The contextlist must have a component set");
|
||||
}
|
||||
if (isset($this->contextlists[$component])) {
|
||||
throw new \moodle_exception("A contextlist has already been added for the '{$component}' component");
|
||||
}
|
||||
|
||||
$this->contextlists[$component] = $contextlist;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the contextlists in this collection.
|
||||
*
|
||||
* @return array the associative array of contextlists in this collection, indexed by component name.
|
||||
* E.g. mod_assign => contextlist, core_comment => contextlist.
|
||||
*/
|
||||
public function get_contextlists() : array {
|
||||
return $this->contextlists;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the contextlist for the specified component.
|
||||
*
|
||||
* @param string $component the frankenstyle name of the component to fetch for.
|
||||
* @return contextlist_base|null
|
||||
*/
|
||||
public function get_contextlist_for_component(string $component) {
|
||||
if (isset($this->contextlists[$component])) {
|
||||
return $this->contextlists[$component];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current contexlist.
|
||||
*
|
||||
* @return \context
|
||||
*/
|
||||
public function current() {
|
||||
$key = $this->get_key_from_position();
|
||||
return $this->contextlists[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the key of the current element.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function key() {
|
||||
return $this->get_key_from_position();
|
||||
}
|
||||
|
||||
/**
|
||||
* Move to the next context in the list.
|
||||
*/
|
||||
public function next() {
|
||||
++$this->iteratorposition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the current position is valid.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function valid() {
|
||||
return ($this->iteratorposition < count($this->contextlists));
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewind to the first found context.
|
||||
*
|
||||
* The list of contexts is uniqued during the rewind.
|
||||
* The rewind is called at the start of most iterations.
|
||||
*/
|
||||
public function rewind() {
|
||||
$this->iteratorposition = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key for the current iterator position.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_key_from_position() {
|
||||
$keylist = array_keys($this->contextlists);
|
||||
if (isset($keylist[$this->iteratorposition])) {
|
||||
return $keylist[$this->iteratorposition];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of contexts.
|
||||
*/
|
||||
public function count() {
|
||||
return count($this->contextlists);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file contains the \core_privacy\local\request\core_data_provider interface to describe
|
||||
* classes which provide data in some form to core.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\local\request;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The core_data_provider interface is used to describe a provider which
|
||||
* services user requests between components and core.
|
||||
*
|
||||
* It does not define a specific way of doing so and different types of
|
||||
* data will need to extend this interface in order to define their own
|
||||
* contract.
|
||||
*
|
||||
* It should not be implemented directly, but should be extended by other
|
||||
* interfaces in core.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
*/
|
||||
interface core_data_provider extends data_provider {
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file contains the \core_privacy\local\request\core_user_data_provider interface to describe
|
||||
* classes which provide user data in some form to core.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
*
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\local\request;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The core_user_data_provider interface is used to describe a provider
|
||||
* which services user requests between components and core.
|
||||
*
|
||||
* It describes data how these requests are serviced in a specific format.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
*/
|
||||
interface core_user_data_provider extends core_data_provider {
|
||||
|
||||
/**
|
||||
* Get the list of contexts that contain user information for the specified user.
|
||||
*
|
||||
* @param int $userid The user to search.
|
||||
* @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
|
||||
*/
|
||||
public static function get_contexts_for_userid(int $userid) : contextlist;
|
||||
|
||||
/**
|
||||
* Export all user data for the specified user, in the specified contexts.
|
||||
*
|
||||
* @param approved_contextlist $contextlist The approved contexts to export information for.
|
||||
*/
|
||||
public static function export_user_data(approved_contextlist $contextlist);
|
||||
|
||||
/**
|
||||
* Delete all use data which matches the specified deletion_criteria.
|
||||
*
|
||||
* @param deletion_criteria $criteria An object containing specific deletion criteria to delete for.
|
||||
*/
|
||||
public static function delete_for_context(deletion_criteria $criteria);
|
||||
|
||||
/**
|
||||
* Delete all user data for the specified user, in the specified contexts.
|
||||
*
|
||||
* @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
|
||||
*/
|
||||
public static function delete_user_data(approved_contextlist $contextlist);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file contains the \core_privacy\local\request\data_provider interface to describe
|
||||
* a class which provides data in some form.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\local\request;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The data_provider interface is used to describe a provider
|
||||
* which services user requests in any fashion. This includes both
|
||||
* -- component <-> core; and
|
||||
* -- component <-> component.
|
||||
*
|
||||
* It does not define a specific way of doing so and different types of
|
||||
* data will need to extend this interface in order to define their own
|
||||
* contract.
|
||||
*
|
||||
* It should not be implemented directly, but should be extended by other
|
||||
* interfaces in core.
|
||||
*
|
||||
* This is the base interface for any component which stores any form of
|
||||
* user data.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
*/
|
||||
interface data_provider {
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* The \core_privacy\local\request\deletion_criteria class.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\local\request;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The deletion_criteria class is used to describe conditions for a set of
|
||||
* data due to be deleted.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class deletion_criteria {
|
||||
/**
|
||||
* @var context The context being deleted.
|
||||
*/
|
||||
protected $context = null;
|
||||
|
||||
/**
|
||||
* Constructor for a new deletion_criteria.
|
||||
*
|
||||
* @param \context $context The context being deleted.
|
||||
*/
|
||||
public function __construct(\context $context) {
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the context to be deleted.
|
||||
*
|
||||
* @return \context
|
||||
*/
|
||||
public function get_context() : \context {
|
||||
return $this->context;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,301 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file contains the core_privacy\local\request helper.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
*
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\local\request;
|
||||
|
||||
use \core_privacy\local\request\writer;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir . '/modinfolib.php');
|
||||
require_once($CFG->dirroot . '/course/modlib.php');
|
||||
|
||||
/**
|
||||
* The core_privacy\local\request\helper class with useful shared functionality.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
*
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class helper {
|
||||
|
||||
/**
|
||||
* Add core-controlled contexts which are related to a component but that component may know about.
|
||||
*
|
||||
* For example, most activities are not aware of activity completion, but the course implements it for them.
|
||||
* These should be included.
|
||||
*
|
||||
* @param int $userid The user being added for.
|
||||
* @param contextlist $contextlist The contextlist being appended to.
|
||||
* @return contextlist The final contextlist
|
||||
*/
|
||||
public static function add_shared_contexts_to_contextlist_for(int $userid, contextlist $contextlist) : contextlist {
|
||||
if (strpos($contextlist->get_component(), 'mod_') === 0) {
|
||||
// Activity modules support data stored by core about them - for example, activity completion.
|
||||
$contextlist = static::add_shared_contexts_to_contextlist_for_course_module($userid, $contextlist);
|
||||
}
|
||||
|
||||
return $contextlist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle export of standard data for a plugin which implements the null provider and does not normally store data
|
||||
* of its own.
|
||||
*
|
||||
* This is used in cases such as activities like mod_resource, which do not store their own data, but may still have
|
||||
* data on them (like Activity Completion).
|
||||
*
|
||||
* Any context provided in a contextlist should have base data exported as a minimum.
|
||||
*
|
||||
* @param approved_contextlist $contextlist The approved contexts to export information for.
|
||||
*/
|
||||
public static function export_data_for_null_provider(approved_contextlist $contextlist) {
|
||||
$user = $contextlist->get_user();
|
||||
foreach ($contextlist as $context) {
|
||||
$data = static::get_context_data($context, $user);
|
||||
static::export_context_files($context, $user);
|
||||
|
||||
writer::with_context($context)->export_data([], $data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle removal of 'standard' data for any plugin.
|
||||
*
|
||||
* This will handle deletion for things such as activity completion.
|
||||
*
|
||||
* @param string $component The component being deleted for.
|
||||
* @param deletion_criteria $criteria An object containing specific deletion criteria to delete for.
|
||||
*/
|
||||
public static function delete_for_context(string $component, deletion_criteria $criteria) {
|
||||
if (strpos($component, 'mod_') === 0) {
|
||||
// Activity modules support data stored by core about them - for example, activity completion.
|
||||
static::delete_for_context_course_module($component, $criteria->get_context());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all 'standard' user data for the specified user, in the specified contexts.
|
||||
*
|
||||
* This will handle deletion for things such as activity completion.
|
||||
*
|
||||
* @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
|
||||
*/
|
||||
public static function delete_user_data(approved_contextlist $contextlist) {
|
||||
$component = $contextlist->get_component();
|
||||
|
||||
if (strpos($component, 'mod_') === 0) {
|
||||
// Activity modules support data stored by core about them - for example, activity completion.
|
||||
static::delete_user_data_for_course_module($contextlist);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all general data for this context.
|
||||
*
|
||||
* @param \context $context The context to retrieve data for.
|
||||
* @param \stdClass $user The user being written.
|
||||
* @return \stdClass
|
||||
*/
|
||||
public static function get_context_data(\context $context, \stdClass $user) : \stdClass {
|
||||
global $DB;
|
||||
|
||||
$basedata = (object) [];
|
||||
if ($context instanceof \context_module) {
|
||||
return static::get_context_module_data($context, $user);
|
||||
}
|
||||
if ($context instanceof \context_block) {
|
||||
return static::get_context_block_data($context, $user);
|
||||
}
|
||||
|
||||
return $basedata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export all files for this context.
|
||||
*
|
||||
* @param \context $context The context to export files for.
|
||||
* @param \stdClass $user The user being written.
|
||||
* @return \stdClass
|
||||
*/
|
||||
public static function export_context_files(\context $context, \stdClass $user) {
|
||||
if ($context instanceof \context_module) {
|
||||
return static::export_context_module_files($context, $user);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add core-controlled contexts which are related to a component but that component may know about.
|
||||
*
|
||||
* For example, most activities are not aware of activity completion, but the course implements it for them.
|
||||
* These should be included.
|
||||
*
|
||||
* @param int $userid The user being added for.
|
||||
* @param contextlist $contextlist The contextlist being appended to.
|
||||
* @return contextlist The final contextlist
|
||||
*/
|
||||
protected static function add_shared_contexts_to_contextlist_for_course_module(int $userid, contextlist $contextlist) : contextlist {
|
||||
// Fetch all contexts where the user has activity completion enabled.
|
||||
$sql = "SELECT
|
||||
c.id
|
||||
FROM {course_modules_completion} cmp
|
||||
INNER JOIN {course_modules} cm ON cm.id = cmp.coursemoduleid
|
||||
INNER JOIN {modules} m ON m.id = cm.module
|
||||
INNER JOIN {context} c ON c.instanceid = cm.id AND c.contextlevel = :contextlevel
|
||||
WHERE cmp.userid = :userid
|
||||
AND m.name = :modname";
|
||||
$params = [
|
||||
'userid' => $userid,
|
||||
// Strip the mod_ from the name.
|
||||
'modname' => substr($contextlist->get_component(), 4),
|
||||
'contextlevel' => CONTEXT_MODULE,
|
||||
];
|
||||
|
||||
$contextlist->add_from_sql($sql, $params);
|
||||
|
||||
return $contextlist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all general data for the activity module at this context.
|
||||
*
|
||||
* @param \context_module $context The context to retrieve data for.
|
||||
* @param \stdClass $user The user being written.
|
||||
* @return \stdClass
|
||||
*/
|
||||
protected static function get_context_module_data(\context_module $context, \stdClass $user) : \stdClass {
|
||||
global $DB;
|
||||
|
||||
$coursecontext = $context->get_course_context();
|
||||
$modinfo = get_fast_modinfo($coursecontext->instanceid);
|
||||
$cm = $modinfo->cms[$context->instanceid];
|
||||
$component = "mod_{$cm->modname}";
|
||||
$course = $cm->get_course();
|
||||
$moduledata = $DB->get_record($cm->modname, ['id' => $cm->instance]);
|
||||
|
||||
$basedata = (object) [
|
||||
'name' => $cm->get_formatted_name(),
|
||||
];
|
||||
|
||||
if (plugin_supports('mod', $cm->modname, FEATURE_MOD_INTRO, true)) {
|
||||
$intro = $moduledata->intro;
|
||||
|
||||
$intro = writer::with_context($context)
|
||||
->rewrite_pluginfile_urls([], $component, 'intro', 0, $intro);
|
||||
|
||||
$options = [
|
||||
'noclean' => true,
|
||||
'para' => false,
|
||||
'context' => $context,
|
||||
'overflowdiv' => true,
|
||||
];
|
||||
$basedata->intro = format_text($intro, $moduledata->introformat, $options);
|
||||
}
|
||||
|
||||
// Completion tracking.
|
||||
$completioninfo = new \completion_info($course);
|
||||
$completion = $completioninfo->is_enabled($cm);
|
||||
if ($completion != COMPLETION_TRACKING_NONE) {
|
||||
$completiondata = $completioninfo->get_data($cm, true, $user->id);
|
||||
$basedata->completion = (object) [
|
||||
'state' => $completiondata->completionstate,
|
||||
];
|
||||
}
|
||||
|
||||
return $basedata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all general data for the block at this context.
|
||||
*
|
||||
* @param \context_block $context The context to retrieve data for.
|
||||
* @param \stdClass $user The user being written.
|
||||
* @return \stdClass General data about this block instance.
|
||||
*/
|
||||
protected static function get_context_block_data(\context_block $context, \stdClass $user) : \stdClass {
|
||||
global $DB;
|
||||
|
||||
$block = $DB->get_record('block_instances', ['id' => $context->instanceid]);
|
||||
|
||||
$basedata = (object) [
|
||||
'blocktype' => get_string('pluginname', 'block_' . $block->blockname)
|
||||
];
|
||||
|
||||
return $basedata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all general data for the activity module at this context.
|
||||
*
|
||||
* @param \context_module $context The context to retrieve data for.
|
||||
* @param \stdClass $user The user being written.
|
||||
* @return \stdClass
|
||||
*/
|
||||
protected static function export_context_module_files(\context_module $context, \stdClass $user) {
|
||||
$coursecontext = $context->get_course_context();
|
||||
$modinfo = get_fast_modinfo($coursecontext->instanceid);
|
||||
$cm = $modinfo->cms[$context->instanceid];
|
||||
$component = "mod_{$cm->modname}";
|
||||
|
||||
writer::with_context($context)
|
||||
// Export the files for the intro.
|
||||
->export_area_files([], $component, 'intro', 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle removal of 'standard' data for course modules.
|
||||
*
|
||||
* This will handle deletion for things such as activity completion.
|
||||
*
|
||||
* @param string $component The component being deleted for.
|
||||
* @param \context_module $context The context to delete all data for.
|
||||
*/
|
||||
public static function delete_for_context_course_module(string $component, \context_module $context) {
|
||||
global $DB;
|
||||
|
||||
// Delete course completion data for this context.
|
||||
$DB->delete_records('course_modules_completion', ['coursemoduleid' => $context->instanceid]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all 'standard' user data for the specified user in course modules.
|
||||
*
|
||||
* This will handle deletion for things such as activity completion.
|
||||
*
|
||||
* @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
|
||||
*/
|
||||
protected static function delete_user_data_for_course_module(approved_contextlist $contextlist) {
|
||||
global $DB;
|
||||
|
||||
foreach ($contextlist as $context) {
|
||||
// Delete course completion data for this context.
|
||||
$DB->delete_records('course_modules_completion', [
|
||||
'coursemoduleid' => $context->instanceid,
|
||||
'userid' => $contextlist->get_user()->id,
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,320 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file contains the moodle format implementation of the content writer.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\local\request;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The moodle_content_writer is the default Moodle implementation of a content writer.
|
||||
*
|
||||
* It exports data to a rich tree structure using Moodle's context system,
|
||||
* and produces a single zip file with all content.
|
||||
*
|
||||
* Objects of data are stored as JSON.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class moodle_content_writer implements content_writer {
|
||||
/**
|
||||
* @var string The base path on disk for this instance.
|
||||
*/
|
||||
protected $path = null;
|
||||
|
||||
/**
|
||||
* @var \context The current context of the writer.
|
||||
*/
|
||||
protected $context = null;
|
||||
|
||||
/**
|
||||
* @var \stored_file[] The list of files to be exported.
|
||||
*/
|
||||
protected $files = [];
|
||||
|
||||
/**
|
||||
* Constructor for the content writer.
|
||||
*
|
||||
* Note: The writer factory must be passed.
|
||||
*
|
||||
* @param writer $writer The factory.
|
||||
*/
|
||||
public function __construct(writer $writer) {
|
||||
$this->path = make_request_directory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the context for the current item being processed.
|
||||
*
|
||||
* @param \context $context The context to use
|
||||
*/
|
||||
public function set_context(\context $context) : content_writer {
|
||||
$this->context = $context;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the supplied data within the current context, at the supplied subcontext.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @param \stdClass $data The data to be exported
|
||||
*/
|
||||
public function export_data(array $subcontext, \stdClass $data) : content_writer {
|
||||
$path = $this->get_path($subcontext, 'data.json');
|
||||
|
||||
$this->write_data($path, json_encode($data));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export metadata about the supplied subcontext.
|
||||
*
|
||||
* Metadata consists of a key/value pair and a description of the value.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @param string $key The metadata name.
|
||||
* @param string $value The metadata value.
|
||||
* @param string $description The description of the value.
|
||||
*/
|
||||
public function export_metadata(array $subcontext, string $key, $value, string $description) : content_writer {
|
||||
$path = $this->get_full_path($subcontext, 'metadata.json');
|
||||
|
||||
if (file_exists($path)) {
|
||||
$data = json_decode(file_get_contents($path));
|
||||
} else {
|
||||
$data = (object) [];
|
||||
}
|
||||
|
||||
$data->$key = (object) [
|
||||
'value' => $value,
|
||||
'description' => $description,
|
||||
];
|
||||
|
||||
$path = $this->get_path($subcontext, 'metadata.json');
|
||||
$this->write_data($path, json_encode($data));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export a piece of related data.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @param string $name The name of the file to be exported.
|
||||
* @param \stdClass $data The related data to export.
|
||||
*/
|
||||
public function export_related_data(array $subcontext, $name, $data) : content_writer {
|
||||
$path = $this->get_path($subcontext, "{$name}.json");
|
||||
|
||||
$this->write_data($path, json_encode($data));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export a piece of data in a custom format.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @param string $filename The name of the file to be exported.
|
||||
* @param string $filecontent The content to be exported.
|
||||
*/
|
||||
public function export_custom_file(array $subcontext, $filename, $filecontent) : content_writer {
|
||||
$filename = clean_param($filename, PARAM_FILE);
|
||||
$path = $this->get_path($subcontext, $filename);
|
||||
$this->write_data($path, $filecontent);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a text area by processing pluginfile URLs within it.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @param string $component The name of the component that the files belong to.
|
||||
* @param string $filearea The filearea within that component.
|
||||
* @param string $itemid Which item those files belong to.
|
||||
* @param string $text The text to be processed
|
||||
* @return string The processed string
|
||||
*/
|
||||
public function rewrite_pluginfile_urls(array $subcontext, $component, $filearea, $itemid, $text) : string {
|
||||
return str_replace('@@PLUGINFILE@@/', 'files/', $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export all files within the specified component, filearea, itemid combination.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @param string $component The name of the component that the files belong to.
|
||||
* @param string $filearea The filearea within that component.
|
||||
* @param string $itemid Which item those files belong to.
|
||||
*/
|
||||
public function export_area_files(array $subcontext, $component, $filearea, $itemid) : content_writer {
|
||||
$fs = get_file_storage();
|
||||
$files = $fs->get_area_files($this->context->id, $component, $filearea, $itemid);
|
||||
foreach ($files as $file) {
|
||||
$this->export_file($subcontext, $file);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the specified file in the target location.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @param \stored_file $file The file to be exported.
|
||||
*/
|
||||
public function export_file(array $subcontext, \stored_file $file) : content_writer {
|
||||
if (!$file->is_directory()) {
|
||||
$subcontextextra = [
|
||||
get_string('files'),
|
||||
$file->get_filepath(),
|
||||
];
|
||||
$path = $this->get_path(array_merge($subcontext, $subcontextextra), $file->get_filename());
|
||||
check_dir_exists(dirname($path), true, true);
|
||||
$this->files[$path] = $file;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the specified user preference.
|
||||
*
|
||||
* @param string $component The name of the component.
|
||||
* @param string $key The name of th key to be exported.
|
||||
* @param string $value The value of the preference
|
||||
* @param string $description A description of the value
|
||||
* @return content_writer
|
||||
*/
|
||||
public function export_user_preference(string $component, string $key, string $value, string $description) : content_writer {
|
||||
if ($this->context !== \context_system::instance()) {
|
||||
throw new \coding_exception('export_user_preference must be called against the system context');
|
||||
}
|
||||
$subcontext = [
|
||||
get_string('userpreferences'),
|
||||
];
|
||||
$fullpath = $this->get_full_path($subcontext, "{$component}.json");
|
||||
$path = $this->get_path($subcontext, "{$component}.json");
|
||||
|
||||
if (file_exists($fullpath)) {
|
||||
$data = json_decode(file_get_contents($fullpath));
|
||||
} else {
|
||||
$data = (object) [];
|
||||
}
|
||||
|
||||
$data->$key = (object) [
|
||||
'value' => $value,
|
||||
'description' => $description,
|
||||
];
|
||||
$this->write_data($path, json_encode($data));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the path for the current context.
|
||||
*
|
||||
* @return array The context path.
|
||||
*/
|
||||
protected function get_context_path() : Array {
|
||||
$path = [];
|
||||
$contexts = array_reverse($this->context->get_parent_contexts(true));
|
||||
foreach ($contexts as $context) {
|
||||
$path[] = clean_param($context->get_context_name(), PARAM_FILE);
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the relative file path within the current context, and subcontext, using the specified filename.
|
||||
*
|
||||
* @param string[] $subcontext The location within the current context to export this data.
|
||||
* @param string $name The intended filename, including any extensions.
|
||||
* @return string The fully-qualfiied file path.
|
||||
*/
|
||||
protected function get_path(array $subcontext, string $name) : string {
|
||||
// Combine the context path, and the subcontext data.
|
||||
$path = array_merge(
|
||||
$this->get_context_path(),
|
||||
$subcontext
|
||||
);
|
||||
|
||||
// Join the directory together with the name.
|
||||
$filepath = implode(DIRECTORY_SEPARATOR, $path) . DIRECTORY_SEPARATOR . $name;
|
||||
|
||||
return preg_replace('@' . DIRECTORY_SEPARATOR . '+@', DIRECTORY_SEPARATOR, $filepath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fully-qualified file path within the current context, and subcontext, using the specified filename.
|
||||
*
|
||||
* @param string[] $subcontext The location within the current context to export this data.
|
||||
* @param string $name The intended filename, including any extensions.
|
||||
* @return string The fully-qualfiied file path.
|
||||
*/
|
||||
protected function get_full_path(array $subcontext, string $name) : string {
|
||||
$path = array_merge(
|
||||
[$this->path],
|
||||
[$this->get_path($subcontext, $name)]
|
||||
);
|
||||
|
||||
// Join the directory together with the name.
|
||||
$filepath = implode(DIRECTORY_SEPARATOR, $path);
|
||||
|
||||
return preg_replace('@' . DIRECTORY_SEPARATOR . '+@', DIRECTORY_SEPARATOR, $filepath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the data to the specified path.
|
||||
*
|
||||
* @param string $path The path to export the data at.
|
||||
* @param string $data The data to be exported.
|
||||
*/
|
||||
protected function write_data(string $path, string $data) {
|
||||
$targetpath = $this->path . DIRECTORY_SEPARATOR . $path;
|
||||
check_dir_exists(dirname($targetpath), true, true);
|
||||
file_put_contents($targetpath, $data);
|
||||
$this->files[$path] = $targetpath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform any required finalisation steps and return the location of the finalised export.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function finalise_content() : string {
|
||||
$exportfile = make_request_directory() . '/export.zip';
|
||||
|
||||
$fp = get_file_packer();
|
||||
$fp->archive_to_pathname($this->files, $exportfile);
|
||||
|
||||
// Reset the writer to prevent any further writes.
|
||||
writer::reset();
|
||||
|
||||
return $exportfile;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file contains the \core_privacy\local\request\plugin\provider interface to describe
|
||||
* a class which provides data in some form for a plugin.
|
||||
*
|
||||
* Plugins should implement this if they store any personal information.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\local\request\plugin;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The provider interface for plugins which provide data from a plugin
|
||||
* directly to the Privacy subsystem.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
interface provider extends \core_privacy\local\request\core_user_data_provider {
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file contains the \core_privacy\local\request\plugin\subplugin_provider
|
||||
* interface to describe a class which provides data in some form for the
|
||||
* subplugin of another plugin.
|
||||
*
|
||||
* It should not be implemented directly, but should be extended by the
|
||||
* plugin providing a subplugin.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\local\request\plugin;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The subplugin_provider interface is for plugins which are sub-plugins of
|
||||
* a plugin. They do not provide data directly to the core Privacy
|
||||
* subsystem, but will be accessed and called via the plugin itself.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
interface subplugin_provider extends \core_privacy\local\request\shared_data_provider {
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file contains the \core_privacy\local\request\plugin\subsystem_provider
|
||||
* interface to describe a class which provides data in some form for a
|
||||
* subsystem.
|
||||
*
|
||||
* It should not be implemented directly, but should be extended by the
|
||||
* subsystem responsible for the plugintype.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\local\request\plugin;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The subsystem_provider interface is for plugins which may not
|
||||
* necessarily be called directly, but instead via a subsystem.
|
||||
*
|
||||
* One example of this is the questiontype plugintype. These are
|
||||
* intrinsically linked against the question subsystem and the question
|
||||
* subsystem should define an interface extending this one through which it
|
||||
* can query and retrieve specific data from each questiontype as required.
|
||||
*
|
||||
* Each questiontype may additionally respond directly to the privacy API
|
||||
* if it also impleents the \core_privacay\local\request\plugin\provider
|
||||
* interface directly.
|
||||
*
|
||||
* Care should be taken when extending this provider to not conflict with
|
||||
* the \core_privacay\local\request\plugin\provider interface.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
interface subsystem_provider extends \core_privacy\local\request\shared_data_provider {
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file contains the \core_privacy\local\request\shared_data_provider interface to describe
|
||||
* a class which provides data in some form.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
*
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\local\request;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The shared_data_provider interface is used to describe a provider which
|
||||
* services user requests between components and and other components.
|
||||
*
|
||||
* This includes communication between subplugin, subsystems, and plugins
|
||||
* which are designed to interact closely with subsystems.
|
||||
*
|
||||
* It does not define a specific way of doing so and different types of
|
||||
* data will need to extend this interface in order to define their own
|
||||
* contract.
|
||||
*
|
||||
* It should not be implemented directly, but should be extended by other
|
||||
* interfaces in core.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
*/
|
||||
interface shared_data_provider extends data_provider {
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file contains the \core_privacy\local\request\subsystem\plugin_provider interface to describe
|
||||
* a class which provides data in some form for a subsystem.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\local\request\subsystem;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The plugin_provider interface for subsystems which provide data directly to a plugin.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
*/
|
||||
interface plugin_provider extends \core_privacy\local\request\shared_data_provider {
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file contains the \core_privacy\local\request\subsystem\provider interface to describe
|
||||
* a class which provides data in some form for a subsystem.
|
||||
*
|
||||
* Plugins should implement this if they directly store any personal information.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\local\request\subsystem;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The provider interface for plugins which provide data from a subsystem
|
||||
* directly to the Privacy subsystem.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
*/
|
||||
interface provider extends \core_privacy\local\request\core_user_data_provider {
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file contains the core_privacy\local\request helper.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\local\request;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* A class containing a set of data transformations for core data types.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class transform {
|
||||
/**
|
||||
* Translate a userid into the standard user format for exports.
|
||||
*
|
||||
* We have not determined if we will do this or not, but we provide the functionality and encourgae people to use
|
||||
* it so that it can be retrospectively fitted if required.
|
||||
*
|
||||
* @param int $userid the userid to translate
|
||||
* @return mixed
|
||||
*/
|
||||
public static function user(int $userid) {
|
||||
// For the moment we do not think we should transform as this reveals information about other users.
|
||||
// However this function is implemented should the need arise in the future.
|
||||
return $userid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate a unix timestamp into a datetime string.
|
||||
*
|
||||
* @param int $datetime the unixtimestamp to translate.
|
||||
* @return string The translated string.
|
||||
*/
|
||||
public static function datetime($datetime) {
|
||||
return userdate($datetime, get_string('strftimedaydatetime', 'langconfig'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate a unix timestamp into a date string.
|
||||
*
|
||||
* @param int $date the unixtimestamp to translate.
|
||||
* @return string The translated string.
|
||||
*/
|
||||
public static function date($date) {
|
||||
return userdate($date, get_string('strftimetime', 'langconfig'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate a bool or int (0/1) value into a translated yes/no string.
|
||||
*
|
||||
* @param bool $value The value to translate
|
||||
* @return string
|
||||
*/
|
||||
public static function yesno($value) {
|
||||
if ($value) {
|
||||
return get_string('yes');
|
||||
} else {
|
||||
return get_string('no');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file contains the \core_privacy\local\request\user_preference_provider interface to describe
|
||||
* a class which provides preference data in some form to core.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\local\request;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The user_preference_provider interface is an interface designed to be
|
||||
* implemented by components directly to describe a case where that
|
||||
* component is responsible for storing some form of system-wide user
|
||||
* preference.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
interface user_preference_provider extends core_data_provider {
|
||||
|
||||
/**
|
||||
* Export all user preferences for the plugin.
|
||||
*
|
||||
* @param int $userid The userid of the user whose data is to be exported.
|
||||
*/
|
||||
public static function export_user_preferences(int $userid);
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file contains the interface required to implmeent a content writer.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\local\request;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The writer factory class used to fetch and work with the content_writer.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class writer {
|
||||
/**
|
||||
* @var writer The singleton instance of this writer.
|
||||
*/
|
||||
protected static $instance = null;
|
||||
|
||||
/**
|
||||
* @var content_writer The current content_writer instance.
|
||||
*/
|
||||
protected $realwriter = null;
|
||||
|
||||
/**
|
||||
* Constructor for the content writer.
|
||||
*
|
||||
* Protected to prevent direct instantiation.
|
||||
*/
|
||||
protected function __construct() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton to return or create and return a copy of a content_writer.
|
||||
*
|
||||
* @return content_writer
|
||||
*/
|
||||
protected function get_writer_instance() : content_writer {
|
||||
if (null === $this->realwriter) {
|
||||
if (PHPUNIT_TEST) {
|
||||
$this->realwriter = new \core_privacy\tests\request\content_writer(static::instance());
|
||||
} else {
|
||||
$this->realwriter = new moodle_content_writer(static::instance());
|
||||
}
|
||||
}
|
||||
|
||||
return $this->realwriter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance of
|
||||
*/
|
||||
protected static final function instance() {
|
||||
if (null === self::$instance) {
|
||||
self::$instance = new static();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the writer and content_writer.
|
||||
*/
|
||||
public static final function reset() {
|
||||
static::$instance = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide an instance of the writer with the specified context applied.
|
||||
*
|
||||
* @param \context $context The context to apply
|
||||
* @return content_writer The content_writer
|
||||
*/
|
||||
public static function with_context(\context $context) : content_writer {
|
||||
return static::instance()
|
||||
->get_writer_instance()
|
||||
->set_context($context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the specified user preference.
|
||||
*
|
||||
* @param string $component The name of the component.
|
||||
* @param string $key The name of th key to be exported.
|
||||
* @param string $value The value of the preference
|
||||
* @param string $description A description of the value
|
||||
* @return content_writer
|
||||
*/
|
||||
public static function export_user_preference(
|
||||
string $component,
|
||||
string $key,
|
||||
string $value,
|
||||
string $description
|
||||
) : content_writer {
|
||||
return static::with_context(\context_system::instance())
|
||||
->export_user_preference($component, $key, $value, $description);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Testcase for providers implementing parts of the core_privacy subsystem.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_privacy\tests;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
/**
|
||||
* Testcase for providers implementing parts of the core_privacy subsystem.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
abstract class provider_testcase extends \advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test tearDown.
|
||||
*/
|
||||
public function tearDown() {
|
||||
\core_privacy\local\request\writer::reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Export all data for a component for the specified user.
|
||||
*
|
||||
* @param int $userid The userid of the user to fetch.
|
||||
* @param string $component The component to get context data for.
|
||||
* @return \core_privacy\local\request\contextlist
|
||||
*/
|
||||
public function get_contexts_for_userid(int $userid, string $component) {
|
||||
$classname = $this->get_provider_classname($component);
|
||||
|
||||
return $classname::get_contexts_for_userid($userid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export all data for a component for the specified user.
|
||||
*
|
||||
* @param int $userid The userid of the user to fetch.
|
||||
* @param string $component The component to get export data for.
|
||||
*/
|
||||
public function export_all_data_for_user(int $userid, string $component) {
|
||||
$contextlist = $this->get_contexts_for_userid($userid, $component);
|
||||
|
||||
$approvedcontextlist = new \core_privacy\tests\request\approved_contextlist(
|
||||
\core_user::get_user($userid),
|
||||
$component,
|
||||
$contextlist->get_contextids()
|
||||
);
|
||||
|
||||
$classname = $this->get_provider_classname($component);
|
||||
$classname::export_user_data($approvedcontextlist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export all daa within a context for a component for the specified user.
|
||||
*
|
||||
* @param int $userid The userid of the user to fetch.
|
||||
* @param \context $context The context to export data for.
|
||||
* @param string $component The component to get export data for.
|
||||
*/
|
||||
public function export_context_data_for_user(int $userid, \context $context, string $component) {
|
||||
$contextlist = new \core_privacy\tests\request\approved_contextlist(
|
||||
\core_user::get_user($userid),
|
||||
$component,
|
||||
[$context->id]
|
||||
);
|
||||
|
||||
$classname = $this->get_provider_classname($component);
|
||||
$classname::export_user_data($contextlist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the classname and ensure that it is a provider.
|
||||
*
|
||||
* @param string $component The classname.
|
||||
* @return string
|
||||
*/
|
||||
protected function get_provider_classname($component) {
|
||||
$classname = "\\${component}\\privacy\\provider";
|
||||
|
||||
if (!class_exists($classname)) {
|
||||
throw new \coding_exception("{$component} does not implement any provider");
|
||||
}
|
||||
|
||||
$rc = new \ReflectionClass($classname);
|
||||
if (!$rc->implementsInterface(\core_privacy\local\metadata\provider::class)) {
|
||||
throw new \coding_exception("{$component} does not implement metadata provider");
|
||||
}
|
||||
|
||||
if (!$rc->implementsInterface(\core_privacy\local\request\core_user_data_provider::class)) {
|
||||
throw new \coding_exception("{$component} does not declare that it provides any user data");
|
||||
}
|
||||
|
||||
return $classname;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Approved result set for unit testing.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_privacy\tests\request;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Privacy Fetch Result Set.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class approved_contextlist extends \core_privacy\local\request\approved_contextlist {
|
||||
/**
|
||||
* Add a single context to this approved_contextlist.
|
||||
*
|
||||
* @param \context $context The context to be added.
|
||||
* @return $this
|
||||
*/
|
||||
public function add_context(\context $context) {
|
||||
return $this->add_context_by_id($context->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a single context to this approved_contextlist by it's ID.
|
||||
*
|
||||
* @param int $contextid The context to be added.
|
||||
* @return $this
|
||||
*/
|
||||
public function add_context_by_id($contextid) {
|
||||
return $this->set_contextids(array_merge($this->get_contextids(), [$contextid]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a set of contexts to this approved_contextlist.
|
||||
*
|
||||
* @param \context[] $contexts The contexts to be added.
|
||||
* @return $this
|
||||
*/
|
||||
public function add_contexts(array $contexts) {
|
||||
foreach ($contexts as $context) {
|
||||
$this->add_context($context);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a set of contexts to this approved_contextlist by ID.
|
||||
*
|
||||
* @param int[] $contexts The contexts to be added.
|
||||
* @return $this
|
||||
*/
|
||||
public function add_contexts_by_id(array $contexts) {
|
||||
foreach ($contexts as $contextid) {
|
||||
$this->add_context_by_id($contextid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,484 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file contains the moodle format implementation of the content writer.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_privacy\tests\request;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* An implementation of the content_writer for use in unit tests.
|
||||
*
|
||||
* This implementation does not export any data but instead stores it in
|
||||
* structures within the instance which can be easily queried for use
|
||||
* during unit tests.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class content_writer implements \core_privacy\local\request\content_writer {
|
||||
/**
|
||||
* @var \context The context currently being exported.
|
||||
*/
|
||||
protected $context = null;
|
||||
|
||||
/**
|
||||
* @var array The collection of metadata which has been exported.
|
||||
*/
|
||||
protected $metadata = [];
|
||||
|
||||
/**
|
||||
* @var array The data which has been exported.
|
||||
*/
|
||||
protected $data = [];
|
||||
|
||||
/**
|
||||
* @var array The related data which has been exported.
|
||||
*/
|
||||
protected $relateddata = [];
|
||||
|
||||
/**
|
||||
* @var array The list of stored files which have been exported.
|
||||
*/
|
||||
protected $files = [];
|
||||
|
||||
/**
|
||||
* @var array The custom files which have been exported.
|
||||
*/
|
||||
protected $customfiles = [];
|
||||
|
||||
/**
|
||||
* @var array The site-wide user preferences which have been exported.
|
||||
*/
|
||||
protected $userprefs = [];
|
||||
|
||||
/**
|
||||
* Whether any data has been exported at all within the current context.
|
||||
*/
|
||||
public function has_any_data() {
|
||||
$hasdata = !empty($this->data[$this->context->id]);
|
||||
$hasrelateddata = !empty($this->relateddata[$this->context->id]);
|
||||
$hasmetadata = !empty($this->metadata[$this->context->id]);
|
||||
$hasfiles = !empty($this->files[$this->context->id]);
|
||||
$hascustomfiles = !empty($this->customfiles[$this->context->id]);
|
||||
$hasuserprefs = !empty($this->userprefs);
|
||||
|
||||
return $hasdata || $hasrelateddata || $hasmetadata || $hasfiles || $hascustomfiles || $hasuserprefs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for the content writer.
|
||||
*
|
||||
* Note: The writer_factory must be passed.
|
||||
* @param \core_privacy\local\request\writer $writer The writer factory.
|
||||
*/
|
||||
public function __construct(\core_privacy\local\request\writer $writer) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the context for the current item being processed.
|
||||
*
|
||||
* @param \context $context The context to use
|
||||
*/
|
||||
public function set_context(\context $context) : \core_privacy\local\request\content_writer {
|
||||
$this->context = $context;
|
||||
|
||||
if (empty($this->data[$this->context->id])) {
|
||||
$this->data[$this->context->id] = [];
|
||||
}
|
||||
|
||||
if (empty($this->relateddata[$this->context->id])) {
|
||||
$this->relateddata[$this->context->id] = [];
|
||||
}
|
||||
|
||||
if (empty($this->metadata[$this->context->id])) {
|
||||
$this->metadata[$this->context->id] = [];
|
||||
}
|
||||
|
||||
if (empty($this->files[$this->context->id])) {
|
||||
$this->files[$this->context->id] = [];
|
||||
}
|
||||
|
||||
if (empty($this->customfiles[$this->context->id])) {
|
||||
$this->customfiles[$this->context->id] = [];
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current context.
|
||||
*
|
||||
* @return \context
|
||||
*/
|
||||
public function get_current_context() : \context {
|
||||
return $this->context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the supplied data within the current context, at the supplied subcontext.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @param \stdClass $data The data to be exported
|
||||
*/
|
||||
public function export_data(array $subcontext, \stdClass $data) : \core_privacy\local\request\content_writer {
|
||||
array_push($subcontext, 'data');
|
||||
|
||||
$finalcontent = $data;
|
||||
|
||||
while ($pathtail = array_pop($subcontext)) {
|
||||
$finalcontent = [
|
||||
$pathtail => $finalcontent,
|
||||
];
|
||||
}
|
||||
|
||||
$this->data[$this->context->id] = array_replace_recursive($this->data[$this->context->id], $finalcontent);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data within the subcontext.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @return array The metadata as a series of keys to value + descrition objects.
|
||||
*/
|
||||
public function get_data(array $subcontext = []) {
|
||||
$basepath = $this->data[$this->context->id];
|
||||
while ($subpath = array_shift($subcontext)) {
|
||||
if (isset($basepath[$subpath])) {
|
||||
$basepath = $basepath[$subpath];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($basepath['data'])) {
|
||||
return $basepath['data'];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Export metadata about the supplied subcontext.
|
||||
*
|
||||
* Metadata consists of a key/value pair and a description of the value.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @param string $key The metadata name.
|
||||
* @param string $value The metadata value.
|
||||
* @param string $description The description of the value.
|
||||
* @return $this
|
||||
*/
|
||||
public function export_metadata(array $subcontext,
|
||||
string $key,
|
||||
$value,
|
||||
string $description
|
||||
) : \core_privacy\local\request\content_writer {
|
||||
array_push($subcontext, 'metadata');
|
||||
|
||||
$finalcontent = [
|
||||
$key => (object) [
|
||||
'value' => $value,
|
||||
'description' => $description,
|
||||
],
|
||||
];
|
||||
|
||||
while ($pathtail = array_pop($subcontext)) {
|
||||
$finalcontent = [
|
||||
$pathtail => $finalcontent,
|
||||
];
|
||||
}
|
||||
|
||||
$this->metadata[$this->context->id] = array_replace_recursive($this->metadata[$this->context->id], $finalcontent);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all metadata within the subcontext.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @return array The metadata as a series of keys to value + descrition objects.
|
||||
*/
|
||||
public function get_all_metadata(array $subcontext = []) {
|
||||
$basepath = $this->metadata[$this->context->id];
|
||||
while ($subpath = array_shift($subcontext)) {
|
||||
if (isset($basepath[$subpath])) {
|
||||
$basepath = $basepath[$subpath];
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($basepath['metadata'])) {
|
||||
return $basepath['metadata'];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specified metadata within the subcontext.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @param string $key The metadata to be fetched within the context + subcontext.
|
||||
* @param boolean $valueonly Whether to fetch only the value, rather than the value + description.
|
||||
* @return array The metadata as a series of keys to value + descrition objects.
|
||||
*/
|
||||
public function get_metadata(array $subcontext = [], $key, $valueonly = true) {
|
||||
$data = $this->get_all_metadata($subcontext);
|
||||
|
||||
if (!isset($data[$key])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$metadata = $data[$key];
|
||||
if ($valueonly) {
|
||||
return $metadata->value;
|
||||
} else {
|
||||
return $metadata;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Export a piece of related data.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @param string $name The name of the file to be exported.
|
||||
* @param \stdClass $data The related data to export.
|
||||
*/
|
||||
public function export_related_data(array $subcontext, $name, $data) : \core_privacy\local\request\content_writer {
|
||||
array_push($subcontext, $name);
|
||||
array_push($subcontext, 'data');
|
||||
|
||||
$finalcontent = $data;
|
||||
|
||||
while ($pathtail = array_pop($subcontext)) {
|
||||
$finalcontent = [
|
||||
$pathtail => $finalcontent,
|
||||
];
|
||||
}
|
||||
|
||||
$this->relateddata[$this->context->id] = array_replace_recursive($this->relateddata[$this->context->id], $finalcontent);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data within the subcontext.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @param string $filename The name of the intended filename.
|
||||
* @return array The metadata as a series of keys to value + descrition objects.
|
||||
*/
|
||||
public function get_related_data(array $subcontext = [], $filename) {
|
||||
$basepath = $this->relateddata[$this->context->id];
|
||||
$subcontext[] = $filename;
|
||||
while ($subpath = array_shift($subcontext)) {
|
||||
if (isset($basepath[$subpath])) {
|
||||
$basepath = $basepath[$subpath];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($basepath['data'])) {
|
||||
return $basepath['data'];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Export a piece of data in a custom format.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @param string $filename The name of the file to be exported.
|
||||
* @param string $filecontent The content to be exported.
|
||||
*/
|
||||
public function export_custom_file(array $subcontext, $filename, $filecontent) : \core_privacy\local\request\content_writer {
|
||||
$filename = clean_param($filename, PARAM_FILE);
|
||||
|
||||
$finalcontent = [
|
||||
$filename => $filecontent,
|
||||
];
|
||||
while ($pathtail = array_pop($subcontext)) {
|
||||
$finalcontent = [
|
||||
$pathtail => $finalcontent,
|
||||
];
|
||||
}
|
||||
|
||||
$this->customfiles[$this->context->id] = array_replace_recursive($this->customfiles[$this->context->id], $finalcontent);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specified custom file within the subcontext.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @param string $filename The name of the file to be fetched within the context + subcontext.
|
||||
* @return string The content of the file.
|
||||
*/
|
||||
public function get_custom_file(array $subcontext = [], $filename = null) {
|
||||
if (!empty($filename)) {
|
||||
array_push($subcontext, $filename);
|
||||
}
|
||||
|
||||
$basepath = $this->customfiles[$this->context->id];
|
||||
while ($subpath = array_shift($subcontext)) {
|
||||
if (isset($basepath[$subpath])) {
|
||||
$basepath = $basepath[$subpath];
|
||||
}
|
||||
}
|
||||
|
||||
return $basepath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a text area by processing pluginfile URLs within it.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @param string $component The name of the component that the files belong to.
|
||||
* @param string $filearea The filearea within that component.
|
||||
* @param string $itemid Which item those files belong to.
|
||||
* @param string $text The text to be processed
|
||||
* @return string The processed string
|
||||
*/
|
||||
public function rewrite_pluginfile_urls(array $subcontext, $component, $filearea, $itemid, $text) : string {
|
||||
return str_replace('@@PLUGINFILE@@/', 'files/', $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export all files within the specified component, filearea, itemid combination.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @param string $component The name of the component that the files belong to.
|
||||
* @param string $filearea The filearea within that component.
|
||||
* @param string $itemid Which item those files belong to.
|
||||
*/
|
||||
public function export_area_files(array $subcontext, $component, $filearea, $itemid) : \core_privacy\local\request\content_writer {
|
||||
$fs = get_file_storage();
|
||||
$files = $fs->get_area_files($this->context->id, $component, $filearea, $itemid);
|
||||
foreach ($files as $file) {
|
||||
$this->export_file($subcontext, $file);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the specified file in the target location.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @param \stored_file $file The file to be exported.
|
||||
*/
|
||||
public function export_file(array $subcontext, \stored_file $file) : \core_privacy\local\request\content_writer {
|
||||
if (!$file->is_directory()) {
|
||||
$subcontextextra = [
|
||||
'files',
|
||||
$file->get_filepath(),
|
||||
];
|
||||
$newsubcontext = array_merge($subcontext, $subcontextextra);
|
||||
|
||||
$finalcontent = [
|
||||
$file,
|
||||
];
|
||||
while ($pathtail = array_pop($subcontext)) {
|
||||
$finalcontent = [
|
||||
$pathtail => $finalcontent,
|
||||
];
|
||||
}
|
||||
|
||||
$this->customfiles[$this->context->id] = array_replace_recursive($this->customfiles[$this->context->id], $finalcontent);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all files in the specfied subcontext.
|
||||
*
|
||||
* @param array $subcontext The location within the current context that this data belongs.
|
||||
* @return \stored_file[] The list of stored_files in this context + subcontext.
|
||||
*/
|
||||
public function get_files(array $subcontext = []) {
|
||||
$basepath = $this->files[$this->context->id];
|
||||
while ($subpath = array_shift($subcontext)) {
|
||||
if (isset($basepath[$subpath])) {
|
||||
$basepath = $basepath[$subpath];
|
||||
}
|
||||
}
|
||||
|
||||
return $basepath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the specified user preference.
|
||||
*
|
||||
* @param string $component The name of the component.
|
||||
* @param string $key The name of th key to be exported.
|
||||
* @param string $value The value of the preference
|
||||
* @param string $description A description of the value
|
||||
* @return \core_privacy\local\request\content_writer
|
||||
*/
|
||||
public function export_user_preference(
|
||||
string $component,
|
||||
string $key,
|
||||
string $value,
|
||||
string $description
|
||||
) : \core_privacy\local\request\content_writer {
|
||||
if (!isset($this->userprefs[$component])) {
|
||||
$this->userprefs[$component] = (object) [];
|
||||
}
|
||||
|
||||
$this->userprefs[$component]->$key = (object) [
|
||||
'value' => $value,
|
||||
'description' => $description,
|
||||
];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all user preferences for the specified component.
|
||||
*
|
||||
* @param string $component The name of the component.
|
||||
* @return \stdClass
|
||||
*/
|
||||
public function get_user_preferences(string $component) {
|
||||
if (isset($this->userprefs[$component])) {
|
||||
return $this->userprefs[$component];
|
||||
} else {
|
||||
return (object) [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform any required finalisation steps and return the location of the finalised export.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function finalise_content() : string {
|
||||
return 'mock_path';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Unit Tests for the approved contextlist Class
|
||||
*
|
||||
* @package core_privacy
|
||||
* @category test
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
use \core_privacy\local\request\approved_contextlist;
|
||||
|
||||
/**
|
||||
* Tests for the \core_privacy API's approved contextlist functionality.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class approved_contextlist_test extends advanced_testcase {
|
||||
/**
|
||||
* The approved contextlist should not be modifiable once set.
|
||||
*/
|
||||
public function test_default_values_set() {
|
||||
$testuser = \core_user::get_user_by_username('admin');
|
||||
$contextids = [3, 2, 1];
|
||||
$component = 'core_privacy';
|
||||
|
||||
$uit = new approved_contextlist($testuser, $component, $contextids);
|
||||
|
||||
$this->assertEquals($testuser, $uit->get_user());
|
||||
$this->assertEquals($component, $uit->get_component());
|
||||
$result = $uit->get_contextids();
|
||||
|
||||
// Note: Array order is not guaranteed and should not matter.
|
||||
foreach ($contextids as $contextid) {
|
||||
$this->assertNotFalse(array_search($contextid, $result));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Collection unit tests.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @category test
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
use \core_privacy\local\metadata\collection;
|
||||
use \core_privacy\local\metadata\types;
|
||||
|
||||
/**
|
||||
* Tests for the \core_privacy API's collection functionality.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class core_privacy_metadata_collection extends advanced_testcase {
|
||||
|
||||
|
||||
/**
|
||||
* Test that adding an unknown type causes the type to be added to the collection.
|
||||
*/
|
||||
public function test_add_type_generic_type() {
|
||||
$collection = new collection('core_privacy');
|
||||
|
||||
// Mock a new types\type.
|
||||
$mockedtype = $this->createMock(types\type::class);
|
||||
$collection->add_type($mockedtype);
|
||||
|
||||
$items = $collection->get_collection();
|
||||
$this->assertCount(1, $items);
|
||||
$this->assertEquals($mockedtype, reset($items));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that adding a known type works as anticipated.
|
||||
*/
|
||||
public function test_add_type_known_type() {
|
||||
$collection = new collection('core_privacy');
|
||||
|
||||
$linked = new types\subsystem_link('example', 'langstring');
|
||||
$collection->add_type($linked);
|
||||
|
||||
$items = $collection->get_collection();
|
||||
$this->assertCount(1, $items);
|
||||
$this->assertEquals($linked, reset($items));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that adding multiple types returns them all.
|
||||
*/
|
||||
public function test_add_type_multiple() {
|
||||
$collection = new collection('core_privacy');
|
||||
|
||||
$a = new types\subsystem_link('example', 'langstring');
|
||||
$collection->add_type($a);
|
||||
|
||||
$b = new types\subsystem_link('example', 'langstring');
|
||||
$collection->add_type($b);
|
||||
|
||||
$items = $collection->get_collection();
|
||||
$this->assertCount(2, $items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the add_database_table function adds a database table.
|
||||
*/
|
||||
public function test_add_database_table() {
|
||||
$collection = new collection('core_privacy');
|
||||
|
||||
$name = 'example';
|
||||
$fields = ['field' => 'description'];
|
||||
$summary = 'summarisation';
|
||||
|
||||
$collection->add_database_table($name, $fields, $summary);
|
||||
|
||||
$items = $collection->get_collection();
|
||||
$this->assertCount(1, $items);
|
||||
$item = reset($items);
|
||||
$this->assertInstanceOf(types\database_table::class, $item);
|
||||
$this->assertEquals($name, $item->get_name());
|
||||
$this->assertEquals($fields, $item->get_privacy_fields());
|
||||
$this->assertEquals($summary, $item->get_summary());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the add_user_preference function adds a single user preference.
|
||||
*/
|
||||
public function test_add_user_preference() {
|
||||
$collection = new collection('core_privacy');
|
||||
|
||||
$name = 'example';
|
||||
$summary = 'summarisation';
|
||||
|
||||
$collection->add_user_preference($name, $summary);
|
||||
|
||||
$items = $collection->get_collection();
|
||||
$this->assertCount(1, $items);
|
||||
$item = reset($items);
|
||||
$this->assertInstanceOf(types\user_preference::class, $item);
|
||||
$this->assertEquals($name, $item->get_name());
|
||||
$this->assertEquals($summary, $item->get_summary());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the link_external_location function links an external location.
|
||||
*/
|
||||
public function test_link_external_location() {
|
||||
$collection = new collection('core_privacy');
|
||||
|
||||
$name = 'example';
|
||||
$fields = ['field' => 'description'];
|
||||
$summary = 'summarisation';
|
||||
|
||||
$collection->link_external_location($name, $fields, $summary);
|
||||
|
||||
$items = $collection->get_collection();
|
||||
$this->assertCount(1, $items);
|
||||
$item = reset($items);
|
||||
$this->assertInstanceOf(types\external_location::class, $item);
|
||||
$this->assertEquals($name, $item->get_name());
|
||||
$this->assertEquals($fields, $item->get_privacy_fields());
|
||||
$this->assertEquals($summary, $item->get_summary());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the link_subsystem function links the subsystem.
|
||||
*/
|
||||
public function test_link_subsystem() {
|
||||
$collection = new collection('core_privacy');
|
||||
|
||||
$name = 'example';
|
||||
$summary = 'summarisation';
|
||||
|
||||
$collection->link_subsystem($name, $summary);
|
||||
|
||||
$items = $collection->get_collection();
|
||||
$this->assertCount(1, $items);
|
||||
$item = reset($items);
|
||||
$this->assertInstanceOf(types\subsystem_link::class, $item);
|
||||
$this->assertEquals($name, $item->get_name());
|
||||
$this->assertEquals($summary, $item->get_summary());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the link_plugintype function links the plugin.
|
||||
*/
|
||||
public function test_link_plugintype() {
|
||||
$collection = new collection('core_privacy');
|
||||
|
||||
$name = 'example';
|
||||
$summary = 'summarisation';
|
||||
|
||||
$collection->link_plugintype($name, $summary);
|
||||
|
||||
$items = $collection->get_collection();
|
||||
$this->assertCount(1, $items);
|
||||
$item = reset($items);
|
||||
$this->assertInstanceOf(types\plugintype_link::class, $item);
|
||||
$this->assertEquals($name, $item->get_name());
|
||||
$this->assertEquals($summary, $item->get_summary());
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider to supply a list of valid components.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function component_list_provider() {
|
||||
return [
|
||||
['core_privacy'],
|
||||
['mod_forum'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that we can get the component correctly.
|
||||
*
|
||||
* The component will be used for string translations.
|
||||
*
|
||||
* @dataProvider component_list_provider
|
||||
* @param string $component The component to test
|
||||
*/
|
||||
public function test_get_component($component) {
|
||||
$collection = new collection($component);
|
||||
|
||||
$this->assertEquals($component, $collection->get_component());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Unit Tests for the abstract contextlist Class
|
||||
*
|
||||
* @package core_privacy
|
||||
* @category test
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
use \core_privacy\local\request\contextlist_base;
|
||||
|
||||
/**
|
||||
* Tests for the \core_privacy API's contextlist base functionality.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class contextlist_base_test extends advanced_testcase {
|
||||
/**
|
||||
* Ensure that get_contextids returns the list of unique contextids.
|
||||
*
|
||||
* @dataProvider get_contextids_provider
|
||||
* @param array $input List of context IDs
|
||||
* @param array $expected list of contextids
|
||||
* @param int $count Expected count
|
||||
*/
|
||||
public function test_get_contextids($input, $expected, $count) {
|
||||
$uit = new test_contextlist_base();
|
||||
$uit->set_contextids($input);
|
||||
|
||||
$result = $uit->get_contextids();
|
||||
$this->assertCount($count, $result);
|
||||
|
||||
// Note: Array order is not guaranteed and should not matter.
|
||||
foreach ($expected as $contextid) {
|
||||
$this->assertNotFalse(array_search($contextid, $result));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provider for the list of contextids.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_contextids_provider() {
|
||||
return [
|
||||
'basic' => [
|
||||
[1, 2, 3, 4, 5],
|
||||
[1, 2, 3, 4, 5],
|
||||
5,
|
||||
],
|
||||
'duplicates' => [
|
||||
[1, 1, 2, 2, 3, 4, 5],
|
||||
[1, 2, 3, 4, 5],
|
||||
5,
|
||||
],
|
||||
'Mixed order with duplicates' => [
|
||||
[5, 4, 2, 5, 4, 1, 3, 4, 1, 5, 5, 5, 2, 4, 1, 2],
|
||||
[1, 2, 3, 4, 5],
|
||||
5,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that get_contexts returns the correct list of contexts.
|
||||
*/
|
||||
public function test_get_contexts() {
|
||||
global $DB;
|
||||
|
||||
$contexts = [];
|
||||
$contexts[] = \context_system::instance();
|
||||
$contexts[] = \context_user::instance(\core_user::get_user_by_username('admin')->id);
|
||||
|
||||
$ids = [];
|
||||
foreach ($contexts as $context) {
|
||||
$ids[] = $context->id;
|
||||
}
|
||||
|
||||
$uit = new test_contextlist_base();
|
||||
$uit->set_contextids($ids);
|
||||
|
||||
$result = $uit->get_contexts();
|
||||
$this->assertCount(count($contexts), $result);
|
||||
foreach ($contexts as $context) {
|
||||
$this->assertNotFalse(array_search($context, $result));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the contextlist_base is countable.
|
||||
*
|
||||
* @dataProvider get_contextids_provider
|
||||
* @param array $input List of context IDs
|
||||
* @param array $expected list of contextids
|
||||
* @param int $count Expected count
|
||||
*/
|
||||
public function test_countable($input, $expected, $count) {
|
||||
$uit = new test_contextlist_base();
|
||||
$uit->set_contextids($input);
|
||||
|
||||
$this->assertCount($count, $uit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the contextlist_base iterates over the set of contexts.
|
||||
*/
|
||||
public function test_context_iteration() {
|
||||
global $DB;
|
||||
|
||||
$allcontexts = $DB->get_records('context');
|
||||
$contexts = [];
|
||||
foreach ($allcontexts as $context) {
|
||||
$contexts[] = \context::instance_by_id($context->id);
|
||||
}
|
||||
|
||||
$uit = new test_contextlist_base();
|
||||
$uit->set_contextids(array_keys($allcontexts));
|
||||
|
||||
foreach ($uit as $key => $context) {
|
||||
$this->assertNotFalse(array_search($context, $contexts));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A test class extending the contextlist_base allowing setting of the
|
||||
* contextids.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class test_contextlist_base extends contextlist_base {
|
||||
/**
|
||||
* Set the contextids for the test class.
|
||||
*
|
||||
* @param int[] $contexids The list of contextids to use.
|
||||
*/
|
||||
public function set_contextids(array $contextids) {
|
||||
parent::set_contextids($contextids);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Unit Tests for a the collection of contextlists class
|
||||
*
|
||||
* @package core_privacy
|
||||
* @category test
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
use \core_privacy\local\request\contextlist_collection;
|
||||
use \core_privacy\local\request\contextlist;
|
||||
use \core_privacy\local\request\approved_contextlist;
|
||||
|
||||
/**
|
||||
* Tests for the \core_privacy API's contextlist collection functionality.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class contextlist_collection_test extends advanced_testcase {
|
||||
/**
|
||||
* A contextlist_collection should support the contextlist type.
|
||||
*/
|
||||
public function test_supports_contextlist() {
|
||||
$uit = new contextlist_collection(1);
|
||||
$contextlist = new contextlist();
|
||||
$contextlist->set_component('core_privacy');
|
||||
$uit->add_contextlist($contextlist);
|
||||
|
||||
$this->assertCount(1, $uit->get_contextlists());
|
||||
}
|
||||
|
||||
/**
|
||||
* A contextlist_collection should support the approved_contextlist type.
|
||||
*/
|
||||
public function test_supports_approved_contextlist() {
|
||||
$uit = new contextlist_collection(1);
|
||||
$testuser = \core_user::get_user_by_username('admin');
|
||||
$contextids = [3, 2, 1];
|
||||
$uit->add_contextlist(new approved_contextlist($testuser, 'core_privacy', $contextids));
|
||||
|
||||
$this->assertCount(1, $uit->get_contextlists());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that get_contextlist_for_component returns the correct contextlist.
|
||||
*/
|
||||
public function test_get_contextlist_for_component() {
|
||||
$uit = new contextlist_collection(1);
|
||||
$coretests = new contextlist();
|
||||
$coretests->set_component('core_tests');
|
||||
$uit->add_contextlist($coretests);
|
||||
|
||||
$coreprivacy = new contextlist();
|
||||
$coreprivacy->set_component('core_privacy');
|
||||
$uit->add_contextlist($coreprivacy);
|
||||
|
||||
// Note: This uses assertSame rather than assertEquals.
|
||||
// The former checks the actual object, whilst assertEquals only checks that they look the same.
|
||||
$this->assertSame($coretests, $uit->get_contextlist_for_component('core_tests'));
|
||||
$this->assertSame($coreprivacy, $uit->get_contextlist_for_component('core_privacy'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that get_contextlist_for_component does not die horribly when querying a non-existent component.
|
||||
*/
|
||||
public function test_get_contextlist_for_component_not_found() {
|
||||
$uit = new contextlist_collection(1);
|
||||
|
||||
$this->assertNull($uit->get_contextlist_for_component('core_tests'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that a duplicate contextlist in the collection throws an Exception.
|
||||
*/
|
||||
public function test_duplicate_addition_throws() {
|
||||
$uit = new contextlist_collection(1);
|
||||
|
||||
$coretests = new contextlist();
|
||||
$coretests->set_component('core_tests');
|
||||
$uit->add_contextlist($coretests);
|
||||
|
||||
$this->expectException('moodle_exception');
|
||||
$uit->add_contextlist($coretests);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the contextlist_collection is countable.
|
||||
*/
|
||||
public function test_countable() {
|
||||
$uit = new contextlist_collection(1);
|
||||
|
||||
$contextlist = new contextlist();
|
||||
$contextlist->set_component('test_example');
|
||||
$uit->add_contextlist($contextlist);
|
||||
|
||||
$contextlist = new contextlist();
|
||||
$contextlist->set_component('test_another');
|
||||
$uit->add_contextlist($contextlist);
|
||||
|
||||
$this->assertCount(2, $uit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the contextlist_collection iterates over the set of contextlists.
|
||||
*/
|
||||
public function test_iteration() {
|
||||
$uit = new contextlist_collection(1);
|
||||
|
||||
$testdata = [];
|
||||
|
||||
$component = 'test_example';
|
||||
$contextlist = new contextlist();
|
||||
$contextlist->set_component($component);
|
||||
$uit->add_contextlist($contextlist);
|
||||
$testdata[$component] = $contextlist;
|
||||
|
||||
$component = 'test_another';
|
||||
$contextlist = new contextlist();
|
||||
$contextlist->set_component($component);
|
||||
$uit->add_contextlist($contextlist);
|
||||
$testdata[$component] = $contextlist;
|
||||
|
||||
$component = 'test_third';
|
||||
$contextlist = new contextlist();
|
||||
$contextlist->set_component($component);
|
||||
$uit->add_contextlist($contextlist);
|
||||
$testdata[$component] = $contextlist;
|
||||
|
||||
foreach ($uit as $component => $list) {
|
||||
$this->assertEquals($testdata[$component], $list);
|
||||
}
|
||||
|
||||
$this->assertCount(3, $uit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the userid is correctly returned.
|
||||
*/
|
||||
public function test_get_userid() {
|
||||
$uit = new contextlist_collection(1);
|
||||
|
||||
$this->assertEquals(1, $uit->get_userid());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that an exception is thrown if a contextlist does not contain a component.
|
||||
*/
|
||||
public function test_add_without_component() {
|
||||
$uit = new contextlist_collection(1);
|
||||
|
||||
$this->expectException(moodle_exception::class);
|
||||
$uit->add_contextlist(new contextlist());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Unit Tests for the approved contextlist Class
|
||||
*
|
||||
* @package core_privacy
|
||||
* @category test
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
use \core_privacy\local\request\contextlist;
|
||||
|
||||
/**
|
||||
* Tests for the \core_privacy API's approved contextlist functionality.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class contextlist_test extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Ensure that valid SQL results in the relevant contexts being added.
|
||||
*/
|
||||
public function test_add_from_sql() {
|
||||
global $DB;
|
||||
|
||||
$sql = "SELECT c.id FROM {context} c";
|
||||
$params = [];
|
||||
$allcontexts = $DB->get_records_sql($sql, $params);
|
||||
|
||||
$uit = new contextlist();
|
||||
$uit->add_from_sql($sql, $params);
|
||||
|
||||
$this->assertCount(count($allcontexts), $uit);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Unit Tests for the request deletion criteria.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @category test
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
use \core_privacy\local\request\deletion_criteria;
|
||||
|
||||
/**
|
||||
* Tests for the \core_privacy API's request deletion criteria class.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class deletion_criteria_test extends advanced_testcase {
|
||||
/**
|
||||
* The get_context function should return the entered context.
|
||||
*/
|
||||
public function test_get_context() {
|
||||
$context = \context_system::instance();
|
||||
$uit = new deletion_criteria($context);
|
||||
$this->assertSame($context, $uit->get_context());
|
||||
}
|
||||
|
||||
/**
|
||||
* The get_context function should return the entered context.
|
||||
*/
|
||||
public function test_get_context_user_context() {
|
||||
$context = \context_user::instance(\core_user::get_user_by_username('admin')->id);
|
||||
$uit = new deletion_criteria($context);
|
||||
$this->assertSame($context, $uit->get_context());
|
||||
}
|
||||
}
|
||||
Vendored
BIN
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
@@ -0,0 +1,747 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Unit Tests for the Moodle Content Writer.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @category test
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
use \core_privacy\local\request\writer;
|
||||
use \core_privacy\local\request\moodle_content_writer;
|
||||
|
||||
/**
|
||||
* Tests for the \core_privacy API's moodle_content_writer functionality.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class moodle_content_writer_test extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test that exported data is saved correctly within the system context.
|
||||
*
|
||||
* @dataProvider export_data_provider
|
||||
* @param \stdClass $data Data
|
||||
*/
|
||||
public function test_export_data($data) {
|
||||
$context = \context_system::instance();
|
||||
$subcontext = [];
|
||||
|
||||
$writer = $this->get_writer_instance()
|
||||
->set_context($context)
|
||||
->export_data($subcontext, $data);
|
||||
|
||||
$fileroot = $this->fetch_exported_content($writer);
|
||||
|
||||
$contextpath = $this->get_context_path($context, $subcontext, 'data.json');
|
||||
$this->assertTrue($fileroot->hasChild($contextpath));
|
||||
|
||||
$json = $fileroot->getChild($contextpath)->getContent();
|
||||
$expanded = json_decode($json);
|
||||
$this->assertEquals($data, $expanded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that exported data is saved correctly for context/subcontext.
|
||||
*
|
||||
* @dataProvider export_data_provider
|
||||
* @param \stdClass $data Data
|
||||
*/
|
||||
public function test_export_data_different_context($data) {
|
||||
$context = \context_user::instance(\core_user::get_user_by_username('admin')->id);
|
||||
$subcontext = ['sub', 'context'];
|
||||
|
||||
$writer = $this->get_writer_instance()
|
||||
->set_context($context)
|
||||
->export_data($subcontext, $data);
|
||||
|
||||
$fileroot = $this->fetch_exported_content($writer);
|
||||
|
||||
$contextpath = $this->get_context_path($context, $subcontext, 'data.json');
|
||||
$this->assertTrue($fileroot->hasChild($contextpath));
|
||||
|
||||
$json = $fileroot->getChild($contextpath)->getContent();
|
||||
$expanded = json_decode($json);
|
||||
$this->assertEquals($data, $expanded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that exported is saved within the correct directory locations.
|
||||
*/
|
||||
public function test_export_data_writes_to_multiple_context() {
|
||||
$subcontext = ['sub', 'context'];
|
||||
|
||||
$systemcontext = \context_system::instance();
|
||||
$systemdata = (object) [
|
||||
'belongsto' => 'system',
|
||||
];
|
||||
$usercontext = \context_user::instance(\core_user::get_user_by_username('admin')->id);
|
||||
$userdata = (object) [
|
||||
'belongsto' => 'user',
|
||||
];
|
||||
|
||||
$writer = $this->get_writer_instance();
|
||||
|
||||
$writer
|
||||
->set_context($systemcontext)
|
||||
->export_data($subcontext, $systemdata);
|
||||
|
||||
$writer
|
||||
->set_context($usercontext)
|
||||
->export_data($subcontext, $userdata);
|
||||
|
||||
$fileroot = $this->fetch_exported_content($writer);
|
||||
|
||||
$contextpath = $this->get_context_path($systemcontext, $subcontext, 'data.json');
|
||||
$this->assertTrue($fileroot->hasChild($contextpath));
|
||||
|
||||
$json = $fileroot->getChild($contextpath)->getContent();
|
||||
$expanded = json_decode($json);
|
||||
$this->assertEquals($systemdata, $expanded);
|
||||
|
||||
$contextpath = $this->get_context_path($usercontext, $subcontext, 'data.json');
|
||||
$this->assertTrue($fileroot->hasChild($contextpath));
|
||||
|
||||
$json = $fileroot->getChild($contextpath)->getContent();
|
||||
$expanded = json_decode($json);
|
||||
$this->assertEquals($userdata, $expanded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that multiple writes to the same location cause the latest version to be written.
|
||||
*/
|
||||
public function test_export_data_multiple_writes_same_context() {
|
||||
$subcontext = ['sub', 'context'];
|
||||
|
||||
$systemcontext = \context_system::instance();
|
||||
$originaldata = (object) [
|
||||
'belongsto' => 'system',
|
||||
];
|
||||
|
||||
$newdata = (object) [
|
||||
'abc' => 'def',
|
||||
];
|
||||
|
||||
$writer = $this->get_writer_instance();
|
||||
|
||||
$writer
|
||||
->set_context($systemcontext)
|
||||
->export_data($subcontext, $originaldata);
|
||||
|
||||
$writer
|
||||
->set_context($systemcontext)
|
||||
->export_data($subcontext, $newdata);
|
||||
|
||||
$fileroot = $this->fetch_exported_content($writer);
|
||||
|
||||
$contextpath = $this->get_context_path($systemcontext, $subcontext, 'data.json');
|
||||
$this->assertTrue($fileroot->hasChild($contextpath));
|
||||
|
||||
$json = $fileroot->getChild($contextpath)->getContent();
|
||||
$expanded = json_decode($json);
|
||||
$this->assertEquals($newdata, $expanded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for exporting user data.
|
||||
*/
|
||||
public function export_data_provider() {
|
||||
return [
|
||||
'basic' => [
|
||||
(object) [
|
||||
'example' => (object) [
|
||||
'key' => 'value',
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that metadata can be set.
|
||||
*
|
||||
* @dataProvider export_metadata_provider
|
||||
* @param string $key Key
|
||||
* @param string $value Value
|
||||
* @param string $description Description
|
||||
*/
|
||||
public function test_export_metadata($key, $value, $description) {
|
||||
$context = \context_system::instance();
|
||||
$subcontext = ['a', 'b', 'c'];
|
||||
|
||||
$writer = $this->get_writer_instance()
|
||||
->set_context($context)
|
||||
->export_metadata($subcontext, $key, $value, $description);
|
||||
|
||||
$fileroot = $this->fetch_exported_content($writer);
|
||||
|
||||
$contextpath = $this->get_context_path($context, $subcontext, 'metadata.json');
|
||||
$this->assertTrue($fileroot->hasChild($contextpath));
|
||||
|
||||
$json = $fileroot->getChild($contextpath)->getContent();
|
||||
$expanded = json_decode($json);
|
||||
$this->assertTrue(isset($expanded->$key));
|
||||
$this->assertEquals($value, $expanded->$key->value);
|
||||
$this->assertEquals($description, $expanded->$key->description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that metadata can be set additively.
|
||||
*/
|
||||
public function test_export_metadata_additive() {
|
||||
$context = \context_system::instance();
|
||||
$subcontext = [];
|
||||
|
||||
$writer = $this->get_writer_instance();
|
||||
|
||||
$writer
|
||||
->set_context($context)
|
||||
->export_metadata($subcontext, 'firstkey', 'firstvalue', 'firstdescription');
|
||||
|
||||
$writer
|
||||
->set_context($context)
|
||||
->export_metadata($subcontext, 'secondkey', 'secondvalue', 'seconddescription');
|
||||
|
||||
$fileroot = $this->fetch_exported_content($writer);
|
||||
|
||||
$contextpath = $this->get_context_path($context, $subcontext, 'metadata.json');
|
||||
$this->assertTrue($fileroot->hasChild($contextpath));
|
||||
|
||||
$json = $fileroot->getChild($contextpath)->getContent();
|
||||
$expanded = json_decode($json);
|
||||
|
||||
$this->assertTrue(isset($expanded->firstkey));
|
||||
$this->assertEquals('firstvalue', $expanded->firstkey->value);
|
||||
$this->assertEquals('firstdescription', $expanded->firstkey->description);
|
||||
|
||||
$this->assertTrue(isset($expanded->secondkey));
|
||||
$this->assertEquals('secondvalue', $expanded->secondkey->value);
|
||||
$this->assertEquals('seconddescription', $expanded->secondkey->description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that metadata can be set additively.
|
||||
*/
|
||||
public function test_export_metadata_to_multiple_contexts() {
|
||||
$systemcontext = \context_system::instance();
|
||||
$usercontext = \context_user::instance(\core_user::get_user_by_username('admin')->id);
|
||||
$subcontext = [];
|
||||
|
||||
$writer = $this->get_writer_instance();
|
||||
|
||||
$writer
|
||||
->set_context($systemcontext)
|
||||
->export_metadata($subcontext, 'firstkey', 'firstvalue', 'firstdescription')
|
||||
->export_metadata($subcontext, 'secondkey', 'secondvalue', 'seconddescription');
|
||||
|
||||
$writer
|
||||
->set_context($usercontext)
|
||||
->export_metadata($subcontext, 'firstkey', 'alternativevalue', 'alternativedescription')
|
||||
->export_metadata($subcontext, 'thirdkey', 'thirdvalue', 'thirddescription');
|
||||
|
||||
$fileroot = $this->fetch_exported_content($writer);
|
||||
|
||||
$systemcontextpath = $this->get_context_path($systemcontext, $subcontext, 'metadata.json');
|
||||
$this->assertTrue($fileroot->hasChild($systemcontextpath));
|
||||
|
||||
$json = $fileroot->getChild($systemcontextpath)->getContent();
|
||||
$expanded = json_decode($json);
|
||||
|
||||
$this->assertTrue(isset($expanded->firstkey));
|
||||
$this->assertEquals('firstvalue', $expanded->firstkey->value);
|
||||
$this->assertEquals('firstdescription', $expanded->firstkey->description);
|
||||
$this->assertTrue(isset($expanded->secondkey));
|
||||
$this->assertEquals('secondvalue', $expanded->secondkey->value);
|
||||
$this->assertEquals('seconddescription', $expanded->secondkey->description);
|
||||
$this->assertFalse(isset($expanded->thirdkey));
|
||||
|
||||
$usercontextpath = $this->get_context_path($usercontext, $subcontext, 'metadata.json');
|
||||
$this->assertTrue($fileroot->hasChild($usercontextpath));
|
||||
|
||||
$json = $fileroot->getChild($usercontextpath)->getContent();
|
||||
$expanded = json_decode($json);
|
||||
|
||||
$this->assertTrue(isset($expanded->firstkey));
|
||||
$this->assertEquals('alternativevalue', $expanded->firstkey->value);
|
||||
$this->assertEquals('alternativedescription', $expanded->firstkey->description);
|
||||
$this->assertFalse(isset($expanded->secondkey));
|
||||
$this->assertTrue(isset($expanded->thirdkey));
|
||||
$this->assertEquals('thirdvalue', $expanded->thirdkey->value);
|
||||
$this->assertEquals('thirddescription', $expanded->thirdkey->description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for exporting user metadata.
|
||||
*
|
||||
* return array
|
||||
*/
|
||||
public function export_metadata_provider() {
|
||||
return [
|
||||
'basic' => [
|
||||
'key',
|
||||
'value',
|
||||
'This is a description',
|
||||
],
|
||||
'valuewithspaces' => [
|
||||
'key',
|
||||
'value has mixed',
|
||||
'This is a description',
|
||||
],
|
||||
'encodedvalue' => [
|
||||
'key',
|
||||
base64_encode('value has mixed'),
|
||||
'This is a description',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Exporting a single stored_file should cause that file to be output in the files directory.
|
||||
*/
|
||||
public function test_export_area_files() {
|
||||
$this->resetAfterTest();
|
||||
$context = \context_system::instance();
|
||||
$fs = get_file_storage();
|
||||
|
||||
// Add two files to core_privacy::tests::0.
|
||||
$files = [];
|
||||
$file = (object) [
|
||||
'component' => 'core_privacy',
|
||||
'filearea' => 'tests',
|
||||
'itemid' => 0,
|
||||
'path' => '/',
|
||||
'name' => 'a.txt',
|
||||
'content' => 'Test file 0',
|
||||
];
|
||||
$files[] = $file;
|
||||
|
||||
$file = (object) [
|
||||
'component' => 'core_privacy',
|
||||
'filearea' => 'tests',
|
||||
'itemid' => 0,
|
||||
'path' => '/',
|
||||
'name' => 'b.txt',
|
||||
'content' => 'Test file 1',
|
||||
];
|
||||
$files[] = $file;
|
||||
|
||||
// One with a different itemid.
|
||||
$file = (object) [
|
||||
'component' => 'core_privacy',
|
||||
'filearea' => 'tests',
|
||||
'itemid' => 1,
|
||||
'path' => '/',
|
||||
'name' => 'c.txt',
|
||||
'content' => 'Other',
|
||||
];
|
||||
$files[] = $file;
|
||||
|
||||
// One with a different filearea.
|
||||
$file = (object) [
|
||||
'component' => 'core_privacy',
|
||||
'filearea' => 'alternative',
|
||||
'itemid' => 0,
|
||||
'path' => '/',
|
||||
'name' => 'd.txt',
|
||||
'content' => 'Alternative',
|
||||
];
|
||||
$files[] = $file;
|
||||
|
||||
// One with a different component.
|
||||
$file = (object) [
|
||||
'component' => 'core',
|
||||
'filearea' => 'tests',
|
||||
'itemid' => 0,
|
||||
'path' => '/',
|
||||
'name' => 'e.txt',
|
||||
'content' => 'Other tests',
|
||||
];
|
||||
$files[] = $file;
|
||||
|
||||
foreach ($files as $file) {
|
||||
$record = [
|
||||
'contextid' => $context->id,
|
||||
'component' => $file->component,
|
||||
'filearea' => $file->filearea,
|
||||
'itemid' => $file->itemid,
|
||||
'filepath' => $file->path,
|
||||
'filename' => $file->name,
|
||||
];
|
||||
|
||||
$file->namepath = $file->path . $file->name;
|
||||
$file->storedfile = $fs->create_file_from_string($record, $file->content);
|
||||
}
|
||||
|
||||
$writer = $this->get_writer_instance()
|
||||
->set_context($context)
|
||||
->export_area_files([], 'core_privacy', 'tests', 0);
|
||||
|
||||
$fileroot = $this->fetch_exported_content($writer);
|
||||
|
||||
$firstfiles = array_slice($files, 0, 2);
|
||||
foreach ($firstfiles as $file) {
|
||||
$contextpath = $this->get_context_path($context, [get_string('files')], $file->namepath);
|
||||
$this->assertTrue($fileroot->hasChild($contextpath));
|
||||
$this->assertEquals($file->content, $fileroot->getChild($contextpath)->getContent());
|
||||
}
|
||||
|
||||
$otherfiles = array_slice($files, 2);
|
||||
foreach ($otherfiles as $file) {
|
||||
$contextpath = $this->get_context_path($context, [get_string('files')], $file->namepath);
|
||||
$this->assertFalse($fileroot->hasChild($contextpath));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exporting a single stored_file should cause that file to be output in the files directory.
|
||||
*
|
||||
* @dataProvider export_file_provider
|
||||
* @param string $filepath File path
|
||||
* @param string $filename File name
|
||||
* @param string $content Content
|
||||
*/
|
||||
public function test_export_file($filepath, $filename, $content) {
|
||||
$this->resetAfterTest();
|
||||
$context = \context_system::instance();
|
||||
$filenamepath = $filepath . $filename;
|
||||
|
||||
$filerecord = array(
|
||||
'contextid' => $context->id,
|
||||
'component' => 'core_privacy',
|
||||
'filearea' => 'tests',
|
||||
'itemid' => 0,
|
||||
'filepath' => $filepath,
|
||||
'filename' => $filename,
|
||||
);
|
||||
|
||||
$fs = get_file_storage();
|
||||
$file = $fs->create_file_from_string($filerecord, $content);
|
||||
|
||||
$writer = $this->get_writer_instance()
|
||||
->set_context($context)
|
||||
->export_file([], $file);
|
||||
|
||||
$fileroot = $this->fetch_exported_content($writer);
|
||||
|
||||
$contextpath = $this->get_context_path($context, [get_string('files')], $filenamepath);
|
||||
$this->assertTrue($fileroot->hasChild($contextpath));
|
||||
$this->assertEquals($content, $fileroot->getChild($contextpath)->getContent());
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for the test_export_file function.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function export_file_provider() {
|
||||
return [
|
||||
'basic' => [
|
||||
'/',
|
||||
'testfile.txt',
|
||||
'An example file content',
|
||||
],
|
||||
'longpath' => [
|
||||
'/path/within/a/path/within/a/path/',
|
||||
'testfile.txt',
|
||||
'An example file content',
|
||||
],
|
||||
'pathwithspaces' => [
|
||||
'/path with/some spaces/',
|
||||
'testfile.txt',
|
||||
'An example file content',
|
||||
],
|
||||
'filewithspaces' => [
|
||||
'/path with/some spaces/',
|
||||
'test file.txt',
|
||||
'An example file content',
|
||||
],
|
||||
'image' => [
|
||||
'/',
|
||||
'logo.png',
|
||||
file_get_contents(__DIR__ . '/fixtures/logo.png'),
|
||||
],
|
||||
'UTF8' => [
|
||||
'/Žluťoučký/',
|
||||
'koníček.txt',
|
||||
'koníček',
|
||||
],
|
||||
'EUC-JP' => [
|
||||
'/言語設定/',
|
||||
'言語設定.txt',
|
||||
'言語設定',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* User preferences can not be exported against the user context.
|
||||
*/
|
||||
public function test_export_user_preference_context_user() {
|
||||
$admin = \core_user::get_user_by_username('admin');
|
||||
|
||||
$writer = $this->get_writer_instance();
|
||||
|
||||
$this->expectException('coding_exception');
|
||||
$writer->set_context(\context_user::instance($admin->id))
|
||||
->export_user_preference('core_privacy', 'validkey', 'value', 'description');
|
||||
}
|
||||
|
||||
/**
|
||||
* User preferences can not be exported against the coursecat context.
|
||||
*/
|
||||
public function test_export_user_preference_context_coursecat() {
|
||||
global $DB;
|
||||
|
||||
$categories = $DB->get_records('course_categories');
|
||||
$firstcategory = reset($categories);
|
||||
|
||||
$this->expectException('coding_exception');
|
||||
$this->get_writer_instance()
|
||||
->set_context(\context_coursecat::instance($firstcategory->id))
|
||||
->export_user_preference('core_privacy', 'validkey', 'value', 'description');
|
||||
}
|
||||
|
||||
/**
|
||||
* User preferences can not be exported against the course context.
|
||||
*/
|
||||
public function test_export_user_preference_context_course() {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
|
||||
$this->expectException('coding_exception');
|
||||
$this->get_writer_instance()
|
||||
->set_context(\context_course::instance($course->id))
|
||||
->export_user_preference('core_privacy', 'validkey', 'value', 'description');
|
||||
}
|
||||
|
||||
/**
|
||||
* User preferences can not be exported against a module context.
|
||||
*/
|
||||
public function test_export_user_preference_context_module() {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$forum = $this->getDataGenerator()->create_module('forum', ['course' => $course->id]);
|
||||
|
||||
$this->expectException('coding_exception');
|
||||
$this->get_writer_instance()
|
||||
->set_context(\context_module::instance($forum->cmid))
|
||||
->export_user_preference('core_privacy', 'validkey', 'value', 'description');
|
||||
}
|
||||
|
||||
/**
|
||||
* User preferences can not be exported against a block context.
|
||||
*/
|
||||
public function test_export_user_preference_context_block() {
|
||||
global $DB;
|
||||
|
||||
$blocks = $DB->get_records('block_instances');
|
||||
$block = reset($blocks);
|
||||
|
||||
$this->expectException('coding_exception');
|
||||
$this->get_writer_instance()
|
||||
->set_context(\context_block::instance($block->id))
|
||||
->export_user_preference('core_privacy', 'validkey', 'value', 'description');
|
||||
}
|
||||
|
||||
/**
|
||||
* User preferences can be exported against the system.
|
||||
*
|
||||
* @dataProvider export_user_preference_provider
|
||||
* @param string $component Component
|
||||
* @param string $key Key
|
||||
* @param string $value Value
|
||||
* @param string $desc Description
|
||||
*/
|
||||
public function test_export_user_preference_context_system($component, $key, $value, $desc) {
|
||||
$context = \context_system::instance();
|
||||
$writer = $this->get_writer_instance()
|
||||
->set_context($context)
|
||||
->export_user_preference($component, $key, $value, $desc);
|
||||
|
||||
$fileroot = $this->fetch_exported_content($writer);
|
||||
|
||||
$contextpath = $this->get_context_path($context, [get_string('userpreferences')], "{$component}.json");
|
||||
$this->assertTrue($fileroot->hasChild($contextpath));
|
||||
|
||||
$json = $fileroot->getChild($contextpath)->getContent();
|
||||
$expanded = json_decode($json);
|
||||
$this->assertTrue(isset($expanded->$key));
|
||||
$data = $expanded->$key;
|
||||
$this->assertEquals($value, $data->value);
|
||||
$this->assertEquals($desc, $data->description);
|
||||
}
|
||||
|
||||
/**
|
||||
* User preferences can be exported against the system.
|
||||
*/
|
||||
public function test_export_multiple_user_preference_context_system() {
|
||||
$context = \context_system::instance();
|
||||
$writer = $this->get_writer_instance();
|
||||
$component = 'core_privacy';
|
||||
|
||||
$writer
|
||||
->set_context($context)
|
||||
->export_user_preference($component, 'key1', 'val1', 'desc1')
|
||||
->export_user_preference($component, 'key2', 'val2', 'desc2');
|
||||
|
||||
$fileroot = $this->fetch_exported_content($writer);
|
||||
|
||||
$contextpath = $this->get_context_path($context, [get_string('userpreferences')], "{$component}.json");
|
||||
$this->assertTrue($fileroot->hasChild($contextpath));
|
||||
|
||||
$json = $fileroot->getChild($contextpath)->getContent();
|
||||
$expanded = json_decode($json);
|
||||
|
||||
$this->assertTrue(isset($expanded->key1));
|
||||
$data = $expanded->key1;
|
||||
$this->assertEquals('val1', $data->value);
|
||||
$this->assertEquals('desc1', $data->description);
|
||||
|
||||
$this->assertTrue(isset($expanded->key2));
|
||||
$data = $expanded->key2;
|
||||
$this->assertEquals('val2', $data->value);
|
||||
$this->assertEquals('desc2', $data->description);
|
||||
}
|
||||
|
||||
/**
|
||||
* User preferences can be exported against the system.
|
||||
*/
|
||||
public function test_export_user_preference_replace() {
|
||||
$context = \context_system::instance();
|
||||
$writer = $this->get_writer_instance();
|
||||
$component = 'core_privacy';
|
||||
$key = 'key';
|
||||
|
||||
$writer
|
||||
->set_context($context)
|
||||
->export_user_preference($component, $key, 'val1', 'desc1');
|
||||
|
||||
$writer
|
||||
->set_context($context)
|
||||
->export_user_preference($component, $key, 'val2', 'desc2');
|
||||
|
||||
$fileroot = $this->fetch_exported_content($writer);
|
||||
|
||||
$contextpath = $this->get_context_path($context, [get_string('userpreferences')], "{$component}.json");
|
||||
$this->assertTrue($fileroot->hasChild($contextpath));
|
||||
|
||||
$json = $fileroot->getChild($contextpath)->getContent();
|
||||
$expanded = json_decode($json);
|
||||
|
||||
$this->assertTrue(isset($expanded->$key));
|
||||
$data = $expanded->$key;
|
||||
$this->assertEquals('val2', $data->value);
|
||||
$this->assertEquals('desc2', $data->description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provider for various user preferences.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function export_user_preference_provider() {
|
||||
return [
|
||||
'basic' => [
|
||||
'core_privacy',
|
||||
'onekey',
|
||||
'value',
|
||||
'description',
|
||||
],
|
||||
'encodedvalue' => [
|
||||
'core_privacy',
|
||||
'donkey',
|
||||
base64_encode('value'),
|
||||
'description',
|
||||
],
|
||||
'long description' => [
|
||||
'core_privacy',
|
||||
'twokey',
|
||||
'value',
|
||||
'This is a much longer description which actually states what this is used for. Blah blah blah.',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a fresh content writer.
|
||||
*
|
||||
* @return moodle_content_writer
|
||||
*/
|
||||
public function get_writer_instance() {
|
||||
$factory = $this->createMock(writer::class);
|
||||
return new moodle_content_writer($factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the exported content for inspection.
|
||||
*
|
||||
* @param moodle_content_writer $writer
|
||||
* @return \org\bovigo\vfs\vfsStreamDirectory
|
||||
*/
|
||||
protected function fetch_exported_content(moodle_content_writer $writer) {
|
||||
$export = $writer
|
||||
->set_context(\context_system::instance())
|
||||
->finalise_content();
|
||||
|
||||
$fileroot = \org\bovigo\vfs\vfsStream::setup('root');
|
||||
|
||||
$target = \org\bovigo\vfs\vfsStream::url('root');
|
||||
$fp = get_file_packer();
|
||||
$fp->extract_to_pathname($export, $target);
|
||||
|
||||
return $fileroot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the path for the current context.
|
||||
*
|
||||
* Note: This is a wrapper around the real function.
|
||||
*
|
||||
* @param \context $context The context being written
|
||||
* @param array $subcontext The subcontext path
|
||||
* @param string $name THe name of the file target
|
||||
* @return array The context path.
|
||||
*/
|
||||
protected function get_context_path($context, $subcontext = null, $name = '') {
|
||||
$rc = new ReflectionClass(moodle_content_writer::class);
|
||||
$writer = $this->get_writer_instance();
|
||||
$writer->set_context($context);
|
||||
|
||||
if (null === $subcontext) {
|
||||
$rcm = $rc->getMethod('get_context_path');
|
||||
$rcm->setAccessible(true);
|
||||
return $rcm->invoke($writer);
|
||||
} else {
|
||||
$rcm = $rc->getMethod('get_path');
|
||||
$rcm->setAccessible(true);
|
||||
return $rcm->invoke($writer, $subcontext, $name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Unit Tests for the request helper.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @category test
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
use \core_privacy\local\request\helper;
|
||||
use \core_privacy\local\request\writer;
|
||||
|
||||
/**
|
||||
* Tests for the \core_privacy API's request helper functionality.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class request_helper_test extends advanced_testcase {
|
||||
/**
|
||||
* Test that basic module data is returned.
|
||||
*/
|
||||
public function test_get_context_data_context_module() {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Setup.
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$user = \core_user::get_user_by_username('admin');
|
||||
|
||||
$forum = $this->getDataGenerator()->create_module('forum', [
|
||||
'course' => $course->id,
|
||||
]);
|
||||
$context = context_module::instance($forum->cmid);
|
||||
$modinfo = get_fast_modinfo($course->id);
|
||||
$cm = $modinfo->cms[$context->instanceid];
|
||||
|
||||
// Fetch the data.
|
||||
$result = helper::get_context_data($context, $user);
|
||||
$this->assertInstanceOf('stdClass', $result);
|
||||
|
||||
// Check that the name matches.
|
||||
$this->assertEquals($cm->get_formatted_name(), $result->name);
|
||||
|
||||
// This plugin supports the intro. Check that it is included and correct.
|
||||
$formattedintro = format_text($forum->intro, $forum->introformat, [
|
||||
'noclean' => true,
|
||||
'para' => false,
|
||||
'context' => $context,
|
||||
'overflowdiv' => true,
|
||||
]);
|
||||
$this->assertEquals($formattedintro, $result->intro);
|
||||
|
||||
// This function should only fetch data. It does not export it.
|
||||
$this->assertFalse(writer::with_context($context)->has_any_data());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that basic block data is returned.
|
||||
*/
|
||||
public function test_get_context_data_context_block() {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Setup.
|
||||
$block = $this->getDataGenerator()->create_block('online_users');
|
||||
$context = context_block::instance($block->id);
|
||||
$user = \core_user::get_user_by_username('admin');
|
||||
|
||||
// Fetch the data.
|
||||
$data = helper::get_context_data($context, $user);
|
||||
$this->assertEquals(get_string('pluginname', 'block_online_users'), $data->blocktype);
|
||||
|
||||
// This function should only fetch data. It does not export it.
|
||||
$this->assertFalse(writer::with_context($context)->has_any_data());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that a course moudle with completion tracking enabled has the completion data returned.
|
||||
*/
|
||||
public function test_get_context_data_context_module_completion() {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Create a module and set completion.
|
||||
$course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]);
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$this->getDataGenerator()->enrol_user($user->id, $course->id, 'student');
|
||||
$assign = $this->getDataGenerator()->create_module('assign', ['course' => $course->id, 'completion' => 1]);
|
||||
$context = context_module::instance($assign->cmid);
|
||||
$cm = get_coursemodule_from_id('assign', $assign->cmid);
|
||||
|
||||
// Fetch context data.
|
||||
$contextdata = helper::get_context_data($context, $user);
|
||||
|
||||
// Completion state is zero.
|
||||
// Check non completion for a user.
|
||||
$this->assertEquals(0, $contextdata->completion->state);
|
||||
|
||||
// Complete the activity as a user.
|
||||
$completioninfo = new completion_info($course);
|
||||
$completioninfo->update_state($cm, COMPLETION_COMPLETE, $user->id);
|
||||
|
||||
// Check that completion is now exported.
|
||||
$contextdata = helper::get_context_data($context, $user);
|
||||
$this->assertEquals(1, $contextdata->completion->state);
|
||||
|
||||
// This function should only fetch data. It does not export it.
|
||||
$this->assertFalse(writer::with_context($context)->has_any_data());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that when there are no files to export for a course module context, nothing is exported.
|
||||
*/
|
||||
public function test_export_context_files_context_module_no_files() {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Setup.
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$user = \core_user::get_user_by_username('admin');
|
||||
|
||||
$forum = $this->getDataGenerator()->create_module('forum', [
|
||||
'course' => $course->id,
|
||||
]);
|
||||
$context = context_module::instance($forum->cmid);
|
||||
$modinfo = get_fast_modinfo($course->id);
|
||||
$cm = $modinfo->cms[$context->instanceid];
|
||||
|
||||
// Fetch the data.
|
||||
helper::export_context_files($context, $user);
|
||||
|
||||
// This function should only fetch data. It does not export it.
|
||||
$this->assertFalse(writer::with_context($context)->has_any_data());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that when there are no files to export for a course context, nothing is exported.
|
||||
*/
|
||||
public function test_export_context_files_context_course_no_files() {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Setup.
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$user = \core_user::get_user_by_username('admin');
|
||||
$context = context_course::instance($course->id);
|
||||
|
||||
// Fetch the data.
|
||||
helper::export_context_files($context, $user);
|
||||
|
||||
// This function should only fetch data. It does not export it.
|
||||
$this->assertFalse(writer::with_context($context)->has_any_data());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that when there are files to export for a course context, the files are exported.
|
||||
*/
|
||||
public function test_export_context_files_context_course_intro_files() {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Setup.
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$user = \core_user::get_user_by_username('admin');
|
||||
$assign = $this->getDataGenerator()->create_module('assign', ['course' => $course->id]);
|
||||
$context = context_module::instance($assign->cmid);
|
||||
|
||||
// File details.
|
||||
$filerecord = array(
|
||||
'contextid' => $context->id,
|
||||
'component' => 'mod_assign',
|
||||
'filearea' => 'intro',
|
||||
'itemid' => 0,
|
||||
'filepath' => '/',
|
||||
'filename' => 'logo.png',
|
||||
);
|
||||
|
||||
$content = file_get_contents(__DIR__ . '/fixtures/logo.png');
|
||||
|
||||
// Store the file.
|
||||
$fs = get_file_storage();
|
||||
$file = $fs->create_file_from_string($filerecord, $content);
|
||||
|
||||
// Fetch the data.
|
||||
helper::export_context_files($context, $user);
|
||||
|
||||
// This should have resulted in the file being exported.
|
||||
$this->assertTrue(writer::with_context($context)->has_any_data());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Unit Tests for the request transform helper.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @category test
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
use \core_privacy\local\request\transform;
|
||||
|
||||
/**
|
||||
* Tests for the \core_privacy API's request transform helper functionality.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class request_transform_test extends advanced_testcase {
|
||||
/**
|
||||
* Test that user translation currently does nothing.
|
||||
*
|
||||
* We have not determined if we will do this or not, but we provide the functionality and encourgae people to use
|
||||
* it so that it can be retrospectively fitted if required.
|
||||
*/
|
||||
public function test_user() {
|
||||
// Note: This test currently sucks, but there's no point creating users just to test this.
|
||||
for ($i = 0; $i < 10; $i++) {
|
||||
$this->assertEquals($i, transform::user($i));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the datetime is translated into a string.
|
||||
*/
|
||||
public function test_datetime() {
|
||||
$this->assertInternalType('string', transform::datetime(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the date is translated into a string.
|
||||
*/
|
||||
public function test_date() {
|
||||
$this->assertInternalType('string', transform::date(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the yesno function translates correctly.
|
||||
*
|
||||
* @dataProvider yesno_provider
|
||||
* @param mixed $input The input to test
|
||||
* @param string $expected The expected value
|
||||
*/
|
||||
public function test_yesno($input, $expected) {
|
||||
$this->assertEquals($expected, transform::yesno($input));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for tests of the yesno transformation.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function yesno_provider() {
|
||||
return [
|
||||
'Bool False' => [
|
||||
false,
|
||||
get_string('no'),
|
||||
],
|
||||
'Bool true' => [
|
||||
true,
|
||||
get_string('yes'),
|
||||
],
|
||||
'Int 0' => [
|
||||
0,
|
||||
get_string('no'),
|
||||
],
|
||||
'Int 1' => [
|
||||
1,
|
||||
get_string('yes'),
|
||||
],
|
||||
'String 0' => [
|
||||
'0',
|
||||
get_string('no'),
|
||||
],
|
||||
'String 1' => [
|
||||
'1',
|
||||
get_string('yes'),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Type unit tests for the Database Table.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @category test
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
use \core_privacy\local\metadata\types\database_table;
|
||||
|
||||
/**
|
||||
* Tests for the \core_privacy API's types\database_table functionality.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class core_privacy_metadata_types_database_table extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Ensure that warnings are thrown if string identifiers contain invalid characters.
|
||||
*
|
||||
* @dataProvider invalid_string_provider
|
||||
* @param string $name Name
|
||||
* @param array $fields List of fields
|
||||
* @param string $summary Summary
|
||||
*/
|
||||
public function test_invalid_configs($name, $fields, $summary) {
|
||||
$record = new database_table($name, $fields, $summary);
|
||||
$this->assertDebuggingCalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that warnings are not thrown if debugging is not enabled, even if string identifiers contain invalid characters.
|
||||
*
|
||||
* @dataProvider invalid_string_provider
|
||||
* @param string $name Name
|
||||
* @param array $fields List of fields
|
||||
* @param string $summary Summary
|
||||
*/
|
||||
public function test_invalid_configs_debug_normal($name, $fields, $summary) {
|
||||
global $CFG;
|
||||
$this->resetAfterTest();
|
||||
|
||||
$CFG->debug = DEBUG_NORMAL;
|
||||
$record = new database_table($name, $fields, $summary);
|
||||
$this->assertDebuggingNotCalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that no warnings are shown for valid combinations.
|
||||
*
|
||||
* @dataProvider valid_string_provider
|
||||
* @param string $name Name
|
||||
* @param array $fields List of fields
|
||||
* @param string $summary Summary
|
||||
*/
|
||||
public function test_valid_configs($name, $fields, $summary) {
|
||||
$record = new database_table($name, $fields, $summary);
|
||||
$this->assertDebuggingNotCalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider with a list of invalid string identifiers.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function invalid_string_provider() {
|
||||
return [
|
||||
'Space in summary' => [
|
||||
'example',
|
||||
[
|
||||
'field' => 'privacy:valid',
|
||||
],
|
||||
'This table is used for purposes.',
|
||||
],
|
||||
'Comma in summary' => [
|
||||
'example',
|
||||
[
|
||||
'field' => 'privacy:valid',
|
||||
],
|
||||
'privacy,foo',
|
||||
],
|
||||
'Space in field name' => [
|
||||
'example',
|
||||
[
|
||||
'field' => 'This field is used for purposes.',
|
||||
],
|
||||
'privacy:valid',
|
||||
],
|
||||
'Comma in field name' => [
|
||||
'example',
|
||||
[
|
||||
'field' => 'invalid,name',
|
||||
],
|
||||
'privacy:valid',
|
||||
],
|
||||
'No fields specified' => [
|
||||
'example',
|
||||
[],
|
||||
'privacy:example:valid',
|
||||
],
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider with a list of valid string identifiers.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function valid_string_provider() {
|
||||
return [
|
||||
'Valid combination' => [
|
||||
'example',
|
||||
[
|
||||
'field' => 'privacy:example:valid:field',
|
||||
'field2' => 'privacy:example:valid:field2',
|
||||
],
|
||||
'privacy:example:valid',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Type unit tests for the External Location.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @category test
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
use \core_privacy\local\metadata\types\external_location;
|
||||
|
||||
/**
|
||||
* Tests for the \core_privacy API's types\external_location functionality.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class core_privacy_metadata_types_external_location extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Ensure that warnings are thrown if string identifiers contain invalid characters.
|
||||
*
|
||||
* @dataProvider invalid_string_provider
|
||||
* @param string $name Name
|
||||
* @param array $fields List of fields
|
||||
* @param string $summary Summary
|
||||
*/
|
||||
public function test_invalid_configs($name, $fields, $summary) {
|
||||
$record = new external_location($name, $fields, $summary);
|
||||
$this->assertDebuggingCalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that warnings are not thrown if debugging is not enabled, even if string identifiers contain invalid characters.
|
||||
*
|
||||
* @dataProvider invalid_string_provider
|
||||
* @param string $name Name
|
||||
* @param array $fields List of fields
|
||||
* @param string $summary Summary
|
||||
*/
|
||||
public function test_invalid_configs_debug_normal($name, $fields, $summary) {
|
||||
global $CFG;
|
||||
$this->resetAfterTest();
|
||||
|
||||
$CFG->debug = DEBUG_NORMAL;
|
||||
$record = new external_location($name, $fields, $summary);
|
||||
$this->assertDebuggingNotCalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that no warnings are shown for valid combinations.
|
||||
*
|
||||
* @dataProvider valid_string_provider
|
||||
* @param string $name Name
|
||||
* @param array $fields List of fields
|
||||
* @param string $summary Summary
|
||||
*/
|
||||
public function test_valid_configs($name, $fields, $summary) {
|
||||
$record = new external_location($name, $fields, $summary);
|
||||
$this->assertDebuggingNotCalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider with a list of invalid string identifiers.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function invalid_string_provider() {
|
||||
return [
|
||||
'Space in summary' => [
|
||||
'example',
|
||||
[
|
||||
'field' => 'privacy:valid',
|
||||
],
|
||||
'This table is used for purposes.',
|
||||
],
|
||||
'Comma in summary' => [
|
||||
'example',
|
||||
[
|
||||
'field' => 'privacy:valid',
|
||||
],
|
||||
'privacy,foo',
|
||||
],
|
||||
'Space in field name' => [
|
||||
'example',
|
||||
[
|
||||
'field' => 'This field is used for purposes.',
|
||||
],
|
||||
'privacy:valid',
|
||||
],
|
||||
'Comma in field name' => [
|
||||
'example',
|
||||
[
|
||||
'field' => 'invalid,name',
|
||||
],
|
||||
'privacy:valid',
|
||||
],
|
||||
'No fields specified' => [
|
||||
'example',
|
||||
[],
|
||||
'privacy:example:valid',
|
||||
],
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider with a list of valid string identifiers.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function valid_string_provider() {
|
||||
return [
|
||||
'Valid combination' => [
|
||||
'example',
|
||||
[
|
||||
'field' => 'privacy:example:valid:field',
|
||||
'field2' => 'privacy:example:valid:field2',
|
||||
],
|
||||
'privacy:example:valid',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Types unit tests for the Plugintype Link.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @category test
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
use \core_privacy\local\metadata\types\plugintype_link;
|
||||
|
||||
/**
|
||||
* Tests for the \core_privacy API's types\plugintype_link functionality.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class core_privacy_metadata_types_plugintype_link extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Ensure that warnings are thrown if string identifiers contain invalid characters.
|
||||
*
|
||||
* @dataProvider invalid_string_provider
|
||||
* @param string $name Name
|
||||
* @param string $summary Summary
|
||||
*/
|
||||
public function test_invalid_configs($name, $summary) {
|
||||
$record = new plugintype_link($name, $summary);
|
||||
$this->assertDebuggingCalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that warnings are not thrown if debugging is not enabled, even if string identifiers contain invalid characters.
|
||||
*
|
||||
* @dataProvider invalid_string_provider
|
||||
* @param string $name Name
|
||||
* @param string $summary Summary
|
||||
*/
|
||||
public function test_invalid_configs_debug_normal($name, $summary) {
|
||||
global $CFG;
|
||||
$this->resetAfterTest();
|
||||
|
||||
$CFG->debug = DEBUG_NORMAL;
|
||||
$record = new plugintype_link($name, $summary);
|
||||
$this->assertDebuggingNotCalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that no warnings are shown for valid combinations.
|
||||
*
|
||||
* @dataProvider valid_string_provider
|
||||
* @param string $name Name
|
||||
* @param string $summary Summary
|
||||
*/
|
||||
public function test_valid_configs($name, $summary) {
|
||||
$record = new plugintype_link($name, $summary);
|
||||
$this->assertDebuggingNotCalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider with a list of invalid string identifiers.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function invalid_string_provider() {
|
||||
return [
|
||||
'Space in summary' => [
|
||||
'example',
|
||||
'This table is used for purposes.',
|
||||
],
|
||||
'Comma in summary' => [
|
||||
'example',
|
||||
'privacy,foo',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider with a list of valid string identifiers.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function valid_string_provider() {
|
||||
return [
|
||||
'Valid combination' => [
|
||||
'example',
|
||||
'privacy:example:valid',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Types unit tests for the Subsystem Link.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @category test
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
use \core_privacy\local\metadata\types\subsystem_link;
|
||||
|
||||
/**
|
||||
* Tests for the \core_privacy API's types\subsystem_link functionality.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class core_privacy_metadata_types_subsystem_link extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Ensure that warnings are thrown if string identifiers contain invalid characters.
|
||||
*
|
||||
* @dataProvider invalid_string_provider
|
||||
* @param string $name Name
|
||||
* @param string $summary Summary
|
||||
*/
|
||||
public function test_invalid_configs($name, $summary) {
|
||||
$record = new subsystem_link($name, $summary);
|
||||
$this->assertDebuggingCalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that warnings are not thrown if debugging is not enabled, even if string identifiers contain invalid characters.
|
||||
*
|
||||
* @dataProvider invalid_string_provider
|
||||
* @param string $name Name
|
||||
* @param string $summary Summary
|
||||
*/
|
||||
public function test_invalid_configs_debug_normal($name, $summary) {
|
||||
global $CFG;
|
||||
$this->resetAfterTest();
|
||||
|
||||
$CFG->debug = DEBUG_NORMAL;
|
||||
$record = new subsystem_link($name, $summary);
|
||||
$this->assertDebuggingNotCalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that no warnings are shown for valid combinations.
|
||||
*
|
||||
* @dataProvider valid_string_provider
|
||||
* @param string $name Name
|
||||
* @param string $summary Summary
|
||||
*/
|
||||
public function test_valid_configs($name, $summary) {
|
||||
$record = new subsystem_link($name, $summary);
|
||||
$this->assertDebuggingNotCalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider with a list of invalid string identifiers.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function invalid_string_provider() {
|
||||
return [
|
||||
'Space in summary' => [
|
||||
'example',
|
||||
'This table is used for purposes.',
|
||||
],
|
||||
'Comma in summary' => [
|
||||
'example',
|
||||
'privacy,foo',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider with a list of valid string identifiers.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function valid_string_provider() {
|
||||
return [
|
||||
'Valid combination' => [
|
||||
'example',
|
||||
'privacy:example:valid',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Types unit tests for the Subsystem Link.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @category test
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
use \core_privacy\local\metadata\types\user_preference;
|
||||
|
||||
/**
|
||||
* Tests for the \core_privacy API's types\user_preference functionality.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class core_privacy_metadata_types_user_preference extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Ensure that warnings are thrown if string identifiers contain invalid characters.
|
||||
*
|
||||
* @dataProvider invalid_string_provider
|
||||
* @param string $name Name
|
||||
* @param string $summary Summary
|
||||
*/
|
||||
public function test_invalid_configs($name, $summary) {
|
||||
$record = new user_preference($name, $summary);
|
||||
$this->assertDebuggingCalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that warnings are not thrown if debugging is not enabled, even if string identifiers contain invalid characters.
|
||||
*
|
||||
* @dataProvider invalid_string_provider
|
||||
* @param string $name Name
|
||||
* @param string $summary Summary
|
||||
*/
|
||||
public function test_invalid_configs_debug_normal($name, $summary) {
|
||||
global $CFG;
|
||||
$this->resetAfterTest();
|
||||
|
||||
$CFG->debug = DEBUG_NORMAL;
|
||||
$record = new user_preference($name, $summary);
|
||||
$this->assertDebuggingNotCalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that no warnings are shown for valid combinations.
|
||||
*
|
||||
* @dataProvider valid_string_provider
|
||||
* @param string $name Name
|
||||
* @param string $summary Summary
|
||||
*/
|
||||
public function test_valid_configs($name, $summary) {
|
||||
$record = new user_preference($name, $summary);
|
||||
$this->assertDebuggingNotCalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider with a list of invalid string identifiers.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function invalid_string_provider() {
|
||||
return [
|
||||
'Space in summary' => [
|
||||
'example',
|
||||
'This table is used for purposes.',
|
||||
],
|
||||
'Comma in summary' => [
|
||||
'example',
|
||||
'privacy,foo',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider with a list of valid string identifiers.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function valid_string_provider() {
|
||||
return [
|
||||
'Valid combination' => [
|
||||
'example',
|
||||
'privacy:example:valid',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Unit Tests for the Moodle Content Writer.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @category test
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
use \core_privacy\local\request\writer;
|
||||
|
||||
/**
|
||||
* Tests for the \core_privacy API's moodle_content_writer functionality.
|
||||
*
|
||||
* Note: The \core_privacy\tests\request\content_writer will be used for these tests.
|
||||
* This content writer has additional sugar methods for fetching infromation which are not part of the standard
|
||||
* content_writer interface.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class writer_test extends advanced_testcase {
|
||||
/**
|
||||
* Test that calling with_context multiple times will return the same write instance.
|
||||
*/
|
||||
public function test_with_context() {
|
||||
$writer = writer::with_context(\context_system::instance());
|
||||
|
||||
$this->assertSame($writer, writer::with_context(\context_system::instance()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that calling with_context multiple times will return the same write instance.
|
||||
*/
|
||||
public function test_with_context_different_context_same_instance() {
|
||||
$writer = writer::with_context(\context_system::instance());
|
||||
|
||||
$this->assertSame($writer, writer::with_context(\context_user::instance(\core_user::get_user_by_username('admin')->id)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that calling writer::reset() causes a new copy of the writer to be returned.
|
||||
*/
|
||||
public function test_reset() {
|
||||
$writer = writer::with_context(\context_system::instance());
|
||||
writer::reset();
|
||||
|
||||
$this->assertNotSame($writer, writer::with_context(\context_system::instance()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the export_user_preference calls the writer against the system context.
|
||||
*/
|
||||
public function test_export_user_preference_sets_system_context() {
|
||||
$writer = writer::with_context(\context_user::instance(\core_user::get_user_by_username('admin')->id));
|
||||
|
||||
writer::export_user_preference('core_test', 'key', 'value', 'description');
|
||||
|
||||
$this->assertSame(\context_system::instance(), $writer->get_current_context());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user