Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

Privacy API/Utilities

From MoodleDocs
Revision as of 12:51, 12 April 2018 by David Mudrak (talk | contribs) (Put a note about the purpose of the scripts)

While implementing the privacy API into your plugin, there are CLI scripts that can help you to test things on the fly. Just don't forget these are not supposed to replace proper unit tests.

Put these scripts into the root of your Moodle development installation and run them via command line. See Privacy API for the full guide on implementing the API in your plugin.

Test of privacy API compliance

<?php

// Set this if you want to run the script for one component only. Otherwise leave empty. $CHECK_COMPONENT = ;

define('CLI_SCRIPT', true);

require_once('config.php');

$user = \core_user::get_user(2);

\core\session\manager::init_empty_session(); \core\session\manager::set_user($user);

$rc = new \ReflectionClass(\core_privacy\manager::class); $rcm = $rc->getMethod('get_component_list'); $rcm->setAccessible(true);

$manager = new \core_privacy\manager(); $components = $rcm->invoke($manager);

$list = (object) [

   'good' => [],
   'bad' => [],

];

foreach ($components as $component) {

   if ($CHECK_COMPONENT && $component !== $CHECK_COMPONENT) {
       continue;
   }
   $compliant = $manager->component_is_compliant($component);
   if ($compliant) {
       $list->good[] = $component;
   } else {
       $list->bad[] = $component;
   }

}

echo "The following plugins are not compliant:\n"; echo "=> " . implode("\n=> ", array_values($list->bad)) . "\n";

echo "\n"; echo "Testing the compliant plugins:\n"; foreach ($list->good as $component) {

   $classname = \core_privacy\manager::get_provider_classname_for_component($component);
   echo "== {$component} ($classname) ==\n";
   if (check_implements($component, \core_privacy\local\metadata\null_provider::class)) {
       echo "    Claims not to store any data with reason:\n";
       echo "      '" . get_string($classname::get_reason(), $component) . "'\n";
   }
   else if (check_implements($component, \core_privacy\local\metadata\provider::class)) {
       $collection = new \core_privacy\local\metadata\collection($component);
       $classname::get_metadata($collection);
       $count = count($collection);
       echo "    Found {$count} items of metadata\n";
       if (empty($count)) {
           echo "!!! No metadata found!!! This an error.\n";
       }
       if (check_implements($component, \core_privacy\local\request\user_preference_provider::class)) {
           $userprefdescribed = false;
           foreach ($collection->get_collection() as $item) {
               if ($item instanceof \core_privacy\local\metadata\types\user_preference) {
                   $userprefdescribed = true;
                   echo "     ".$item->get_name()." : ".get_string($item->get_summary(), $component) . "\n";
               }
           }
           if (!$userprefdescribed) {
               echo "!!! User preference found, but was not described in metadata\n";
           }
       }
       if (check_implements($component, \core_privacy\local\request\core_user_data_provider::class)) {
           // No need to check the return type - it's enforced by the interface.
           $contextlist = $classname::get_contexts_for_userid($user->id);
           $approvedcontextlist = new \core_privacy\local\request\approved_contextlist($user, $contextlist->get_component(), $contextlist->get_contextids());
           if (count($approvedcontextlist)) {
               $classname::export_user_data($approvedcontextlist);
               echo "    Successfully ran a test export\n";
           } else {
               echo "    Nothing to export.\n";
           }
       }
       if (check_implements($component, \core_privacy\local\request\shared_data_provider::class)) {
           echo "    This is a shared data provider\n";
       }
   }

}

echo "\n\n== Done ==\n";

function check_implements($component, $interface) {

   $manager = new \core_privacy\manager();
   $rc = new \ReflectionClass(\core_privacy\manager::class);
   $rcm = $rc->getMethod('component_implements');
   $rcm->setAccessible(true);
   return $rcm->invoke($manager, $component, $interface);

}

Test of exporting user data

<?php

define('CLI_SCRIPT', true);

require_once('config.php');

$user = \core_user::get_user(2);

\core\session\manager::init_empty_session(); \core\session\manager::set_user($user);

$manager = new \core_privacy\manager();

$approvedlist = new \core_privacy\local\request\contextlist_collection($user->id);

$contextlists = $manager->get_contexts_for_userid($user->id); foreach ($contextlists as $contextlist) {

   $approvedlist->add_contextlist(new \core_privacy\local\request\approved_contextlist(
       $user,
       $contextlist->get_component(),
       $contextlist->get_contextids()
   ));

}

$exportedcontent = $manager->export_user_data($approvedlist);

echo "\n"; echo "== File was successfully exported to {$exportedcontent}\n";

$basedir = make_temp_directory('privacy'); $exportpath = make_unique_writable_directory($basedir, true); $fp = get_file_packer(); $fp->extract_to_pathname($exportedcontent, $exportpath);

echo "== File export was uncompressed to {$exportpath}\n"; echo "============================================================================\n";