Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 39 and 310]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * Data provider tests.
  19   *
  20   * @package    core_badges
  21   * @category   test
  22   * @copyright  2018 Frédéric Massart
  23   * @author     Frédéric Massart <fred@branchup.tech>
  24   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  25   */
  26  
  27  defined('MOODLE_INTERNAL') || die();
  28  global $CFG;
  29  
  30  use core_privacy\tests\provider_testcase;
  31  use core_privacy\local\request\approved_contextlist;
  32  use core_privacy\local\request\transform;
  33  use core_privacy\local\request\writer;
  34  use core_badges\privacy\provider;
  35  use core_privacy\local\request\approved_userlist;
  36  use core_badges\helper;
  37  
  38  require_once($CFG->libdir . '/badgeslib.php');
  39  
  40  /**
  41   * Data provider testcase class.
  42   *
  43   * @package    core_badges
  44   * @category   test
  45   * @copyright  2018 Frédéric Massart
  46   * @author     Frédéric Massart <fred@branchup.tech>
  47   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  48   */
  49  class core_badges_privacy_testcase extends provider_testcase {
  50  
  51      public function setUp() {
  52          $this->resetAfterTest();
  53      }
  54  
  55      public function test_get_contexts_for_userid_for_badge_editing() {
  56          $dg = $this->getDataGenerator();
  57          $u1 = $dg->create_user();
  58          $u2 = $dg->create_user();
  59          $u3 = $dg->create_user();
  60          $u4 = $dg->create_user();
  61          $u5 = $dg->create_user();
  62          $c1 = $dg->create_course();
  63          $c2 = $dg->create_course();
  64          $sysctx = context_system::instance();
  65          $c1ctx = context_course::instance($c1->id);
  66          $c2ctx = context_course::instance($c2->id);
  67  
  68          // Assert that we find contexts where we created/modified a badge.
  69          $this->create_badge(['usercreated' => $u1->id, 'usermodified' => $u5->id]);
  70          $this->create_badge(['usercreated' => $u2->id, 'type' => BADGE_TYPE_COURSE, 'courseid' => $c1->id]);
  71          $this->create_badge(['usermodified' => $u3->id]);
  72          $this->create_badge(['usermodified' => $u4->id, 'type' => BADGE_TYPE_COURSE, 'courseid' => $c2->id,
  73              'usercreated' => $u5->id]);
  74  
  75          $contexts = provider::get_contexts_for_userid($u1->id)->get_contextids();
  76          $this->assertCount(1, $contexts);
  77          $this->assertEquals($sysctx->id, $contexts[0]);
  78  
  79          $contexts = provider::get_contexts_for_userid($u2->id)->get_contextids();
  80          $this->assertCount(1, $contexts);
  81          $this->assertEquals($c1ctx->id, $contexts[0]);
  82  
  83          $contexts = provider::get_contexts_for_userid($u3->id)->get_contextids();
  84          $this->assertCount(1, $contexts);
  85          $this->assertEquals($sysctx->id, $contexts[0]);
  86  
  87          $contexts = provider::get_contexts_for_userid($u4->id)->get_contextids();
  88          $this->assertCount(1, $contexts);
  89          $this->assertEquals($c2ctx->id, $contexts[0]);
  90  
  91          $contexts = provider::get_contexts_for_userid($u5->id)->get_contextids();
  92          $this->assertCount(2, $contexts);
  93          $this->assertTrue(in_array($sysctx->id, $contexts));
  94          $this->assertTrue(in_array($c2ctx->id, $contexts));
  95      }
  96  
  97      public function test_get_contexts_for_userid_for_manual_award() {
  98          global $DB;
  99  
 100          $dg = $this->getDataGenerator();
 101          $u1 = $dg->create_user();
 102          $u2 = $dg->create_user();
 103          $u3 = $dg->create_user();
 104          $u4 = $dg->create_user();
 105          $c1 = $dg->create_course();
 106          $sysctx = context_system::instance();
 107          $c1ctx = context_course::instance($c1->id);
 108          $u1ctx = context_user::instance($u1->id);
 109          $u2ctx = context_user::instance($u2->id);
 110          $u3ctx = context_user::instance($u3->id);
 111          $u4ctx = context_user::instance($u4->id);
 112          $b1 = $this->create_badge();
 113          $b2 = $this->create_badge(['type' => BADGE_TYPE_COURSE, 'courseid' => $c1->id]);
 114  
 115          $this->create_manual_award(['recipientid' => $u4->id, 'issuerid' => $u1->id, 'badgeid' => $b1->id]);
 116          $this->create_manual_award(['recipientid' => $u3->id, 'issuerid' => $u2->id, 'badgeid' => $b1->id]);
 117          $this->create_manual_award(['recipientid' => $u3->id, 'issuerid' => $u2->id, 'badgeid' => $b2->id]);
 118  
 119          $contexts = provider::get_contexts_for_userid($u1->id)->get_contextids();
 120          $this->assertCount(1, $contexts);
 121          $this->assertEquals($u4ctx->id, $contexts[0]);
 122  
 123          $contexts = provider::get_contexts_for_userid($u2->id)->get_contextids();
 124          $this->assertCount(1, $contexts);
 125          $this->assertEquals($u3ctx->id, $contexts[0]);
 126      }
 127  
 128      public function test_get_contexts_for_userid_for_my_stuff() {
 129          global $DB;
 130  
 131          $dg = $this->getDataGenerator();
 132          $u1 = $dg->create_user();
 133          $u2 = $dg->create_user();
 134          $u3 = $dg->create_user();
 135          $u4 = $dg->create_user();
 136          $c1 = $dg->create_course();
 137          $sysctx = context_system::instance();
 138          $c1ctx = context_course::instance($c1->id);
 139          $u1ctx = context_user::instance($u1->id);
 140          $u2ctx = context_user::instance($u2->id);
 141          $u3ctx = context_user::instance($u3->id);
 142          $u4ctx = context_user::instance($u4->id);
 143          $b1 = $this->create_badge();
 144          $b2 = $this->create_badge(['type' => BADGE_TYPE_COURSE, 'courseid' => $c1->id]);
 145  
 146          helper::create_fake_backpack(['userid' => $u1->id]);
 147          $this->create_manual_award(['recipientid' => $u2->id, 'badgeid' => $b1->id]);
 148          $this->create_issued(['badgeid' => $b2->id, 'userid' => $u3->id]);
 149  
 150          $crit = $this->create_criteria_manual($b1->id);
 151          $crit->mark_complete($u4->id);
 152  
 153          $contexts = provider::get_contexts_for_userid($u1->id)->get_contextids();
 154          $this->assertCount(1, $contexts);
 155          $this->assertEquals($u1ctx->id, $contexts[0]);
 156  
 157          $contexts = provider::get_contexts_for_userid($u2->id)->get_contextids();
 158          $this->assertCount(1, $contexts);
 159          $this->assertEquals($u2ctx->id, $contexts[0]);
 160  
 161          $contexts = provider::get_contexts_for_userid($u3->id)->get_contextids();
 162          $this->assertCount(1, $contexts);
 163          $this->assertEquals($u3ctx->id, $contexts[0]);
 164  
 165          $contexts = provider::get_contexts_for_userid($u4->id)->get_contextids();
 166          $this->assertCount(1, $contexts);
 167          $this->assertEquals($u4ctx->id, $contexts[0]);
 168      }
 169  
 170      public function test_delete_data_for_user() {
 171          global $DB;
 172  
 173          $dg = $this->getDataGenerator();
 174          $u1 = $dg->create_user();
 175          $u2 = $dg->create_user();
 176          $c1 = $dg->create_course();
 177          $sysctx = context_system::instance();
 178          $c1ctx = context_course::instance($c1->id);
 179          $u1ctx = context_user::instance($u1->id);
 180          $u2ctx = context_user::instance($u2->id);
 181  
 182          $b1 = $this->create_badge(['usercreated' => $u1->id, 'usermodified' => $u2->id]);
 183          $b2 = $this->create_badge(['usercreated' => $u2->id, 'usermodified' => $u1->id,
 184              'type' => BADGE_TYPE_COURSE, 'courseid' => $c1->id]);
 185  
 186          helper::create_fake_backpack(['userid' => $u1->id]);
 187          helper::create_fake_backpack(['userid' => $u2->id]);
 188          $this->create_manual_award(['recipientid' => $u1->id, 'badgeid' => $b1->id]);
 189          $this->create_manual_award(['recipientid' => $u2->id, 'badgeid' => $b1->id, 'issuerid' => $u1->id]);
 190          $this->create_issued(['badgeid' => $b2->id, 'userid' => $u1->id]);
 191          $this->create_issued(['badgeid' => $b2->id, 'userid' => $u2->id]);
 192  
 193          $crit = $this->create_criteria_manual($b1->id);
 194          $crit->mark_complete($u2->id);
 195          $crit = $this->create_criteria_manual($b2->id);
 196          $crit->mark_complete($u1->id);
 197  
 198          $this->assertTrue($DB->record_exists('badge_backpack', ['userid' => $u1->id]));
 199          $this->assertTrue($DB->record_exists('badge_backpack', ['userid' => $u2->id]));
 200          $this->assertTrue($DB->record_exists('badge', ['usercreated' => $u1->id]));
 201          $this->assertTrue($DB->record_exists('badge', ['usermodified' => $u1->id]));
 202          $this->assertTrue($DB->record_exists('badge', ['usercreated' => $u2->id]));
 203          $this->assertTrue($DB->record_exists('badge', ['usermodified' => $u2->id]));
 204          $this->assertTrue($DB->record_exists('badge_manual_award', ['recipientid' => $u1->id]));
 205          $this->assertTrue($DB->record_exists('badge_manual_award', ['recipientid' => $u2->id]));
 206          $this->assertTrue($DB->record_exists('badge_issued', ['userid' => $u1->id]));
 207          $this->assertTrue($DB->record_exists('badge_issued', ['userid' => $u2->id]));
 208          $this->assertTrue($DB->record_exists('badge_criteria_met', ['userid' => $u1->id]));
 209          $this->assertTrue($DB->record_exists('badge_criteria_met', ['userid' => $u2->id]));
 210  
 211          provider::delete_data_for_user(new approved_contextlist($u1, 'core_badges', [$sysctx->id, $c1ctx->id,
 212              $u1ctx->id, $u2ctx->id]));
 213  
 214          $this->assertTrue($DB->record_exists('badge', ['usercreated' => $u1->id]));
 215          $this->assertTrue($DB->record_exists('badge', ['usermodified' => $u1->id]));
 216          $this->assertTrue($DB->record_exists('badge', ['usercreated' => $u2->id]));
 217          $this->assertTrue($DB->record_exists('badge', ['usermodified' => $u2->id]));
 218          $this->assertFalse($DB->record_exists('badge_backpack', ['userid' => $u1->id]));
 219          $this->assertTrue($DB->record_exists('badge_backpack', ['userid' => $u2->id]));
 220          $this->assertFalse($DB->record_exists('badge_manual_award', ['recipientid' => $u1->id]));
 221          $this->assertTrue($DB->record_exists('badge_manual_award', ['recipientid' => $u2->id]));
 222          $this->assertFalse($DB->record_exists('badge_issued', ['userid' => $u1->id]));
 223          $this->assertTrue($DB->record_exists('badge_issued', ['userid' => $u2->id]));
 224          $this->assertFalse($DB->record_exists('badge_criteria_met', ['userid' => $u1->id]));
 225          $this->assertTrue($DB->record_exists('badge_criteria_met', ['userid' => $u2->id]));
 226      }
 227  
 228      public function test_delete_data_for_all_users_in_context() {
 229          global $DB;
 230  
 231          $dg = $this->getDataGenerator();
 232          $u1 = $dg->create_user();
 233          $u2 = $dg->create_user();
 234          $c1 = $dg->create_course();
 235          $sysctx = context_system::instance();
 236          $c1ctx = context_course::instance($c1->id);
 237          $u1ctx = context_user::instance($u1->id);
 238          $u2ctx = context_user::instance($u2->id);
 239  
 240          $b1 = $this->create_badge(['usercreated' => $u1->id, 'usermodified' => $u2->id]);
 241          $b2 = $this->create_badge(['usercreated' => $u2->id, 'usermodified' => $u1->id,
 242              'type' => BADGE_TYPE_COURSE, 'courseid' => $c1->id]);
 243  
 244          helper::create_fake_backpack(['userid' => $u1->id]);
 245          helper::create_fake_backpack(['userid' => $u2->id]);
 246          $this->create_manual_award(['recipientid' => $u1->id, 'badgeid' => $b1->id]);
 247          $this->create_manual_award(['recipientid' => $u2->id, 'badgeid' => $b1->id, 'issuerid' => $u1->id]);
 248          $this->create_issued(['badgeid' => $b2->id, 'userid' => $u1->id]);
 249          $this->create_issued(['badgeid' => $b2->id, 'userid' => $u2->id]);
 250  
 251          $crit = $this->create_criteria_manual($b1->id);
 252          $crit->mark_complete($u2->id);
 253          $crit = $this->create_criteria_manual($b2->id);
 254          $crit->mark_complete($u1->id);
 255  
 256          $assertnochange = function() use ($DB, $u1, $u2) {
 257              $this->assertTrue($DB->record_exists('badge_backpack', ['userid' => $u1->id]));
 258              $this->assertTrue($DB->record_exists('badge_backpack', ['userid' => $u2->id]));
 259              $this->assertTrue($DB->record_exists('badge', ['usercreated' => $u1->id]));
 260              $this->assertTrue($DB->record_exists('badge', ['usermodified' => $u1->id]));
 261              $this->assertTrue($DB->record_exists('badge', ['usercreated' => $u2->id]));
 262              $this->assertTrue($DB->record_exists('badge', ['usermodified' => $u2->id]));
 263              $this->assertTrue($DB->record_exists('badge_manual_award', ['recipientid' => $u1->id]));
 264              $this->assertTrue($DB->record_exists('badge_manual_award', ['recipientid' => $u2->id]));
 265              $this->assertTrue($DB->record_exists('badge_issued', ['userid' => $u1->id]));
 266              $this->assertTrue($DB->record_exists('badge_issued', ['userid' => $u2->id]));
 267              $this->assertTrue($DB->record_exists('badge_criteria_met', ['userid' => $u1->id]));
 268              $this->assertTrue($DB->record_exists('badge_criteria_met', ['userid' => $u2->id]));
 269          };
 270          $assertnochange();
 271  
 272          provider::delete_data_for_all_users_in_context($sysctx);
 273          $assertnochange();
 274  
 275          provider::delete_data_for_all_users_in_context($c1ctx);
 276          $assertnochange();
 277  
 278          provider::delete_data_for_all_users_in_context($u1ctx);
 279          $this->assertTrue($DB->record_exists('badge', ['usercreated' => $u1->id]));
 280          $this->assertTrue($DB->record_exists('badge', ['usermodified' => $u1->id]));
 281          $this->assertTrue($DB->record_exists('badge', ['usercreated' => $u2->id]));
 282          $this->assertTrue($DB->record_exists('badge', ['usermodified' => $u2->id]));
 283          $this->assertFalse($DB->record_exists('badge_backpack', ['userid' => $u1->id]));
 284          $this->assertTrue($DB->record_exists('badge_backpack', ['userid' => $u2->id]));
 285          $this->assertFalse($DB->record_exists('badge_manual_award', ['recipientid' => $u1->id]));
 286          $this->assertTrue($DB->record_exists('badge_manual_award', ['recipientid' => $u2->id]));
 287          $this->assertFalse($DB->record_exists('badge_issued', ['userid' => $u1->id]));
 288          $this->assertTrue($DB->record_exists('badge_issued', ['userid' => $u2->id]));
 289          $this->assertFalse($DB->record_exists('badge_criteria_met', ['userid' => $u1->id]));
 290          $this->assertTrue($DB->record_exists('badge_criteria_met', ['userid' => $u2->id]));
 291      }
 292  
 293      public function test_export_data_for_user() {
 294          global $DB;
 295  
 296          $yes = transform::yesno(true);
 297          $no = transform::yesno(false);
 298  
 299          $dg = $this->getDataGenerator();
 300          $u1 = $dg->create_user();
 301          $u2 = $dg->create_user();
 302          $u3 = $dg->create_user();
 303          $c1 = $dg->create_course();
 304          $sysctx = context_system::instance();
 305          $c1ctx = context_course::instance($c1->id);
 306          $u1ctx = context_user::instance($u1->id);
 307          $u2ctx = context_user::instance($u2->id);
 308  
 309          $b1 = $this->create_badge(['usercreated' => $u3->id]);
 310          $this->endorse_badge(['badgeid' => $b1->id]);
 311          $this->align_badge(['badgeid' => $b1->id], ' (1)');
 312          $this->align_badge(['badgeid' => $b1->id], ' (2)');
 313          $b2 = $this->create_badge(['type' => BADGE_TYPE_COURSE, 'courseid' => $c1->id, 'usermodified' => $u3->id]);
 314          $this->relate_badge($b1->id, $b2->id);
 315          $b3 = $this->create_badge();
 316          $b3crit = $this->create_criteria_manual($b3->id);
 317          $b4 = $this->create_badge();
 318  
 319          // Create things for user 2, to check it's not exported it.
 320          $this->create_issued(['badgeid' => $b4->id, 'userid' => $u2->id]);
 321          helper::create_fake_backpack(['userid' => $u2->id, 'email' => $u2->email]);
 322          $this->create_manual_award(['badgeid' => $b1->id, 'recipientid' => $u2->id, 'issuerid' => $u3->id]);
 323  
 324          // Create a set of stuff for u1.
 325          $this->create_issued(['badgeid' => $b1->id, 'userid' => $u1->id, 'uniquehash' => 'yoohoo']);
 326          $this->create_manual_award(['badgeid' => $b2->id, 'recipientid' => $u1->id, 'issuerid' => $u3->id]);
 327          $b3crit->mark_complete($u1->id);
 328          helper::create_fake_backpack(['userid' => $u1->id, 'email' => $u1->email]);
 329  
 330          // Check u1.
 331          writer::reset();
 332          provider::export_user_data(new approved_contextlist($u1, 'core_badges', [$u1ctx->id, $u2ctx->id,
 333              $sysctx->id, $c1ctx->id]));
 334          $this->assertFalse(writer::with_context($u2ctx)->has_any_data());
 335          $this->assertFalse(writer::with_context($sysctx)->has_any_data());
 336          $this->assertFalse(writer::with_context($c1ctx)->has_any_data());
 337  
 338          $path = [get_string('badges', 'core_badges'), "{$b1->name} ({$b1->id})"];
 339          $data = writer::with_context($u1ctx)->get_data($path);
 340          $this->assertEquals($b1->name, $data->name);
 341          $this->assertEquals($b1->version, $data->version);
 342          $this->assertEquals($b1->language, $data->language);
 343          $this->assertEquals($b1->imageauthorname, $data->imageauthorname);
 344          $this->assertEquals($b1->imageauthoremail, $data->imageauthoremail);
 345          $this->assertEquals($b1->imageauthorurl, $data->imageauthorurl);
 346          $this->assertEquals($b1->imagecaption, $data->imagecaption);
 347          $this->assertNotEmpty($data->issued);
 348          $this->assertEmpty($data->manual_award);
 349          $this->assertEmpty($data->criteria_met);
 350          $this->assertFalse(isset($data->course));
 351          $this->assertEquals('yoohoo', $data->issued['unique_hash']);
 352          $this->assertNull($data->issued['expires_on']);
 353  
 354          $this->assertNotEmpty($data->endorsement);
 355          $this->assertNotEmpty($data->endorsement['issuername']);
 356          $this->assertNotEmpty($data->endorsement['issuerurl']);
 357          $this->assertNotEmpty($data->endorsement['issueremail']);
 358          $this->assertNotEmpty($data->endorsement['claimid']);
 359          $this->assertNotEmpty($data->endorsement['claimcomment']);
 360          $this->assertNotEmpty($data->endorsement['dateissued']);
 361  
 362          $this->assertNotEmpty($data->related_badge);
 363          $this->assertNotEmpty($data->related_badge[0]);
 364          $this->assertEquals($data->related_badge[0]['badgeid'], $b2->id);
 365          $this->assertEquals($data->related_badge[0]['badgename'], $b2->name);
 366  
 367          $this->assertNotEmpty($data->alignment);
 368          $this->assertNotEmpty($data->alignment[0]);
 369          $this->assertNotEmpty($data->alignment[0]['targetname']);
 370          $this->assertNotEmpty($data->alignment[0]['targeturl']);
 371          $this->assertNotEmpty($data->alignment[0]['targetdescription']);
 372          $this->assertNotEmpty($data->alignment[0]['targetframework']);
 373          $this->assertNotEmpty($data->alignment[0]['targetcode']);
 374          $this->assertNotEmpty($data->alignment[1]);
 375          $this->assertNotEmpty($data->alignment[1]['targetname']);
 376          $this->assertNotEmpty($data->alignment[1]['targeturl']);
 377          $this->assertNotEmpty($data->alignment[1]['targetdescription']);
 378          $this->assertNotEmpty($data->alignment[1]['targetframework']);
 379          $this->assertNotEmpty($data->alignment[1]['targetcode']);
 380  
 381          $path = [get_string('badges', 'core_badges'), "{$b2->name} ({$b2->id})"];
 382          $data = writer::with_context($u1ctx)->get_data($path);
 383          $this->assertEquals($b2->name, $data->name);
 384          $this->assertEmpty($data->issued);
 385          $this->assertNotEmpty($data->manual_award);
 386          $this->assertEmpty($data->criteria_met);
 387          $this->assertEquals($c1->fullname, $data->course);
 388          $this->assertEquals($u3->id, $data->manual_award['issuer']);
 389  
 390          $path = [get_string('badges', 'core_badges'), "{$b3->name} ({$b3->id})"];
 391          $data = writer::with_context($u1ctx)->get_data($path);
 392          $this->assertEquals($b3->name, $data->name);
 393          $this->assertEmpty($data->issued);
 394          $this->assertEmpty($data->manual_award);
 395          $this->assertNotEmpty($data->criteria_met);
 396          $this->assertNotFalse(strpos($data->criteria_met[0], get_string('criteria_descr_2', 'core_badges', 'ALL')));
 397  
 398          $path = [get_string('badges', 'core_badges')];
 399          $data = writer::with_context($u1ctx)->get_related_data($path, 'backpacks');
 400          $this->assertCount(1, $data->backpacks);
 401          $this->assertEquals($u1->email, $data->backpacks[0]['email']);
 402  
 403          // Confirm we do not have u2.
 404          $path = [get_string('badges', 'core_badges'), "{$b4->name} ({$b4->id})"];
 405          $data = writer::with_context($u1ctx)->get_data($path);
 406          $this->assertEmpty($data);
 407          $data = writer::with_context($u2ctx)->get_data($path);
 408          $this->assertEmpty($data);
 409  
 410          // Export for u3.
 411          writer::reset();
 412          $path = [get_string('badges', 'core_badges')];
 413          provider::export_user_data(new approved_contextlist($u3, 'core_badges', [$u1ctx->id, $u2ctx->id,
 414              $sysctx->id, $c1ctx->id]));
 415  
 416          $data = writer::with_context($u2ctx)->get_related_data($path, 'manual_awards');
 417          $this->assertCount(1, $data->badges);
 418          $this->assertEquals($b1->name, $data->badges[0]['name']);
 419          $this->assertEquals($yes, $data->badges[0]['issued_by_you']);
 420          $this->assertEquals('Manager', $data->badges[0]['issuer_role']);
 421  
 422          $data = writer::with_context($sysctx)->get_data($path);
 423          $this->assertCount(1, $data->badges);
 424          $this->assertEquals($b1->name, $data->badges[0]['name']);
 425          $this->assertEquals($yes, $data->badges[0]['created_by_you']);
 426          $this->assertEquals($no, $data->badges[0]['modified_by_you']);
 427  
 428          $data = writer::with_context($c1ctx)->get_data($path);
 429          $this->assertCount(1, $data->badges);
 430          $this->assertEquals($b2->name, $data->badges[0]['name']);
 431          $this->assertEquals($no, $data->badges[0]['created_by_you']);
 432          $this->assertEquals($yes, $data->badges[0]['modified_by_you']);
 433  
 434          $data = writer::with_context($u1ctx)->get_related_data($path, 'manual_awards');
 435          $this->assertCount(1, $data->badges);
 436          $this->assertEquals($b3->name, $data->badges[0]['name']);
 437          $this->assertEquals($yes, $data->badges[0]['issued_by_you']);
 438          $this->assertEquals('Manager', $data->badges[0]['issuer_role']);
 439      }
 440  
 441      /**
 442       * Test that only users within a user, system and course context are fetched.
 443       */
 444      public function test_get_users_in_context() {
 445          $component = 'core_badges';
 446  
 447          // Create course1.
 448          $course1 = $this->getDataGenerator()->create_course();
 449          $coursecontext1 = context_course::instance($course1->id);
 450          // Create course2.
 451          $course2 = $this->getDataGenerator()->create_course();
 452          $coursecontext2 = context_course::instance($course2->id);
 453          // Create user1.
 454          $user1 = $this->getDataGenerator()->create_user();
 455          $usercontext1 = context_user::instance($user1->id);
 456          // Create user2.
 457          $user2 = $this->getDataGenerator()->create_user();
 458          $usercontext2 = context_user::instance($user2->id);
 459          // Create user3.
 460          $user3 = $this->getDataGenerator()->create_user();
 461          $usercontext3 = context_user::instance($user3->id);
 462  
 463          // The list of users in usercontext1 should not return anything yet (related data still haven't been created).
 464          $userlist1 = new \core_privacy\local\request\userlist($usercontext1, $component);
 465          provider::get_users_in_context($userlist1);
 466          $this->assertCount(0, $userlist1);
 467          // The list of users in coursecontext1 should not return anything yet (related data still haven't been created).
 468          $userlist2 = new \core_privacy\local\request\userlist($coursecontext1, $component);
 469          provider::get_users_in_context($userlist2);
 470          $this->assertCount(0, $userlist2);
 471          // The list of users in systemcontext should not return anything yet (related data still haven't been created).
 472          $systemcontext = context_system::instance();
 473          $userlist3 = new \core_privacy\local\request\userlist($systemcontext, $component);
 474          provider::get_users_in_context($userlist3);
 475          $this->assertCount(0, $userlist3);
 476  
 477          // Assert that we find contexts where we created/modified a badge.
 478          $this->create_badge(['usercreated' => $user1->id, 'usermodified' => $user2->id]);
 479          $badge1 = $this->create_badge(['usercreated' => $user2->id, 'type' => BADGE_TYPE_COURSE, 'courseid' => $course1->id]);
 480          $badge2 = $this->create_badge(['usercreated' => $user3->id, 'usermodified' => $user1->id]);
 481  
 482          $this->create_manual_award(['recipientid' => $user2->id, 'issuerid' => $user1->id, 'badgeid' => $badge1->id]);
 483          $this->create_manual_award(['recipientid' => $user3->id, 'issuerid' => $user2->id, 'badgeid' => $badge1->id]);
 484          $this->create_manual_award(['recipientid' => $user1->id, 'issuerid' => $user2->id, 'badgeid' => $badge2->id]);
 485  
 486          helper::create_fake_backpack(['userid' => $user2->id]);
 487          $this->create_issued(['badgeid' => $badge2->id, 'userid' => $user3->id]);
 488  
 489          $crit = $this->create_criteria_manual($badge1->id);
 490          $crit->mark_complete($user3->id);
 491  
 492          // The list of users for user context should return user1 and user2.
 493          provider::get_users_in_context($userlist1);
 494          $this->assertCount(2, $userlist1);
 495          $this->assertTrue(in_array($user1->id, $userlist1->get_userids()));
 496          $this->assertTrue(in_array($user2->id, $userlist1->get_userids()));
 497  
 498          // The list of users for course context should return user2.
 499          provider::get_users_in_context($userlist2);
 500          $this->assertCount(1, $userlist2);
 501          $this->assertTrue(in_array($user2->id, $userlist2->get_userids()));
 502  
 503          // The list of users for system context should return user1, user2 and user3.
 504          provider::get_users_in_context($userlist3);
 505          $this->assertCount(3, $userlist3);
 506          $this->assertTrue(in_array($user1->id, $userlist3->get_userids()));
 507          $this->assertTrue(in_array($user2->id, $userlist3->get_userids()));
 508          $this->assertTrue(in_array($user3->id, $userlist3->get_userids()));
 509      }
 510  
 511      /**
 512       * Test that data for users in approved userlist is deleted.
 513       */
 514      public function test_delete_data_for_users() {
 515          $component = 'core_badges';
 516  
 517          // Create course1.
 518          $course1 = $this->getDataGenerator()->create_course();
 519          $coursecontext1 = context_course::instance($course1->id);
 520          // Create course2.
 521          $course2 = $this->getDataGenerator()->create_course();
 522          $coursecontext2 = context_course::instance($course2->id);
 523          // Create user1.
 524          $user1 = $this->getDataGenerator()->create_user();
 525          $usercontext1 = context_user::instance($user1->id);
 526          // Create user2.
 527          $user2 = $this->getDataGenerator()->create_user();
 528          $usercontext2 = context_user::instance($user2->id);
 529          // Create user3.
 530          $user3 = $this->getDataGenerator()->create_user();
 531          $usercontext3 = context_user::instance($user3->id);
 532  
 533          $this->create_badge(['usercreated' => $user1->id, 'usermodified' => $user2->id]);
 534          $badge1 = $this->create_badge(['usercreated' => $user2->id, 'type' => BADGE_TYPE_COURSE, 'courseid' => $course1->id]);
 535          $badge2 = $this->create_badge(['usercreated' => $user3->id, 'type' => BADGE_TYPE_COURSE, 'courseid' => $course2->id,
 536              'usermodified' => $user1->id]);
 537  
 538          $this->create_manual_award(['recipientid' => $user2->id, 'issuerid' => $user1->id, 'badgeid' => $badge1->id]);
 539          $this->create_manual_award(['recipientid' => $user3->id, 'issuerid' => $user2->id, 'badgeid' => $badge1->id]);
 540          $this->create_manual_award(['recipientid' => $user1->id, 'issuerid' => $user2->id, 'badgeid' => $badge2->id]);
 541  
 542          helper::create_fake_backpack(['userid' => $user2->id]);
 543          $this->create_issued(['badgeid' => $badge2->id, 'userid' => $user3->id]);
 544  
 545          $crit = $this->create_criteria_manual($badge1->id);
 546          $crit->mark_complete($user3->id);
 547  
 548          // The list of users for usercontext2 context should return users.
 549          $userlist1 = new \core_privacy\local\request\userlist($usercontext2, $component);
 550          provider::get_users_in_context($userlist1);
 551          $this->assertCount(2, $userlist1);
 552          $this->assertTrue(in_array($user1->id, $userlist1->get_userids()));
 553          $this->assertTrue(in_array($user2->id, $userlist1->get_userids()));
 554  
 555          // The list of users for coursecontext2 context should return users.
 556          $userlist2 = new \core_privacy\local\request\userlist($coursecontext2, $component);
 557          provider::get_users_in_context($userlist2);
 558          $this->assertCount(2, $userlist2);
 559          $this->assertTrue(in_array($user1->id, $userlist2->get_userids()));
 560          $this->assertTrue(in_array($user3->id, $userlist2->get_userids()));
 561  
 562          // The list of users for system context should return users.
 563          $systemcontext = context_system::instance();
 564          $userlist3 = new \core_privacy\local\request\userlist($systemcontext, $component);
 565          provider::get_users_in_context($userlist3);
 566          $this->assertCount(2, $userlist3);
 567          $this->assertTrue(in_array($user1->id, $userlist3->get_userids()));
 568          $this->assertTrue(in_array($user2->id, $userlist3->get_userids()));
 569  
 570          // Delete the data for user1 in usercontext2.
 571          $approvedlist = new approved_userlist($usercontext2, $component, [$user1->id]);
 572          // Delete using delete_data_for_user. No data for users in usercontext2 should be removed.
 573          provider::delete_data_for_users($approvedlist);
 574          // The list of users for usercontext2 context should still return user1, user2.
 575          $userlist1 = new \core_privacy\local\request\userlist($usercontext2, $component);
 576          provider::get_users_in_context($userlist1);
 577          $this->assertCount(2, $userlist1);
 578          $this->assertTrue(in_array($user1->id, $userlist1->get_userids()));
 579          $this->assertTrue(in_array($user2->id, $userlist1->get_userids()));
 580  
 581          // Delete the data for user2 in usercontext2.
 582          $approvedlist = new approved_userlist($usercontext2, $component, [$user2->id]);
 583          // Delete using delete_data_for_user. The user data in usercontext2 should be removed.
 584          provider::delete_data_for_users($approvedlist);
 585          // The list of users for usercontext2 context should not return any users.
 586          $userlist1 = new \core_privacy\local\request\userlist($usercontext2, $component);
 587          provider::get_users_in_context($userlist1);
 588          $this->assertCount(0, $userlist1);
 589  
 590          // The list of users for coursecontext2 context should return the previous users.
 591          $userlist2 = new \core_privacy\local\request\userlist($coursecontext2, $component);
 592          provider::get_users_in_context($userlist2);
 593          $this->assertCount(2, $userlist2);
 594  
 595          // The list of users for system context should return the previous users.
 596          $systemcontext = context_system::instance();
 597          $userlist3 = new \core_privacy\local\request\userlist($systemcontext, $component);
 598          provider::get_users_in_context($userlist3);
 599          $this->assertCount(2, $userlist3);
 600  
 601          // Make sure data is only deleted in the user context, nothing in course or system.
 602          // Convert $userlist2 into an approved_contextlist.
 603          $approvedlist = new approved_userlist($coursecontext2, $component, $userlist2->get_userids());
 604          provider::delete_data_for_users($approvedlist);
 605  
 606          // The list of users for coursecontext2 context should still return the user data.
 607          $userlist2 = new \core_privacy\local\request\userlist($coursecontext2, $component);
 608          provider::get_users_in_context($userlist2);
 609          $this->assertCount(2, $userlist2);
 610      }
 611  
 612      /**
 613       * Create a badge.
 614       *
 615       * @param array $params Parameters.
 616       * @return object
 617       */
 618      protected function create_badge(array $params = []) {
 619          global $DB, $USER;
 620          $record = (object) array_merge([
 621              'name' => "Test badge with 'apostrophe' and other friends (<>&@#)",
 622              'description' => "Testing badges",
 623              'timecreated' => time(),
 624              'timemodified' => time(),
 625              'usercreated' => $USER->id,
 626              'usermodified' => $USER->id,
 627              'issuername' => "Test issuer",
 628              'issuerurl' => "http://issuer-url.domain.co.nz",
 629              'issuercontact' => "issuer@example.com",
 630              'expiredate' => null,
 631              'expireperiod' => null,
 632              'type' => BADGE_TYPE_SITE,
 633              'courseid' => null,
 634              'messagesubject' => "Test message subject",
 635              'message' => "Test message body",
 636              'attachment' => 1,
 637              'notification' => 0,
 638              'status' => BADGE_STATUS_ACTIVE,
 639              'version' => OPEN_BADGES_V2,
 640              'language' => 'en',
 641              'imageauthorname' => 'Image author',
 642              'imageauthoremail' => 'author@example.com',
 643              'imageauthorurl' => 'http://image.example.com/',
 644              'imagecaption' => 'Image caption'
 645          ], $params);
 646          $record->id = $DB->insert_record('badge', $record);
 647  
 648          return $record;
 649      }
 650  
 651      /**
 652       * Relate a badge.
 653       *
 654       * @param int $badgeid The badge ID.
 655       * @param int $relatedbadgeid The related badge ID.
 656       * @return object
 657       */
 658      protected function relate_badge(int $badgeid, int $relatedbadgeid) {
 659          global $DB;
 660          $record = (object) [
 661              'badgeid' => $badgeid,
 662              'relatedbadgeid' => $relatedbadgeid
 663          ];
 664          $record->id = $DB->insert_record('badge_related', $record);
 665  
 666          return $record;
 667      }
 668  
 669      /**
 670       * Align a badge.
 671       *
 672       * @param array $params Parameters.
 673       * @return object
 674       */
 675      protected function align_badge(array $params = [], $suffix = '') {
 676          global $DB;
 677          $record = (object) array_merge([
 678              'badgeid' => null,
 679              'targetname' => "Alignment name" . $suffix,
 680              'targeturl' => "http://issuer-url.domain.co.nz",
 681              'targetdescription' => "Description" . $suffix,
 682              'targetframework' => "Framework" . $suffix,
 683              'targetcode' => "Code . $suffix"
 684          ], $params);
 685          $record->id = $DB->insert_record('badge_alignment', $record);
 686  
 687          return $record;
 688      }
 689  
 690      /**
 691       * Endorse a badge.
 692       *
 693       * @param array $params Parameters.
 694       * @return object
 695       */
 696      protected function endorse_badge(array $params = []) {
 697          global $DB;
 698          $record = (object) array_merge([
 699              'badgeid' => null,
 700              'issuername' => "External issuer name",
 701              'issuerurl' => "http://issuer-url.domain.co.nz",
 702              'issueremail' => "issuer@example.com",
 703              'claimid' => "Claim ID",
 704              'claimcomment' => "Claim comment",
 705              'dateissued' => time()
 706          ], $params);
 707          $record->id = $DB->insert_record('badge_endorsement', $record);
 708  
 709          return $record;
 710      }
 711  
 712      /**
 713       * Create a criteria of type badge.
 714       *
 715       * @param int $badgeid The badge ID.
 716       * @param array $params Parameters.
 717       * @return object
 718       */
 719      protected function create_criteria_badge($badgeid, array $params = []) {
 720          $badge = new badge($badgeid);
 721          if (empty($badge->criteria)) {
 722              $overall = award_criteria::build(['criteriatype' => BADGE_CRITERIA_TYPE_OVERALL, 'badgeid' => $badge->id]);
 723              $overall->save(['agg' => BADGE_CRITERIA_AGGREGATION_ALL]);
 724          }
 725  
 726          $criteria = award_criteria::build([
 727              'badgeid' => $badge->id,
 728              'criteriatype' => BADGE_CRITERIA_TYPE_BADGE,
 729          ]);
 730  
 731          if (isset($params['badgeid'])) {
 732              $params['badge_' . $params['badgeid']] = $params['badgeid'];
 733              unset($params['badgeid']);
 734          }
 735  
 736          $criteria->save($params);
 737          $badge = new badge($badgeid);
 738          return $badge->criteria[BADGE_CRITERIA_TYPE_BADGE];
 739      }
 740  
 741      /**
 742       * Create a criteria of type manual.
 743       *
 744       * @param int $badgeid The badge ID.
 745       * @param array $params Parameters.
 746       * @return object
 747       */
 748      protected function create_criteria_manual($badgeid, array $params = []) {
 749          global $DB;
 750  
 751          $badge = new badge($badgeid);
 752          if (empty($badge->criteria)) {
 753              $overall = award_criteria::build(['criteriatype' => BADGE_CRITERIA_TYPE_OVERALL, 'badgeid' => $badge->id]);
 754              $overall->save(['agg' => BADGE_CRITERIA_AGGREGATION_ALL]);
 755          }
 756  
 757          $criteria = award_criteria::build([
 758              'badgeid' => $badge->id,
 759              'criteriatype' => BADGE_CRITERIA_TYPE_MANUAL,
 760          ]);
 761  
 762          $managerroleid = $DB->get_field_select('role', 'id', 'shortname = ?', ['manager'], IGNORE_MULTIPLE);
 763          if (empty($params)) {
 764              $params = [
 765                  'role_' . $managerroleid = $managerroleid
 766              ];
 767          }
 768  
 769          $criteria->save($params);
 770          $badge = new badge($badgeid);
 771          return $badge->criteria[BADGE_CRITERIA_TYPE_MANUAL];
 772      }
 773  
 774      /**
 775       * Create a badge issued.
 776       *
 777       * @param array $params Parameters.
 778       * @return object
 779       */
 780      protected function create_issued(array $params = []) {
 781          global $DB, $USER;
 782          $record = (object) array_merge([
 783              'badgeid' => null,
 784              'userid' => null,
 785              'uniquehash' => random_string(40),
 786              'dateissued' => time(),
 787              'dateexpire' => null,
 788              'visible' => 1,
 789              'issuernotified' => null,
 790          ], $params);
 791          $record->id = $DB->insert_record('badge_issued', $record);
 792          return $record;
 793      }
 794  
 795      /**
 796       * Create a manual award.
 797       *
 798       * @param array $params Parameters.
 799       * @return object
 800       */
 801      protected function create_manual_award(array $params = []) {
 802          global $DB, $USER;
 803          $record = (object) array_merge([
 804              'badgeid' => null,
 805              'recipientid' => null,
 806              'issuerid' => $USER->id,
 807              'issuerrole' => $DB->get_field_select('role', 'id', 'shortname = ?', ['manager'], IGNORE_MULTIPLE),
 808              'datemet' => time()
 809          ], $params);
 810          $record->id = $DB->insert_record('badge_manual_award', $record);
 811          return $record;
 812      }
 813  
 814  }