Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.
   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  namespace mod_data;
  18  
  19  use context_module;
  20  use moodle_url;
  21  use core_component;
  22  use stdClass;
  23  
  24  /**
  25   * Manager tests class for mod_data.
  26   *
  27   * @package    mod_data
  28   * @category   test
  29   * @copyright  2022 Ferran Recio <ferran@moodle.com>
  30   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  31   * @coversDefaultClass \mod_data\manager
  32   */
  33  class manager_test extends \advanced_testcase {
  34  
  35      /**
  36       * Test for static create methods.
  37       *
  38       * @covers ::create_from_instance
  39       * @covers ::create_from_coursemodule
  40       * @covers ::create_from_data_record
  41       */
  42      public function test_create() {
  43  
  44          $this->resetAfterTest();
  45          $this->setAdminUser();
  46  
  47          $course = $this->getDataGenerator()->create_course();
  48          $activity = $this->getDataGenerator()->create_module(manager::MODULE, ['course' => $course]);
  49          $cm = get_coursemodule_from_id(manager::MODULE, $activity->cmid, 0, false, MUST_EXIST);
  50          $context = context_module::instance($cm->id);
  51  
  52          $manager = manager::create_from_instance($activity);
  53          $manageractivity = $manager->get_instance();
  54          $this->assertEquals($activity->id, $manageractivity->id);
  55          $managercm = $manager->get_coursemodule();
  56          $this->assertEquals($cm->id, $managercm->id);
  57          $managercontext = $manager->get_context();
  58          $this->assertEquals($context->id, $managercontext->id);
  59  
  60          $manager = manager::create_from_coursemodule($cm);
  61          $manageractivity = $manager->get_instance();
  62          $this->assertEquals($activity->id, $manageractivity->id);
  63          $managercm = $manager->get_coursemodule();
  64          $this->assertEquals($cm->id, $managercm->id);
  65          $managercontext = $manager->get_context();
  66          $this->assertEquals($context->id, $managercontext->id);
  67  
  68          $datarecord = (object)[
  69              'dataid' => $activity->id,
  70              'id' => 0,
  71              'userid' => 0,
  72              'groupid' => 0,
  73              'timecreated' => 0,
  74              'timemodified' => 0,
  75              'approved' => 0,
  76          ];
  77          $manager = manager::create_from_data_record($datarecord);
  78          $manageractivity = $manager->get_instance();
  79          $this->assertEquals($activity->id, $manageractivity->id);
  80          $managercm = $manager->get_coursemodule();
  81          $this->assertEquals($cm->id, $managercm->id);
  82          $managercontext = $manager->get_context();
  83          $this->assertEquals($context->id, $managercontext->id);
  84      }
  85  
  86      /**
  87       * Test set_module_viewed
  88       * @covers ::set_module_viewed
  89       */
  90      public function test_set_module_viewed() {
  91          global $CFG;
  92  
  93          $CFG->enablecompletion = 1;
  94          $this->resetAfterTest();
  95          $this->setAdminUser();
  96  
  97          // Setup test data.
  98          $course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]);
  99          $instance = $this->getDataGenerator()->create_module(
 100              'data',
 101              ['course' => $course->id],
 102              ['completion' => 2, 'completionview' => 1]
 103          );
 104          $manager = manager::create_from_instance($instance);
 105          $context = $manager->get_context();
 106          $cm = $manager->get_coursemodule();
 107  
 108          // Trigger and capture the event.
 109          $sink = $this->redirectEvents();
 110  
 111          $manager->set_module_viewed($course);
 112  
 113          $events = $sink->get_events();
 114          // 2 additional events thanks to completion.
 115          $this->assertCount(3, $events);
 116          $event = array_shift($events);
 117  
 118          // Checking that the event contains the expected values.
 119          $this->assertInstanceOf('\mod_data\event\course_module_viewed', $event);
 120          $this->assertEquals($context, $event->get_context());
 121          $moodleurl = new moodle_url('/mod/data/view.php', ['id' => $cm->id]);
 122          $this->assertEquals($moodleurl, $event->get_url());
 123          $this->assertEventContextNotUsed($event);
 124          $this->assertNotEmpty($event->get_name());
 125  
 126          // Check completion status.
 127          $completion = new \completion_info($course);
 128          $completiondata = $completion->get_data($cm);
 129          $this->assertEquals(1, $completiondata->completionstate);
 130      }
 131  
 132      /**
 133       * Test set_template_viewed
 134       * @covers ::set_template_viewed
 135       */
 136      public function test_set_template_viewed() {
 137          $this->resetAfterTest();
 138          $this->setAdminUser();
 139  
 140          // Setup test data.
 141          $course = $this->getDataGenerator()->create_course();
 142          $instance = $this->getDataGenerator()->create_module(
 143              'data',
 144              ['course' => $course->id]
 145          );
 146          $manager = manager::create_from_instance($instance);
 147          $context = $manager->get_context();
 148  
 149          // Trigger and capture the event.
 150          $sink = $this->redirectEvents();
 151  
 152          $manager->set_template_viewed();
 153  
 154          $events = $sink->get_events();
 155          $this->assertCount(1, $events);
 156          $event = reset($events);
 157  
 158          // Checking that the event contains the expected values.
 159          $this->assertInstanceOf('mod_data\event\template_viewed', $event);
 160          $this->assertEquals($context, $event->get_context());
 161          $moodleurl = new moodle_url('/mod/data/templates.php', ['d' => $instance->id]);
 162          $this->assertEquals($moodleurl, $event->get_url());
 163          $this->assertEventContextNotUsed($event);
 164          $this->assertNotEmpty($event->get_name());
 165      }
 166  
 167      /**
 168       * Test for has_records().
 169       *
 170       * @covers ::has_records
 171       */
 172      public function test_has_records() {
 173          global $DB;
 174  
 175          $this->resetAfterTest();
 176  
 177          $course = $this->getDataGenerator()->create_course();
 178          $data = $this->getDataGenerator()->create_module(manager::MODULE, ['course' => $course]);
 179          $manager = manager::create_from_instance($data);
 180  
 181          // Empty database should return false.
 182          $this->assertFalse($manager->has_records());
 183  
 184          // Create data record.
 185          $datarecords = new \stdClass();
 186          $datarecords->userid = '2';
 187          $datarecords->dataid = $data->id;
 188          $datarecords->id = $DB->insert_record('data_records', $datarecords);
 189  
 190          // Database with records should return true.
 191          $this->assertTrue($manager->has_records());
 192      }
 193  
 194      /**
 195       * Test for has_fields().
 196       *
 197       * @covers ::has_fields
 198       */
 199      public function test_has_fields() {
 200          $this->resetAfterTest();
 201  
 202          $course = $this->getDataGenerator()->create_course();
 203          $activity = $this->getDataGenerator()->create_module(manager::MODULE, ['course' => $course]);
 204          $manager = manager::create_from_instance($activity);
 205  
 206          // Empty database should return false.
 207          $this->assertFalse($manager->has_fields());
 208  
 209          // Add a field to the activity.
 210          $datagenerator = $this->getDataGenerator()->get_plugin_generator('mod_data');
 211          $fieldrecord = new \stdClass();
 212          $fieldrecord->name = 'field1';
 213          $fieldrecord->type = 'text';
 214          $datagenerator->create_field($fieldrecord, $activity);
 215  
 216          // Database with fields should return true.
 217          $this->assertTrue($manager->has_fields());
 218      }
 219  
 220      /**
 221       * Test for get_available_presets().
 222       *
 223       * @covers ::get_available_presets
 224       */
 225      public function test_get_available_presets() {
 226          global $DB;
 227  
 228          $this->resetAfterTest();
 229  
 230          $course = $this->getDataGenerator()->create_course();
 231          $user = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
 232          $this->setUser($user);
 233  
 234          $activity = $this->getDataGenerator()->create_module(manager::MODULE, ['course' => $course]);
 235          $cm = get_coursemodule_from_id(manager::MODULE, $activity->cmid, 0, false, MUST_EXIST);
 236  
 237          // Check available presets meet the datapreset plugins when there are no any preset saved by users.
 238          $datapresetplugins = core_component::get_plugin_list('datapreset');
 239          $manager = manager::create_from_coursemodule($cm);
 240          $presets = $manager->get_available_presets();
 241          $this->assertCount(count($datapresetplugins), $presets);
 242          // Confirm that, at least, the "Image gallery" is one of them.
 243          $namepresets = array_map(function($preset) {
 244              return $preset->name;
 245          }, $presets);
 246          $this->assertContains('Image gallery', $namepresets);
 247  
 248          // Login as admin and create some presets saved manually by users.
 249          $this->setAdminUser();
 250          $plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_data');
 251          $savedpresets = [];
 252          for ($i = 1; $i <= 3; $i++) {
 253              $preset = (object) [
 254                  'name' => 'Preset name ' . $i,
 255              ];
 256              $plugingenerator->create_preset($activity, $preset);
 257              $savedpresets[] = $preset;
 258          }
 259          $savedpresetsnames = array_map(function($preset) {
 260              return $preset->name;
 261          }, $savedpresets);
 262          $this->setUser($user);
 263  
 264          // Check available presets meet the datapreset plugins + presets saved manually by users.
 265          $presets = $manager->get_available_presets();
 266          $this->assertCount(count($datapresetplugins) + count($savedpresets), $presets);
 267          // Confirm that, apart from the "Image gallery" preset, the ones created manually have been also returned.
 268          $namepresets = array_map(function($preset) {
 269              return $preset->name;
 270          }, $presets);
 271          $this->assertContains('Image gallery', $namepresets);
 272          foreach ($savedpresets as $savedpreset) {
 273              $this->assertContains($savedpreset->name, $namepresets);
 274          }
 275          // Check all the presets have the proper value for the isplugin attribute.
 276          foreach ($presets as $preset) {
 277              if (in_array($preset->name, $savedpresetsnames)) {
 278                  $this->assertFalse($preset->isplugin);
 279              } else {
 280                  $this->assertTrue($preset->isplugin);
 281              }
 282          }
 283  
 284          // Unassign the capability to the teacher role and check that only plugin presets are returned (because the saved presets
 285          // have been created by admin).
 286          $teacherrole = $DB->get_record('role', ['shortname' => 'teacher']);
 287          unassign_capability('mod/data:viewalluserpresets', $teacherrole->id);
 288          $presets = $manager->get_available_presets();
 289          $this->assertCount(count($datapresetplugins), $presets);
 290          // Confirm that, at least, the "Image gallery" is one of them.
 291          $namepresets = array_map(function($preset) {
 292              return $preset->name;
 293          }, $presets);
 294          $this->assertContains('Image gallery', $namepresets);
 295          foreach ($savedpresets as $savedpreset) {
 296              $this->assertNotContains($savedpreset->name, $namepresets);
 297          }
 298  
 299          // Create a preset with the current user and check that, although the viewalluserpresets is not assigned to the teacher
 300          // role, the preset is returned because the teacher is the owner.
 301          $savedpreset = (object) [
 302              'name' => 'Preset created by teacher',
 303          ];
 304          $plugingenerator->create_preset($activity, $savedpreset);
 305          $presets = $manager->get_available_presets();
 306          // The presets total is all the plugin presets plus the preset created by the teacher.
 307          $this->assertCount(count($datapresetplugins) + 1, $presets);
 308          // Confirm that, at least, the "Image gallery" is one of them.
 309          $namepresets = array_map(function($preset) {
 310              return $preset->name;
 311          }, $presets);
 312          $this->assertContains('Image gallery', $namepresets);
 313          // Confirm that savedpresets are still not returned.
 314          foreach ($savedpresets as $savedpreset) {
 315              $this->assertNotContains($savedpreset->name, $namepresets);
 316          }
 317          // Confirm the new preset created by the teacher is returned too.
 318          $this->assertContains('Preset created by teacher', $namepresets);
 319      }
 320  
 321      /**
 322       * Test for get_available_plugin_presets().
 323       *
 324       * @covers ::get_available_plugin_presets
 325       */
 326      public function test_get_available_plugin_presets() {
 327          $this->resetAfterTest();
 328          $this->setAdminUser();
 329  
 330          $course = $this->getDataGenerator()->create_course();
 331          $activity = $this->getDataGenerator()->create_module(manager::MODULE, ['course' => $course]);
 332  
 333          // Check available plugin presets meet the datapreset plugins.
 334          $datapresetplugins = core_component::get_plugin_list('datapreset');
 335          $manager = manager::create_from_instance($activity);
 336          $presets = $manager->get_available_plugin_presets();
 337          $this->assertCount(count($datapresetplugins), $presets);
 338          // Confirm that, at least, the "Image gallery" is one of them.
 339          $namepresets = array_map(function($preset) {
 340              return $preset->name;
 341          }, $presets);
 342          $this->assertContains('Image gallery', $namepresets);
 343  
 344          // Create a preset saved manually by users.
 345          $savedpreset = (object) [
 346              'name' => 'Preset name 1',
 347          ];
 348          $plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_data');
 349          $plugingenerator->create_preset($activity, $savedpreset);
 350  
 351          // Check available plugin presets don't contain the preset saved manually.
 352          $presets = $manager->get_available_plugin_presets();
 353          $this->assertCount(count($datapresetplugins), $presets);
 354          // Confirm that, at least, the "Image gallery" is one of them.
 355          $namepresets = array_map(function($preset) {
 356              return $preset->name;
 357          }, $presets);
 358          $this->assertContains('Image gallery', $namepresets);
 359          // Confirm that the preset saved manually hasn't been returned.
 360          $this->assertNotContains($savedpreset->name, $namepresets);
 361          // Check all the presets have the proper value for the isplugin attribute.
 362          foreach ($presets as $preset) {
 363              $this->assertTrue($preset->isplugin);
 364          }
 365      }
 366  
 367      /**
 368       * Test for get_available_saved_presets().
 369       *
 370       * @covers ::get_available_saved_presets
 371       */
 372      public function test_get_available_saved_presets() {
 373          global $DB;
 374  
 375          $this->resetAfterTest();
 376  
 377          $course = $this->getDataGenerator()->create_course();
 378          $user = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
 379          $this->setUser($user);
 380  
 381          $activity = $this->getDataGenerator()->create_module(manager::MODULE, ['course' => $course]);
 382          $cm = get_coursemodule_from_id(manager::MODULE, $activity->cmid, 0, false, MUST_EXIST);
 383  
 384          // Check available saved presets is empty (because, for now, no user preset has been created).
 385          $manager = manager::create_from_coursemodule($cm);
 386          $presets = $manager->get_available_saved_presets();
 387          $this->assertCount(0, $presets);
 388  
 389          // Create some presets saved manually by the admin user.
 390          $this->setAdminUser();
 391          $plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_data');
 392          $savedpresets = [];
 393          for ($i = 1; $i <= 3; $i++) {
 394              $preset = (object) [
 395                  'name' => 'Preset name ' . $i,
 396              ];
 397              $plugingenerator->create_preset($activity, $preset);
 398              $savedpresets[] = $preset;
 399          }
 400          // Create one more preset saved manually by the teacher user.
 401          $this->setUser($user);
 402          $teacherpreset = (object) [
 403              'name' => 'Preset created by teacher',
 404          ];
 405          $plugingenerator->create_preset($activity, $teacherpreset);
 406          $savedpresets[] = $teacherpreset;
 407  
 408          $savedpresetsnames = array_map(function($preset) {
 409              return $preset->name;
 410          }, $savedpresets);
 411  
 412          // Check available saved presets only contain presets saved manually by users.
 413          $presets = $manager->get_available_saved_presets();
 414          $this->assertCount(count($savedpresets), $presets);
 415          // Confirm that it contains only the presets created manually.
 416          foreach ($presets as $preset) {
 417              $this->assertContains($preset->name, $savedpresetsnames);
 418              $this->assertFalse($preset->isplugin);
 419          }
 420  
 421          // Unassign the mod/data:viewalluserpresets capability to the teacher role and check that saved presets are not returned.
 422          $teacherrole = $DB->get_record('role', ['shortname' => 'teacher']);
 423          unassign_capability('mod/data:viewalluserpresets', $teacherrole->id);
 424  
 425          $presets = $manager->get_available_saved_presets();
 426          $this->assertCount(1, $presets);
 427          $preset = reset($presets);
 428          $this->assertEquals($teacherpreset->name, $preset->name);
 429      }
 430  
 431      /**
 432       * Test for can_view_preset().
 433       *
 434       * @covers ::can_view_preset
 435       * @dataProvider can_view_preset_provider
 436       * @param string $rolename the user role name
 437       * @param bool $ownpreset if the preset belongs to the user
 438       * @param bool|null $useridparam if the method should be called with a user id param
 439       * @param bool $plugin if the preset is a plugin or not
 440       * @param bool $expected the expected result
 441       */
 442      public function test_can_view_preset(string $rolename, bool $ownpreset, ?bool $useridparam, bool $plugin, bool $expected) {
 443  
 444          $this->resetAfterTest();
 445  
 446          $course = $this->getDataGenerator()->create_course();
 447          $user = $this->getDataGenerator()->create_and_enrol($course, $rolename);
 448          $activity = $this->getDataGenerator()->create_module(manager::MODULE, ['course' => $course]);
 449          $cm = get_coursemodule_from_id(manager::MODULE, $activity->cmid, 0, false, MUST_EXIST);
 450          $manager = manager::create_from_coursemodule($cm);
 451  
 452          // Create preset.
 453          if ($ownpreset) {
 454              $this->setUser($user);
 455          } else {
 456              $this->setAdminUser();
 457          }
 458  
 459          if ($plugin) {
 460              $preset = preset::create_from_plugin($manager, 'imagegallery');
 461          } else {
 462              $plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_data');
 463              $preset = $plugingenerator->create_preset($activity, (object)['name' => 'Preset name']);
 464          }
 465  
 466          // Setup user param.
 467          if ($useridparam) {
 468              // Login as a different user to validate the userid param is working.
 469              $otheruser = $this->getDataGenerator()->create_user();
 470              $this->setUser($otheruser);
 471              $useridparam = $user->id;
 472          } else {
 473              $this->setUser($user);
 474          }
 475  
 476          $result = $manager->can_view_preset($preset, $useridparam);
 477          $this->assertEquals($expected, $result);
 478      }
 479  
 480      /**
 481       * Data provider for test_can_view_preset.
 482       *
 483       * @return array
 484       */
 485      public function can_view_preset_provider(): array {
 486          return [
 487              // User presets.
 488              'Teacher owned preset without user id param' => [
 489                  'rolename' => 'editingteacher',
 490                  'ownpreset' => true,
 491                  'useridparam' => null,
 492                  'plugin' => false,
 493                  'expected' => true,
 494              ],
 495              'Teacher owned preset with user id param' => [
 496                  'rolename' => 'editingteacher',
 497                  'ownpreset' => true,
 498                  'useridparam' => true,
 499                  'plugin' => false,
 500                  'expected' => true,
 501              ],
 502              'Teacher not owned preset without user id param' => [
 503                  'rolename' => 'editingteacher',
 504                  'ownpreset' => false,
 505                  'useridparam' => null,
 506                  'plugin' => false,
 507                  'expected' => true,
 508              ],
 509              'Teacher not owned preset with user id param' => [
 510                  'rolename' => 'editingteacher',
 511                  'ownpreset' => false,
 512                  'useridparam' => true,
 513                  'plugin' => false,
 514                  'expected' => true,
 515              ],
 516              'Student owned preset without user id param' => [
 517                  'rolename' => 'student',
 518                  'ownpreset' => true,
 519                  'useridparam' => null,
 520                  'plugin' => false,
 521                  'expected' => true,
 522              ],
 523              'Student owned preset with user id param' => [
 524                  'rolename' => 'student',
 525                  'ownpreset' => true,
 526                  'useridparam' => true,
 527                  'plugin' => false,
 528                  'expected' => true,
 529              ],
 530              'Student not owned preset without user id param' => [
 531                  'rolename' => 'student',
 532                  'ownpreset' => false,
 533                  'useridparam' => null,
 534                  'plugin' => false,
 535                  'expected' => false,
 536              ],
 537              'Student not owned preset with user id param' => [
 538                  'rolename' => 'student',
 539                  'ownpreset' => false,
 540                  'useridparam' => true,
 541                  'plugin' => false,
 542                  'expected' => false,
 543              ],
 544              // Plugin presets.
 545              'Teacher plugin preset without user id param' => [
 546                  'rolename' => 'editingteacher',
 547                  'ownpreset' => false,
 548                  'useridparam' => null,
 549                  'plugin' => true,
 550                  'expected' => true,
 551              ],
 552              'Teacher plugin preset with user id param' => [
 553                  'rolename' => 'editingteacher',
 554                  'ownpreset' => false,
 555                  'useridparam' => true,
 556                  'plugin' => true,
 557                  'expected' => true,
 558              ],
 559              'Student plugin preset without user id param' => [
 560                  'rolename' => 'student',
 561                  'ownpreset' => false,
 562                  'useridparam' => null,
 563                  'plugin' => true,
 564                  'expected' => true,
 565              ],
 566              'Student plugin preset with user id param' => [
 567                  'rolename' => 'student',
 568                  'ownpreset' => false,
 569                  'useridparam' => true,
 570                  'plugin' => true,
 571                  'expected' => true,
 572              ],
 573          ];
 574      }
 575  
 576      /**
 577       * Test for can_export_entries().
 578       *
 579       * @covers ::can_export_entries
 580       */
 581      public function test_can_export_entries() {
 582          global $DB;
 583  
 584          $this->resetAfterTest();
 585  
 586          // Create course with activity and enrol users.
 587          $course = $this->getDataGenerator()->create_course();
 588          $teacherrole = $DB->get_record('role', ['shortname' => 'teacher']);
 589          $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
 590          $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
 591          $activity = $this->getDataGenerator()->create_module(manager::MODULE, ['course' => $course]);
 592          $cm = get_coursemodule_from_id(manager::MODULE, $activity->cmid, 0, false, MUST_EXIST);
 593          $manager = manager::create_from_coursemodule($cm);
 594  
 595          // Add a field.
 596          /** @var \mod_data_generator $generator */
 597          $generator = $this->getDataGenerator()->get_plugin_generator('mod_data');
 598          $fieldrecord = (object)[
 599              'name' => 'myfield',
 600              'type' => 'text',
 601          ];
 602          $field = $generator->create_field($fieldrecord, $activity);
 603  
 604          // Teacher with default capabilities can export entries.
 605          $this->setUser($teacher);
 606          $result = $manager->can_export_entries();
 607          $this->assertEquals(true, $result);
 608  
 609          // Teacher without exportallentries can still export entries.
 610          unassign_capability('mod/data:exportallentries', $teacherrole->id);
 611          $result = $manager->can_export_entries();
 612          $this->assertEquals(true, $result);
 613  
 614          // Teacher without exportallentries and exportentry can't export entries (unless they have created some entries).
 615          unassign_capability('mod/data:exportentry', $teacherrole->id);
 616          $result = $manager->can_export_entries();
 617          $this->assertEquals(false, $result);
 618  
 619          $generator->create_entry(
 620              $activity,
 621              [$field->field->id => 'Example entry'],
 622          );
 623          $result = $manager->can_export_entries();
 624          $this->assertEquals(true, $result);
 625  
 626          // Student without entries can't export.
 627          $this->setUser($student);
 628          $result = $manager->can_export_entries();
 629          $this->assertEquals(false, $result);
 630  
 631          // However, student who has created any entry, can export.
 632          $generator->create_entry(
 633              $activity,
 634              [$field->field->id => 'Another example entry'],
 635          );
 636          $this->setUser($student);
 637          $result = $manager->can_export_entries();
 638          $this->assertEquals(true, $result);
 639      }
 640  
 641      /*
 642       * Test reset_all_templates.
 643       *
 644       * @covers ::reset_all_templates
 645       */
 646      public function test_reset_all_templates() {
 647          global $DB;
 648  
 649          $this->resetAfterTest();
 650          $this->setAdminUser();
 651  
 652          // Setup test data.
 653          $course = $this->getDataGenerator()->create_course();
 654          $instance = $this->getDataGenerator()->create_module(
 655              'data',
 656              ['course' => $course->id]
 657          );
 658          $manager = manager::create_from_instance($instance);
 659  
 660          // Create some initial templates.
 661          $initialtemplates = new stdClass();
 662          foreach (manager::TEMPLATES_LIST as $templatename => $unused) {
 663              $initialtemplates->$templatename = "Initial $templatename";
 664          }
 665          $manager->update_templates($initialtemplates);
 666          $instance = $manager->get_instance();
 667          $record = $DB->get_record('data', ['id' => $instance->id]);
 668          foreach (manager::TEMPLATES_LIST as $templatename => $unused) {
 669              $this->assertEquals($initialtemplates->$templatename, $instance->$templatename);
 670              $this->assertEquals($initialtemplates->$templatename, $record->$templatename);
 671          }
 672  
 673          // Reset all templates.
 674          $result = $manager->reset_all_templates();
 675          $this->assertTrue($result);
 676          $instance = $manager->get_instance();
 677          $record = $DB->get_record('data', ['id' => $instance->id]);
 678          foreach (manager::TEMPLATES_LIST as $templatename => $unused) {
 679              $this->assertEquals('', $instance->$templatename);
 680              $this->assertEquals('', $record->$templatename);
 681          }
 682      }
 683  
 684      /**
 685       * Test reset_template.
 686       *
 687       * @covers ::reset_template
 688       * @dataProvider reset_template_provider
 689       * @param string $templatetoreset the template to reset
 690       * @param string[] $expected the expected templates to be reset
 691       */
 692      public function test_reset_template(string $templatetoreset, array $expected) {
 693          global $DB;
 694  
 695          $this->resetAfterTest();
 696          $this->setAdminUser();
 697  
 698          // Setup test data.
 699          $course = $this->getDataGenerator()->create_course();
 700          $instance = $this->getDataGenerator()->create_module(
 701              'data',
 702              ['course' => $course->id]
 703          );
 704          $manager = manager::create_from_instance($instance);
 705  
 706          // Create some initial templates.
 707          $initialtemplates = new stdClass();
 708          foreach (manager::TEMPLATES_LIST as $templatename => $unused) {
 709              $initialtemplates->$templatename = "Initial $templatename";
 710          }
 711          $manager->update_templates($initialtemplates);
 712          $instance = $manager->get_instance();
 713          $record = $DB->get_record('data', ['id' => $instance->id]);
 714          foreach (manager::TEMPLATES_LIST as $templatename => $unused) {
 715              $this->assertEquals($initialtemplates->$templatename, $instance->$templatename);
 716              $this->assertEquals($initialtemplates->$templatename, $record->$templatename);
 717          }
 718  
 719          // Reset template.
 720          $result = $manager->reset_template($templatetoreset);
 721          $this->assertTrue($result);
 722          $instance = $manager->get_instance();
 723          $record = $DB->get_record('data', ['id' => $instance->id]);
 724          foreach (manager::TEMPLATES_LIST as $templatename => $unused) {
 725              if (in_array($templatename, $expected)) {
 726                  $this->assertEquals('', $instance->$templatename);
 727                  $this->assertEquals('', $record->$templatename);
 728              } else {
 729                  $this->assertEquals($initialtemplates->$templatename, $instance->$templatename);
 730                  $this->assertEquals($initialtemplates->$templatename, $record->$templatename);
 731              }
 732          }
 733      }
 734  
 735      /**
 736       * Data provider for test_reset_templatet.
 737       *
 738       * @return array
 739       */
 740      public function reset_template_provider(): array {
 741          return [
 742              // User presets.
 743              'listtemplate' => [
 744                  'templatename' => 'listtemplate',
 745                  'expected' => ['listtemplate', 'listtemplateheader', 'listtemplatefooter'],
 746              ],
 747              'singletemplate' => [
 748                  'templatename' => 'singletemplate',
 749                  'expected' => ['singletemplate'],
 750              ],
 751              'asearchtemplate' => [
 752                  'templatename' => 'asearchtemplate',
 753                  'expected' => ['asearchtemplate'],
 754              ],
 755              'addtemplate' => [
 756                  'templatename' => 'addtemplate',
 757                  'expected' => ['addtemplate'],
 758              ],
 759              'rsstemplate' => [
 760                  'templatename' => 'rsstemplate',
 761                  'expected' => ['rsstemplate', 'rsstitletemplate'],
 762              ],
 763              'csstemplate' => [
 764                  'templatename' => 'csstemplate',
 765                  'expected' => ['csstemplate'],
 766              ],
 767              'jstemplate' => [
 768                  'templatename' => 'jstemplate',
 769                  'expected' => ['jstemplate'],
 770              ],
 771          ];
 772      }
 773  }