Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 39 and 401] [Versions 401 and 402] [Versions 401 and 403]

   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 quizaccess_seb;
  18  
  19  defined('MOODLE_INTERNAL') || die();
  20  
  21  require_once (__DIR__ . '/test_helper_trait.php');
  22  
  23  /**
  24   * PHPUnit tests for settings_provider.
  25   *
  26   * @package   quizaccess_seb
  27   * @author    Andrew Madden <andrewmadden@catalyst-au.net>
  28   * @copyright 2020 Catalyst IT
  29   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  30   */
  31  class settings_provider_test extends \advanced_testcase {
  32      use \quizaccess_seb_test_helper_trait;
  33  
  34      /**
  35       * Mocked quiz form instance.
  36       * @var \mod_quiz_mod_form
  37       */
  38      protected $mockedquizform;
  39  
  40      /**
  41       * Test moodle form.
  42       * @var \MoodleQuickForm
  43       */
  44      protected $mockedform;
  45  
  46      /**
  47       * Context for testing.
  48       * @var \context
  49       */
  50      protected $context;
  51  
  52      /**
  53       * Test user.
  54       * @var \stdClass
  55       */
  56      protected $user;
  57  
  58      /**
  59       * Test role ID.
  60       * @var int
  61       */
  62      protected $roleid;
  63  
  64      /**
  65       * Helper method to set up form mocks.
  66       */
  67      protected function set_up_form_mocks() {
  68          if (empty($this->context)) {
  69              $this->context = \context_module::instance($this->quiz->cmid);
  70          }
  71  
  72          $this->mockedquizform = $this->createMock('mod_quiz_mod_form');
  73          $this->mockedquizform->method('get_context')->willReturn($this->context);
  74          $this->mockedquizform->method('get_instance')->willReturn($this->quiz->id);
  75          $this->mockedform = new \MoodleQuickForm('test', 'post', '');
  76          $this->mockedform->addElement('static', 'security');
  77      }
  78  
  79      /**
  80       * Helper method to set up user and role for testing.
  81       */
  82      protected function set_up_user_and_role() {
  83          $this->user = $this->getDataGenerator()->create_user();
  84  
  85          $this->setUser($this->user);
  86          $this->roleid = $this->getDataGenerator()->create_role();
  87  
  88          $this->getDataGenerator()->role_assign($this->roleid, $this->user->id, $this->context->id);
  89      }
  90  
  91      /**
  92       * Capability data for testing.
  93       *
  94       * @return array
  95       */
  96      public function settings_capability_data_provider() {
  97          $data = [];
  98  
  99          // Build first level SEB config settings. Any of this setting let us use SEB manual config.
 100          foreach (settings_provider::get_seb_settings_map()[settings_provider::USE_SEB_CONFIG_MANUALLY] as $name => $children) {
 101              if (key_exists($name, settings_provider::get_seb_config_elements())) {
 102                  $cap = settings_provider::build_setting_capability_name($name);
 103                  $data[] = [$cap];
 104              }
 105          }
 106  
 107          return $data;
 108      }
 109  
 110      /**
 111       * Test that settings types to be added to quiz settings, are part of quiz_settings persistent class.
 112       */
 113      public function test_setting_elements_are_part_of_quiz_settings_table() {
 114          $dbsettings = (array) (new quiz_settings())->to_record();
 115          $settingelements = settings_provider::get_seb_config_elements();
 116          $settingelements = (array) $this->strip_all_prefixes((object) $settingelements);
 117  
 118          // Get all elements to be added to form, that are not in the persistent quiz_settings class.
 119          $diffelements = array_diff_key($settingelements, $dbsettings);
 120  
 121          $this->assertEmpty($diffelements);
 122      }
 123  
 124      /**
 125       * Make sure that all SEB settings have related capabilities.
 126       */
 127      public function test_that_all_seb_settings_have_capabilities() {
 128          foreach (settings_provider::get_seb_config_elements() as $name => $notused) {
 129              $this->assertNotEmpty(get_capability_info(settings_provider::build_setting_capability_name($name)));
 130          }
 131      }
 132  
 133      /**
 134       * Test that setting defaults only refer to settings defined in setting types.
 135       */
 136      public function test_setting_defaults_are_part_of_file_types() {
 137          $settingelements = settings_provider::get_seb_config_elements();
 138          $settingdefaults = settings_provider::get_seb_config_element_defaults();
 139  
 140          // Get all defaults that have no matching element in settings types.
 141          $diffelements = array_diff_key($settingdefaults, $settingelements);
 142  
 143          $this->assertEmpty($diffelements);
 144      }
 145  
 146      /**
 147       * Test that setting types only refer to settings defined in setting types.
 148       */
 149      public function test_setting_types_are_part_of_file_types() {
 150          $settingelements = settings_provider::get_seb_config_elements();
 151          $settingtypes = settings_provider::get_seb_config_element_types();
 152  
 153          // Get all defaults that have no matching element in settings types.
 154          $diffelements = array_diff_key($settingtypes, $settingelements);
 155  
 156          $this->assertEmpty($diffelements);
 157      }
 158  
 159      /**
 160       * Helper method to assert hide if element.
 161       * @param hideif_rule $hideif Rule to check.
 162       * @param string $element Expected element.
 163       * @param string $dependantname Expected dependant element name.
 164       * @param string $condition Expected condition.
 165       * @param mixed $value Expected value.
 166       */
 167      protected function assert_hide_if(hideif_rule $hideif, $element, $dependantname, $condition, $value) {
 168          $this->assertEquals($element, $hideif->get_element());
 169          $this->assertEquals($dependantname, $hideif->get_dependantname());
 170          $this->assertEquals($condition, $hideif->get_condition());
 171          $this->assertEquals($value, $hideif->get_dependantvalue());
 172      }
 173  
 174      /**
 175       * Test hideif rules.
 176       */
 177      public function test_hideifs() {
 178          $settinghideifs = settings_provider::get_quiz_hideifs();
 179  
 180          $this->assertCount(23, $settinghideifs);
 181  
 182          $this->assertArrayHasKey('seb_templateid', $settinghideifs);
 183          $this->assertCount(1, $settinghideifs['seb_templateid']);
 184          $this->assert_hide_if(
 185              $settinghideifs['seb_templateid'][0],
 186              'seb_templateid',
 187              'seb_requiresafeexambrowser',
 188              'noteq',
 189              settings_provider::USE_SEB_TEMPLATE
 190          );
 191  
 192          $this->assertArrayHasKey('filemanager_sebconfigfile', $settinghideifs);
 193          $this->assertCount(1, $settinghideifs['filemanager_sebconfigfile']);
 194          $this->assert_hide_if(
 195              $settinghideifs['filemanager_sebconfigfile'][0],
 196              'filemanager_sebconfigfile',
 197              'seb_requiresafeexambrowser',
 198              'noteq',
 199              settings_provider::USE_SEB_UPLOAD_CONFIG
 200          );
 201  
 202          $this->assertArrayHasKey('seb_showsebtaskbar', $settinghideifs);
 203          $this->assertCount(1, $settinghideifs['seb_showsebtaskbar']);
 204          $this->assert_hide_if(
 205              $settinghideifs['seb_showsebtaskbar'][0],
 206              'seb_showsebtaskbar',
 207              'seb_requiresafeexambrowser',
 208              'noteq',
 209              settings_provider::USE_SEB_CONFIG_MANUALLY
 210          );
 211  
 212          $this->assertArrayHasKey('seb_showwificontrol', $settinghideifs);
 213          $this->assertCount(2, $settinghideifs['seb_showwificontrol']);
 214          $this->assert_hide_if(
 215              $settinghideifs['seb_showwificontrol'][0],
 216              'seb_showwificontrol',
 217              'seb_requiresafeexambrowser',
 218              'noteq',
 219              settings_provider::USE_SEB_CONFIG_MANUALLY
 220          );
 221          $this->assert_hide_if(
 222              $settinghideifs['seb_showwificontrol'][1],
 223              'seb_showwificontrol',
 224              'seb_showsebtaskbar',
 225              'eq',
 226              0
 227          );
 228  
 229          $this->assertArrayHasKey('seb_showreloadbutton', $settinghideifs);
 230          $this->assertCount(2, $settinghideifs['seb_showreloadbutton']);
 231          $this->assert_hide_if(
 232              $settinghideifs['seb_showreloadbutton'][0],
 233              'seb_showreloadbutton',
 234              'seb_requiresafeexambrowser',
 235              'noteq',
 236              settings_provider::USE_SEB_CONFIG_MANUALLY
 237          );
 238          $this->assert_hide_if(
 239              $settinghideifs['seb_showreloadbutton'][1],
 240              'seb_showreloadbutton',
 241              'seb_showsebtaskbar',
 242              'eq',
 243              0
 244          );
 245  
 246          $this->assertArrayHasKey('seb_showtime', $settinghideifs);
 247          $this->assertCount(2, $settinghideifs['seb_showtime']);
 248          $this->assert_hide_if(
 249              $settinghideifs['seb_showtime'][0],
 250              'seb_showtime',
 251              'seb_requiresafeexambrowser',
 252              'noteq',
 253              settings_provider::USE_SEB_CONFIG_MANUALLY
 254          );
 255          $this->assert_hide_if(
 256              $settinghideifs['seb_showtime'][1],
 257              'seb_showtime',
 258              'seb_showsebtaskbar',
 259              'eq',
 260              0
 261          );
 262  
 263          $this->assertArrayHasKey('seb_showkeyboardlayout', $settinghideifs);
 264          $this->assertCount(2, $settinghideifs['seb_showkeyboardlayout']);
 265          $this->assert_hide_if(
 266              $settinghideifs['seb_showkeyboardlayout'][0],
 267              'seb_showkeyboardlayout',
 268              'seb_requiresafeexambrowser',
 269              'noteq',
 270              settings_provider::USE_SEB_CONFIG_MANUALLY
 271          );
 272          $this->assert_hide_if(
 273              $settinghideifs['seb_showkeyboardlayout'][1],
 274              'seb_showkeyboardlayout',
 275              'seb_showsebtaskbar',
 276              'eq',
 277              0
 278          );
 279  
 280          $this->assertArrayHasKey('seb_allowuserquitseb', $settinghideifs);
 281          $this->assertCount(3, $settinghideifs['seb_allowuserquitseb']);
 282          $this->assert_hide_if(
 283              $settinghideifs['seb_allowuserquitseb'][0],
 284              'seb_allowuserquitseb',
 285              'seb_requiresafeexambrowser',
 286              'eq',
 287              settings_provider::USE_SEB_NO
 288          );
 289          $this->assert_hide_if(
 290              $settinghideifs['seb_allowuserquitseb'][1],
 291              'seb_allowuserquitseb',
 292              'seb_requiresafeexambrowser',
 293              'eq',
 294              settings_provider::USE_SEB_CLIENT_CONFIG
 295          );
 296          $this->assert_hide_if(
 297              $settinghideifs['seb_allowuserquitseb'][2],
 298              'seb_allowuserquitseb',
 299              'seb_requiresafeexambrowser',
 300              'eq',
 301              settings_provider::USE_SEB_UPLOAD_CONFIG
 302          );
 303  
 304          $this->assertArrayHasKey('seb_quitpassword', $settinghideifs);
 305          $this->assertCount(4, $settinghideifs['seb_quitpassword']);
 306          $this->assert_hide_if(
 307              $settinghideifs['seb_quitpassword'][0],
 308              'seb_quitpassword',
 309              'seb_requiresafeexambrowser',
 310              'eq',
 311              settings_provider::USE_SEB_NO
 312          );
 313          $this->assert_hide_if(
 314              $settinghideifs['seb_quitpassword'][1],
 315              'seb_quitpassword',
 316              'seb_requiresafeexambrowser',
 317              'eq',
 318              settings_provider::USE_SEB_CLIENT_CONFIG
 319          );
 320          $this->assert_hide_if(
 321              $settinghideifs['seb_quitpassword'][2],
 322              'seb_quitpassword',
 323              'seb_requiresafeexambrowser',
 324              'eq',
 325              settings_provider::USE_SEB_UPLOAD_CONFIG
 326          );
 327          $this->assert_hide_if(
 328              $settinghideifs['seb_quitpassword'][3],
 329              'seb_quitpassword',
 330              'seb_allowuserquitseb',
 331              'eq',
 332              0
 333          );
 334  
 335          $this->assertArrayHasKey('seb_linkquitseb', $settinghideifs);
 336          $this->assertCount(1, $settinghideifs['seb_linkquitseb']);
 337          $this->assert_hide_if(
 338              $settinghideifs['seb_linkquitseb'][0],
 339              'seb_linkquitseb',
 340              'seb_requiresafeexambrowser',
 341              'noteq',
 342              settings_provider::USE_SEB_CONFIG_MANUALLY
 343          );
 344  
 345          $this->assertArrayHasKey('seb_userconfirmquit', $settinghideifs);
 346          $this->assertCount(1, $settinghideifs['seb_userconfirmquit']);
 347          $this->assert_hide_if(
 348              $settinghideifs['seb_userconfirmquit'][0],
 349              'seb_userconfirmquit',
 350              'seb_requiresafeexambrowser',
 351              'noteq',
 352              settings_provider::USE_SEB_CONFIG_MANUALLY
 353          );
 354  
 355          $this->assertArrayHasKey('seb_enableaudiocontrol', $settinghideifs);
 356          $this->assertCount(1, $settinghideifs['seb_enableaudiocontrol']);
 357          $this->assert_hide_if(
 358              $settinghideifs['seb_enableaudiocontrol'][0],
 359              'seb_enableaudiocontrol',
 360              'seb_requiresafeexambrowser',
 361              'noteq',
 362              settings_provider::USE_SEB_CONFIG_MANUALLY
 363          );
 364  
 365          $this->assertArrayHasKey('seb_muteonstartup', $settinghideifs);
 366          $this->assertCount(2, $settinghideifs['seb_muteonstartup']);
 367          $this->assert_hide_if(
 368              $settinghideifs['seb_muteonstartup'][0],
 369              'seb_muteonstartup',
 370              'seb_requiresafeexambrowser',
 371              'noteq',
 372              settings_provider::USE_SEB_CONFIG_MANUALLY
 373          );
 374          $this->assert_hide_if(
 375              $settinghideifs['seb_muteonstartup'][1],
 376              'seb_muteonstartup',
 377              'seb_enableaudiocontrol',
 378              'eq',
 379              0
 380          );
 381  
 382          $this->assertArrayHasKey('seb_allowspellchecking', $settinghideifs);
 383          $this->assertCount(1, $settinghideifs['seb_allowspellchecking']);
 384          $this->assert_hide_if(
 385              $settinghideifs['seb_allowspellchecking'][0],
 386              'seb_allowspellchecking',
 387              'seb_requiresafeexambrowser',
 388              'noteq',
 389              settings_provider::USE_SEB_CONFIG_MANUALLY
 390          );
 391  
 392          $this->assertArrayHasKey('seb_allowreloadinexam', $settinghideifs);
 393          $this->assertCount(1, $settinghideifs['seb_allowreloadinexam']);
 394          $this->assert_hide_if(
 395              $settinghideifs['seb_allowreloadinexam'][0],
 396              'seb_allowreloadinexam',
 397              'seb_requiresafeexambrowser',
 398              'noteq',
 399              settings_provider::USE_SEB_CONFIG_MANUALLY
 400          );
 401  
 402          $this->assertArrayHasKey('seb_activateurlfiltering', $settinghideifs);
 403          $this->assertCount(1, $settinghideifs['seb_activateurlfiltering']);
 404          $this->assert_hide_if(
 405              $settinghideifs['seb_activateurlfiltering'][0],
 406              'seb_activateurlfiltering',
 407              'seb_requiresafeexambrowser',
 408              'noteq',
 409              settings_provider::USE_SEB_CONFIG_MANUALLY
 410          );
 411  
 412          $this->assertArrayHasKey('seb_filterembeddedcontent', $settinghideifs);
 413          $this->assertCount(2, $settinghideifs['seb_filterembeddedcontent']);
 414          $this->assert_hide_if(
 415              $settinghideifs['seb_filterembeddedcontent'][0],
 416              'seb_filterembeddedcontent',
 417              'seb_requiresafeexambrowser',
 418              'noteq',
 419              settings_provider::USE_SEB_CONFIG_MANUALLY
 420          );
 421          $this->assert_hide_if(
 422              $settinghideifs['seb_filterembeddedcontent'][1],
 423              'seb_filterembeddedcontent',
 424              'seb_activateurlfiltering',
 425              'eq',
 426              0
 427          );
 428  
 429          $this->assertArrayHasKey('seb_expressionsallowed', $settinghideifs);
 430          $this->assertCount(2, $settinghideifs['seb_expressionsallowed']);
 431          $this->assert_hide_if(
 432              $settinghideifs['seb_expressionsallowed'][0],
 433              'seb_expressionsallowed',
 434              'seb_requiresafeexambrowser',
 435              'noteq',
 436              settings_provider::USE_SEB_CONFIG_MANUALLY
 437          );
 438          $this->assert_hide_if(
 439              $settinghideifs['seb_expressionsallowed'][1],
 440              'seb_expressionsallowed',
 441              'seb_activateurlfiltering',
 442              'eq',
 443              0
 444          );
 445  
 446          $this->assertArrayHasKey('seb_regexallowed', $settinghideifs);
 447          $this->assertCount(2, $settinghideifs['seb_regexallowed']);
 448          $this->assert_hide_if(
 449              $settinghideifs['seb_regexallowed'][0],
 450              'seb_regexallowed',
 451              'seb_requiresafeexambrowser',
 452              'noteq',
 453              settings_provider::USE_SEB_CONFIG_MANUALLY
 454          );
 455          $this->assert_hide_if(
 456              $settinghideifs['seb_regexallowed'][1],
 457              'seb_regexallowed',
 458              'seb_activateurlfiltering',
 459              'eq',
 460              0
 461          );
 462  
 463          $this->assertArrayHasKey('seb_expressionsblocked', $settinghideifs);
 464          $this->assertCount(2, $settinghideifs['seb_expressionsblocked']);
 465          $this->assert_hide_if(
 466              $settinghideifs['seb_expressionsblocked'][0],
 467              'seb_expressionsblocked',
 468              'seb_requiresafeexambrowser',
 469              'noteq',
 470              settings_provider::USE_SEB_CONFIG_MANUALLY
 471          );
 472          $this->assert_hide_if(
 473              $settinghideifs['seb_expressionsblocked'][1],
 474              'seb_expressionsblocked',
 475              'seb_activateurlfiltering',
 476              'eq',
 477              0
 478          );
 479  
 480          $this->assertArrayHasKey('seb_regexblocked', $settinghideifs);
 481          $this->assertCount(2, $settinghideifs['seb_regexblocked']);
 482          $this->assert_hide_if(
 483              $settinghideifs['seb_regexblocked'][0],
 484              'seb_regexblocked',
 485              'seb_requiresafeexambrowser',
 486              'noteq',
 487              settings_provider::USE_SEB_CONFIG_MANUALLY
 488          );
 489          $this->assert_hide_if(
 490              $settinghideifs['seb_regexblocked'][1],
 491              'seb_regexblocked',
 492              'seb_activateurlfiltering',
 493              'eq',
 494              0
 495          );
 496  
 497          $this->assertArrayHasKey('seb_showsebdownloadlink', $settinghideifs);
 498          $this->assertCount(1, $settinghideifs['seb_showsebdownloadlink']);
 499          $this->assert_hide_if(
 500              $settinghideifs['seb_showsebdownloadlink'][0],
 501              'seb_showsebdownloadlink',
 502              'seb_requiresafeexambrowser',
 503              'eq',
 504              settings_provider::USE_SEB_NO
 505          );
 506  
 507          $this->assertArrayHasKey('seb_allowedbrowserexamkeys', $settinghideifs);
 508          $this->assertCount(3, $settinghideifs['seb_allowedbrowserexamkeys']);
 509          $this->assert_hide_if(
 510              $settinghideifs['seb_allowedbrowserexamkeys'][0],
 511              'seb_allowedbrowserexamkeys',
 512              'seb_requiresafeexambrowser',
 513              'eq',
 514              settings_provider::USE_SEB_NO
 515          );
 516          $this->assert_hide_if(
 517              $settinghideifs['seb_allowedbrowserexamkeys'][1],
 518              'seb_allowedbrowserexamkeys',
 519              'seb_requiresafeexambrowser',
 520              'eq',
 521              settings_provider::USE_SEB_CONFIG_MANUALLY
 522          );
 523          $this->assert_hide_if(
 524              $settinghideifs['seb_allowedbrowserexamkeys'][2],
 525              'seb_allowedbrowserexamkeys',
 526              'seb_requiresafeexambrowser',
 527              'eq',
 528              settings_provider::USE_SEB_TEMPLATE
 529          );
 530      }
 531  
 532      /**
 533       * Test that setting hideif rules only refer to settings defined in setting types, including the conditions.
 534       */
 535      public function test_setting_hideifs_are_part_of_file_types() {
 536          $settingelements = settings_provider::get_seb_config_elements();
 537          $settinghideifs = settings_provider::get_quiz_hideifs();
 538  
 539          // Add known additional elements.
 540          $settingelements['seb_templateid'] = '';
 541          $settingelements['filemanager_sebconfigfile'] = '';
 542          $settingelements['seb_showsebdownloadlink'] = '';
 543          $settingelements['seb_allowedbrowserexamkeys'] = '';
 544  
 545          // Get all defaults that have no matching element in settings types.
 546          $diffelements = array_diff_key($settinghideifs, $settingelements);
 547  
 548          // Check no diff for elements to hide.
 549          $this->assertEmpty($diffelements);
 550  
 551          // Check each element's to hide conditions that each condition refers to element in settings types.
 552          foreach ($settinghideifs as $conditions) {
 553              foreach ($conditions as $condition) {
 554                  $this->assertTrue(array_key_exists($condition->get_element(), $settingelements));
 555              }
 556          }
 557      }
 558  
 559      /**
 560       * Test that exception thrown if we try to build capability name from the incorrect setting name.
 561       */
 562      public function test_build_setting_capability_name_incorrect_setting() {
 563          $this->expectException(\coding_exception::class);
 564          $this->expectExceptionMessage('Incorrect SEB quiz setting broken');
 565  
 566          $broken = settings_provider::build_setting_capability_name('broken');
 567      }
 568  
 569      /**
 570       * Test we can build capability name from the the setting name.
 571       */
 572      public function test_build_setting_capability_name_correct_setting() {
 573          foreach (settings_provider::get_seb_config_elements() as $name => $type) {
 574              $expected = 'quizaccess/seb:manage_' . $name;
 575              $actual = settings_provider::build_setting_capability_name($name);
 576  
 577              $this->assertSame($expected, $actual);
 578          }
 579      }
 580  
 581  
 582      /**
 583       * Test can check if can manage SEB settings respecting settings structure.
 584       */
 585      public function test_can_manage_seb_config_setting() {
 586          $this->resetAfterTest();
 587          $this->setAdminUser();
 588          $this->course = $this->getDataGenerator()->create_course();
 589  
 590          $this->quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $this->course->id]);
 591          $this->context = \context_module::instance($this->quiz->cmid);
 592  
 593          $this->set_up_user_and_role();
 594  
 595          foreach (settings_provider::get_seb_settings_map()[settings_provider::USE_SEB_CONFIG_MANUALLY] as $setting => $children) {
 596              // Skip not SEB setting.
 597              if ($setting == 'seb_showsebdownloadlink') {
 598                  continue;
 599              }
 600  
 601              $this->assertFalse(settings_provider::can_manage_seb_config_setting($setting, $this->context));
 602              foreach ($children as $child => $empty) {
 603                  $this->assertFalse(settings_provider::can_manage_seb_config_setting($child, $this->context));
 604  
 605                  // Assign child capability without having parent one. Should not have access to manage child.
 606                  $childcap = settings_provider::build_setting_capability_name($child);
 607                  assign_capability($childcap, CAP_ALLOW, $this->roleid, $this->context->id);
 608                  $this->assertFalse(settings_provider::can_manage_seb_config_setting($child, $this->context));
 609              }
 610  
 611              // Assign parent capability. Should be able to manage children now.
 612              $parentcap = settings_provider::build_setting_capability_name($setting);
 613              assign_capability($parentcap, CAP_ALLOW, $this->roleid, $this->context->id);
 614  
 615              $this->assertTrue(settings_provider::can_manage_seb_config_setting($setting, $this->context));
 616              foreach ($children as $child => $empty) {
 617                  $this->assertTrue(settings_provider::can_manage_seb_config_setting($child, $this->context));
 618              }
 619          }
 620      }
 621  
 622      /**
 623       * Test SEB usage options.
 624       *
 625       * @param string $settingcapability Setting capability to check manual option against.
 626       *
 627       * @dataProvider settings_capability_data_provider
 628       */
 629      public function test_get_requiresafeexambrowser_options($settingcapability) {
 630          $this->resetAfterTest();
 631          $this->setAdminUser();
 632          $this->course = $this->getDataGenerator()->create_course();
 633  
 634          $this->quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $this->course->id]);
 635          $this->context = \context_module::instance($this->quiz->cmid);
 636  
 637          $options = settings_provider::get_requiresafeexambrowser_options($this->context);
 638  
 639          $this->assertCount(4, $options);
 640          $this->assertTrue(array_key_exists(settings_provider::USE_SEB_NO, $options));
 641          $this->assertTrue(array_key_exists(settings_provider::USE_SEB_CONFIG_MANUALLY, $options));
 642          $this->assertFalse(array_key_exists(settings_provider::USE_SEB_TEMPLATE, $options));
 643          $this->assertTrue(array_key_exists(settings_provider::USE_SEB_UPLOAD_CONFIG, $options));
 644          $this->assertTrue(array_key_exists(settings_provider::USE_SEB_CLIENT_CONFIG, $options));
 645  
 646          // Create a template.
 647          $this->create_template();
 648  
 649          // The template options should be visible now.
 650          $options = settings_provider::get_requiresafeexambrowser_options($this->context);
 651          $this->assertCount(5, $options);
 652          $this->assertTrue(array_key_exists(settings_provider::USE_SEB_TEMPLATE, $options));
 653  
 654          // A new user does not have the capability to use the file manager and template.
 655          $this->set_up_user_and_role();
 656  
 657          $options = settings_provider::get_requiresafeexambrowser_options($this->context);
 658  
 659          $this->assertCount(2, $options);
 660          $this->assertFalse(array_key_exists(settings_provider::USE_SEB_CONFIG_MANUALLY, $options));
 661          $this->assertFalse(array_key_exists(settings_provider::USE_SEB_TEMPLATE, $options));
 662          $this->assertFalse(array_key_exists(settings_provider::USE_SEB_UPLOAD_CONFIG, $options));
 663          $this->assertTrue(array_key_exists(settings_provider::USE_SEB_CLIENT_CONFIG, $options));
 664          $this->assertTrue(array_key_exists(settings_provider::USE_SEB_NO, $options));
 665  
 666          assign_capability($settingcapability, CAP_ALLOW, $this->roleid, $this->context->id);
 667          $options = settings_provider::get_requiresafeexambrowser_options($this->context);
 668          $this->assertCount(3, $options);
 669          $this->assertTrue(array_key_exists(settings_provider::USE_SEB_CONFIG_MANUALLY, $options));
 670          $this->assertFalse(array_key_exists(settings_provider::USE_SEB_TEMPLATE, $options));
 671          $this->assertFalse(array_key_exists(settings_provider::USE_SEB_UPLOAD_CONFIG, $options));
 672          $this->assertTrue(array_key_exists(settings_provider::USE_SEB_CLIENT_CONFIG, $options));
 673          $this->assertTrue(array_key_exists(settings_provider::USE_SEB_NO, $options));
 674  
 675          assign_capability('quizaccess/seb:manage_seb_templateid', CAP_ALLOW, $this->roleid, $this->context->id);
 676          $options = settings_provider::get_requiresafeexambrowser_options($this->context);
 677          $this->assertCount(4, $options);
 678          $this->assertTrue(array_key_exists(settings_provider::USE_SEB_CONFIG_MANUALLY, $options));
 679          $this->assertTrue(array_key_exists(settings_provider::USE_SEB_TEMPLATE, $options));
 680          $this->assertFalse(array_key_exists(settings_provider::USE_SEB_UPLOAD_CONFIG, $options));
 681          $this->assertTrue(array_key_exists(settings_provider::USE_SEB_CLIENT_CONFIG, $options));
 682          $this->assertTrue(array_key_exists(settings_provider::USE_SEB_NO, $options));
 683  
 684          assign_capability('quizaccess/seb:manage_filemanager_sebconfigfile', CAP_ALLOW, $this->roleid, $this->context->id);
 685          $options = settings_provider::get_requiresafeexambrowser_options($this->context);
 686          $this->assertCount(5, $options);
 687          $this->assertTrue(array_key_exists(settings_provider::USE_SEB_CONFIG_MANUALLY, $options));
 688          $this->assertTrue(array_key_exists(settings_provider::USE_SEB_TEMPLATE, $options));
 689          $this->assertTrue(array_key_exists(settings_provider::USE_SEB_UPLOAD_CONFIG, $options));
 690          $this->assertTrue(array_key_exists(settings_provider::USE_SEB_CLIENT_CONFIG, $options));
 691          $this->assertTrue(array_key_exists(settings_provider::USE_SEB_NO, $options));
 692      }
 693  
 694      /**
 695       * Test SEB usage options with conflicting permissions.
 696       */
 697      public function test_get_requiresafeexambrowser_options_with_conflicting_permissions() {
 698          $this->resetAfterTest();
 699          $this->setAdminUser();
 700          $this->course = $this->getDataGenerator()->create_course();
 701  
 702          $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY);
 703          $this->context = \context_module::instance($this->quiz->cmid);
 704  
 705          $template = $this->create_template();
 706  
 707          $settings = quiz_settings::get_record(['quizid' => $this->quiz->id]);
 708          $settings->set('templateid', $template->get('id'));
 709          $settings->set('requiresafeexambrowser', settings_provider::USE_SEB_TEMPLATE);
 710          $settings->save();
 711  
 712          $this->set_up_user_and_role();
 713  
 714          $options = settings_provider::get_requiresafeexambrowser_options($this->context);
 715  
 716          // If there is nay conflict we return full list of options.
 717          $this->assertCount(5, $options);
 718          $this->assertTrue(array_key_exists(settings_provider::USE_SEB_TEMPLATE, $options));
 719      }
 720  
 721      /**
 722       * Test that SEB options and templates are frozen if conflicting permissions.
 723       */
 724      public function test_form_elements_are_frozen_if_conflicting_permissions() {
 725          $this->resetAfterTest();
 726          $this->setAdminUser();
 727          $this->course = $this->getDataGenerator()->create_course();
 728  
 729          $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY);
 730          $this->context = \context_module::instance($this->quiz->cmid);
 731  
 732          // Setup conflicting permissions.
 733          $template = $this->create_template();
 734          $settings = quiz_settings::get_record(['quizid' => $this->quiz->id]);
 735          $settings->set('templateid', $template->get('id'));
 736          $settings->set('requiresafeexambrowser', settings_provider::USE_SEB_TEMPLATE);
 737          $settings->save();
 738  
 739          $this->set_up_user_and_role();
 740  
 741          assign_capability('quizaccess/seb:manage_seb_requiresafeexambrowser', CAP_ALLOW, $this->roleid, $this->context->id);
 742          assign_capability('quizaccess/seb:manage_seb_showsebdownloadlink', CAP_ALLOW, $this->roleid, $this->context->id);
 743          assign_capability('quizaccess/seb:manage_seb_allowedbrowserexamkeys', CAP_ALLOW, $this->roleid, $this->context->id);
 744  
 745          $this->set_up_form_mocks();
 746  
 747          settings_provider::add_seb_settings_fields($this->mockedquizform, $this->mockedform);
 748  
 749          $this->assertTrue($this->mockedform->isElementFrozen('seb_requiresafeexambrowser'));
 750          $this->assertTrue($this->mockedform->isElementFrozen('seb_templateid'));
 751          $this->assertTrue($this->mockedform->isElementFrozen('seb_showsebdownloadlink'));
 752          $this->assertTrue($this->mockedform->isElementFrozen('seb_allowedbrowserexamkeys'));
 753      }
 754  
 755      /**
 756       * Test that All settings are frozen if quiz was attempted and use seb with manual settings.
 757       */
 758      public function test_form_elements_are_locked_when_quiz_attempted_manual() {
 759          $this->resetAfterTest();
 760          $this->course = $this->getDataGenerator()->create_course();
 761  
 762          $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY);
 763          $this->context = \context_module::instance($this->quiz->cmid);
 764  
 765          $user = $this->getDataGenerator()->create_user();
 766          $this->attempt_quiz($this->quiz, $user);
 767  
 768          $this->setAdminUser();
 769          $this->set_up_form_mocks();
 770  
 771          settings_provider::add_seb_settings_fields($this->mockedquizform, $this->mockedform);
 772  
 773          $this->assertTrue($this->mockedform->isElementFrozen('seb_requiresafeexambrowser'));
 774          $this->assertTrue($this->mockedform->elementExists('filemanager_sebconfigfile'));
 775          $this->assertFalse($this->mockedform->elementExists('seb_templateid'));
 776          $this->assertTrue($this->mockedform->isElementFrozen('seb_showsebdownloadlink'));
 777          $this->assertTrue($this->mockedform->isElementFrozen('seb_allowedbrowserexamkeys'));
 778  
 779          foreach (settings_provider::get_seb_config_elements() as $name => $type) {
 780              $this->assertTrue($this->mockedform->isElementFrozen($name));
 781          }
 782      }
 783  
 784      /**
 785       * Test that All settings are frozen if a quiz was attempted and use template.
 786       */
 787      public function test_form_elements_are_locked_when_quiz_attempted_template() {
 788          $this->resetAfterTest();
 789          $this->setAdminUser();
 790          $this->course = $this->getDataGenerator()->create_course();
 791  
 792          $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY);
 793          $this->context = \context_module::instance($this->quiz->cmid);
 794  
 795          $template = $this->create_template();
 796  
 797          $settings = quiz_settings::get_record(['quizid' => $this->quiz->id]);
 798          $settings->set('templateid', $template->get('id'));
 799          $settings->set('requiresafeexambrowser', settings_provider::USE_SEB_TEMPLATE);
 800          $settings->save();
 801  
 802          $user = $this->getDataGenerator()->create_user();
 803          $this->attempt_quiz($this->quiz, $user);
 804  
 805          $this->setAdminUser();
 806          $this->set_up_form_mocks();
 807  
 808          settings_provider::add_seb_settings_fields($this->mockedquizform, $this->mockedform);
 809  
 810          $this->assertTrue($this->mockedform->isElementFrozen('seb_requiresafeexambrowser'));
 811          $this->assertTrue($this->mockedform->elementExists('filemanager_sebconfigfile'));
 812          $this->assertTrue($this->mockedform->isElementFrozen('seb_templateid'));
 813          $this->assertTrue($this->mockedform->isElementFrozen('seb_showsebdownloadlink'));
 814          $this->assertTrue($this->mockedform->isElementFrozen('seb_allowedbrowserexamkeys'));
 815  
 816          foreach (settings_provider::get_seb_config_elements() as $name => $type) {
 817              $this->assertTrue($this->mockedform->isElementFrozen($name));
 818          }
 819      }
 820  
 821      /**
 822       * Test Show Safe Exam Browser download button setting in the form.
 823       */
 824      public function test_showsebdownloadlink_in_form() {
 825          $this->resetAfterTest();
 826          $this->setAdminUser();
 827          $this->course = $this->getDataGenerator()->create_course();
 828  
 829          $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY);
 830          $this->context = \context_module::instance($this->quiz->cmid);
 831  
 832          $this->set_up_user_and_role();
 833  
 834          assign_capability('quizaccess/seb:manage_seb_requiresafeexambrowser', CAP_ALLOW, $this->roleid, $this->context->id);
 835          $this->set_up_form_mocks();
 836  
 837          // Shouldn't be in the form if no permissions.
 838          settings_provider::add_seb_settings_fields($this->mockedquizform, $this->mockedform);
 839          $this->assertFalse($this->mockedform->elementExists('seb_showsebdownloadlink'));
 840  
 841          // Should be in the form if we grant require permissions.
 842          assign_capability('quizaccess/seb:manage_seb_showsebdownloadlink', CAP_ALLOW, $this->roleid, $this->context->id);
 843  
 844          settings_provider::add_seb_settings_fields($this->mockedquizform, $this->mockedform);
 845          $this->assertTrue($this->mockedform->elementExists('seb_showsebdownloadlink'));
 846      }
 847  
 848      /**
 849       * Test Allowed Browser Exam Keys setting in the form.
 850       */
 851      public function test_allowedbrowserexamkeys_in_form() {
 852          $this->resetAfterTest();
 853          $this->setAdminUser();
 854          $this->course = $this->getDataGenerator()->create_course();
 855  
 856          $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CLIENT_CONFIG);
 857          $this->context = \context_module::instance($this->quiz->cmid);
 858  
 859          $this->set_up_user_and_role();
 860  
 861          assign_capability('quizaccess/seb:manage_seb_requiresafeexambrowser', CAP_ALLOW, $this->roleid, $this->context->id);
 862          $this->set_up_form_mocks();
 863  
 864          // Shouldn't be in the form if no permissions.
 865          settings_provider::add_seb_settings_fields($this->mockedquizform, $this->mockedform);
 866          $this->assertFalse($this->mockedform->elementExists('seb_allowedbrowserexamkeys'));
 867  
 868          // Should be in the form if we grant require permissions.
 869          assign_capability('quizaccess/seb:manage_seb_allowedbrowserexamkeys', CAP_ALLOW, $this->roleid, $this->context->id);
 870          settings_provider::add_seb_settings_fields($this->mockedquizform, $this->mockedform);
 871          $this->assertTrue($this->mockedform->elementExists('seb_allowedbrowserexamkeys'));
 872      }
 873  
 874      /**
 875       * Test the validation of a seb config file.
 876       */
 877      public function test_validate_draftarea_configfile_success() {
 878          $this->resetAfterTest();
 879  
 880          $user = $this->getDataGenerator()->create_user();
 881          $this->setUser($user);
 882          $xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
 883              . "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
 884              . "<plist version=\"1.0\"><dict><key>hashedQuitPassword</key><string>hashedpassword</string>"
 885              . "<key>allowWlan</key><false/></dict></plist>\n";
 886          $itemid = $this->create_test_draftarea_file($xml);
 887          $errors = settings_provider::validate_draftarea_configfile($itemid);
 888          $this->assertEmpty($errors);
 889      }
 890  
 891      /**
 892       * Test the validation of a missing seb config file.
 893       */
 894      public function test_validate_draftarea_configfile_failure() {
 895          $this->resetAfterTest();
 896  
 897          $user = $this->getDataGenerator()->create_user();
 898          $this->setUser($user);
 899          $xml = "This is not a config file.";
 900          $itemid = $this->create_test_draftarea_file($xml);
 901          $errors = settings_provider::validate_draftarea_configfile($itemid);
 902          $this->assertEquals($errors, new \lang_string('fileparsefailed', 'quizaccess_seb'));
 903      }
 904  
 905      /**
 906       * Test obtaining the draftarea content.
 907       */
 908      public function test_get_current_user_draft_file() {
 909          $this->resetAfterTest();
 910  
 911          $user = $this->getDataGenerator()->create_user();
 912          $this->setUser($user);
 913  
 914          $xml = file_get_contents(__DIR__ . '/fixtures/unencrypted.seb');
 915          $itemid = $this->create_test_draftarea_file($xml);
 916          $file = settings_provider::get_current_user_draft_file($itemid);
 917          $content = $file->get_content();
 918  
 919          $this->assertEquals($xml, $content);
 920      }
 921  
 922      /**
 923       * Test saving files from the user draft area into the quiz context area storage.
 924       */
 925      public function test_save_filemanager_sebconfigfile_draftarea() {
 926          $this->resetAfterTest();
 927          $this->course = $this->getDataGenerator()->create_course();
 928          $this->quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $this->course->id]);
 929          $this->context = \context_module::instance($this->quiz->cmid);
 930          $this->set_up_user_and_role();
 931  
 932          $xml = file_get_contents(__DIR__ . '/fixtures/unencrypted.seb');
 933  
 934          $draftitemid = $this->create_test_draftarea_file($xml);
 935  
 936          settings_provider::save_filemanager_sebconfigfile_draftarea($draftitemid, $this->quiz->cmid);
 937  
 938          $fs = get_file_storage();
 939          $files = $fs->get_area_files($this->context->id, 'quizaccess_seb', 'filemanager_sebconfigfile');
 940  
 941          $this->assertCount(2, $files);
 942      }
 943  
 944      /**
 945       * Test deleting the $this->quiz->cmid itemid from the file area.
 946       */
 947      public function test_delete_uploaded_config_file() {
 948          $this->resetAfterTest();
 949          $this->course = $this->getDataGenerator()->create_course();
 950          $this->quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $this->course->id]);
 951          $this->context = \context_module::instance($this->quiz->cmid);
 952          $this->set_up_user_and_role();
 953  
 954          $xml = file_get_contents(__DIR__ . '/fixtures/unencrypted.seb');
 955          $draftitemid = $this->create_test_draftarea_file($xml);
 956  
 957          settings_provider::save_filemanager_sebconfigfile_draftarea($draftitemid, $this->quiz->cmid);
 958  
 959          $fs = get_file_storage();
 960          $files = $fs->get_area_files($this->context->id, 'quizaccess_seb', 'filemanager_sebconfigfile');
 961          $this->assertCount(2, $files);
 962  
 963          settings_provider::delete_uploaded_config_file($this->quiz->cmid);
 964  
 965          $files = $fs->get_area_files($this->context->id, 'quizaccess_seb', 'filemanager_sebconfigfile');
 966          // The '.' directory.
 967          $this->assertCount(1, $files);
 968      }
 969  
 970      /**
 971       * Test getting the file from the context module id file area.
 972       */
 973      public function test_get_module_context_sebconfig_file() {
 974          $this->resetAfterTest();
 975          $this->setAdminUser();
 976  
 977          $this->course = $this->getDataGenerator()->create_course();
 978          $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY);
 979          $this->context = \context_module::instance($this->quiz->cmid);
 980  
 981          $this->set_up_user_and_role();
 982  
 983          $xml = file_get_contents(__DIR__ . '/fixtures/unencrypted.seb');
 984          $draftitemid = $this->create_test_draftarea_file($xml);
 985  
 986          $fs = get_file_storage();
 987          $files = $fs->get_area_files($this->context->id, 'quizaccess_seb', 'filemanager_sebconfigfile');
 988          $this->assertCount(0, $files);
 989  
 990          settings_provider::save_filemanager_sebconfigfile_draftarea($draftitemid, $this->quiz->cmid);
 991  
 992          $settings = quiz_settings::get_record(['quizid' => $this->quiz->id]);
 993          $settings->set('requiresafeexambrowser', settings_provider::USE_SEB_UPLOAD_CONFIG);
 994          $settings->save();
 995  
 996          $file = settings_provider::get_module_context_sebconfig_file($this->quiz->cmid);
 997  
 998          $this->assertSame($file->get_content(), $xml);
 999      }
1000  
1001      /**
1002       * Test file manager options.
1003       */
1004      public function test_get_filemanager_options() {
1005          $expected = [
1006              'subdirs' => 0,
1007              'maxfiles' => 1,
1008              'accepted_types' => ['.seb']
1009          ];
1010          $this->assertSame($expected, settings_provider::get_filemanager_options());
1011      }
1012  
1013      /**
1014       * Test that users can or can not configure seb settings.
1015       */
1016      public function test_can_configure_seb() {
1017          $this->resetAfterTest();
1018  
1019          $this->course = $this->getDataGenerator()->create_course();
1020          $this->quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $this->course->id]);
1021          $this->context = \context_module::instance($this->quiz->cmid);
1022          $this->setAdminUser();
1023  
1024          $this->assertTrue(settings_provider::can_configure_seb($this->context));
1025  
1026          $this->set_up_user_and_role();
1027  
1028          $this->assertFalse(settings_provider::can_configure_seb($this->context));
1029  
1030          assign_capability('quizaccess/seb:manage_seb_requiresafeexambrowser', CAP_ALLOW, $this->roleid, $this->context->id);
1031          $this->assertTrue(settings_provider::can_configure_seb($this->context));
1032      }
1033  
1034      /**
1035       * Test that users can or can not use seb template.
1036       */
1037      public function test_can_use_seb_template() {
1038          $this->resetAfterTest();
1039  
1040          $this->course = $this->getDataGenerator()->create_course();
1041          $this->quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $this->course->id]);
1042          $this->context = \context_module::instance($this->quiz->cmid);
1043          $this->setAdminUser();
1044  
1045          $this->assertTrue(settings_provider::can_use_seb_template($this->context));
1046  
1047          $this->set_up_user_and_role();
1048  
1049          $this->assertFalse(settings_provider::can_use_seb_template($this->context));
1050  
1051          assign_capability('quizaccess/seb:manage_seb_templateid', CAP_ALLOW, $this->roleid, $this->context->id);
1052          $this->assertTrue(settings_provider::can_use_seb_template($this->context));
1053      }
1054  
1055      /**
1056       * Test that users can or can not upload seb config file.
1057       */
1058      public function test_can_upload_seb_file() {
1059          $this->resetAfterTest();
1060  
1061          $this->course = $this->getDataGenerator()->create_course();
1062          $this->quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $this->course->id]);
1063          $this->context = \context_module::instance($this->quiz->cmid);
1064          $this->setAdminUser();
1065  
1066          $this->assertTrue(settings_provider::can_upload_seb_file($this->context));
1067  
1068          $this->set_up_user_and_role();
1069  
1070          $this->assertFalse(settings_provider::can_upload_seb_file($this->context));
1071  
1072          assign_capability('quizaccess/seb:manage_filemanager_sebconfigfile', CAP_ALLOW, $this->roleid, $this->context->id);
1073          $this->assertTrue(settings_provider::can_upload_seb_file($this->context));
1074      }
1075  
1076      /**
1077       * Test that users can or can not change Show Safe Exam Browser download button setting.
1078       */
1079      public function test_can_change_seb_showsebdownloadlink() {
1080          $this->resetAfterTest();
1081  
1082          $this->course = $this->getDataGenerator()->create_course();
1083          $this->quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $this->course->id]);
1084          $this->context = \context_module::instance($this->quiz->cmid);
1085          $this->setAdminUser();
1086          $this->assertTrue(settings_provider::can_change_seb_showsebdownloadlink($this->context));
1087  
1088          $this->set_up_user_and_role();
1089  
1090          $this->assertFalse(settings_provider::can_change_seb_showsebdownloadlink($this->context));
1091  
1092          assign_capability('quizaccess/seb:manage_seb_showsebdownloadlink', CAP_ALLOW, $this->roleid, $this->context->id);
1093          $this->assertTrue(settings_provider::can_change_seb_showsebdownloadlink($this->context));
1094      }
1095  
1096      /**
1097       * Test that users can or can not change Allowed Browser Exam Keys setting.
1098       */
1099      public function test_can_change_seb_allowedbrowserexamkeys() {
1100          $this->resetAfterTest();
1101          $this->course = $this->getDataGenerator()->create_course();
1102  
1103          $this->quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $this->course->id]);
1104          $this->context = \context_module::instance($this->quiz->cmid);
1105          $this->setAdminUser();
1106          $this->assertTrue(settings_provider::can_change_seb_allowedbrowserexamkeys($this->context));
1107  
1108          $this->set_up_user_and_role();
1109  
1110          $this->assertFalse(settings_provider::can_change_seb_allowedbrowserexamkeys($this->context));
1111  
1112          assign_capability('quizaccess/seb:manage_seb_allowedbrowserexamkeys', CAP_ALLOW, $this->roleid, $this->context->id);
1113          $this->assertTrue(settings_provider::can_change_seb_allowedbrowserexamkeys($this->context));
1114      }
1115  
1116      /**
1117       * Test that users can or can not Configure SEb manually
1118       *
1119       * @param string $settingcapability Setting capability to check manual option against.
1120       *
1121       * @dataProvider settings_capability_data_provider
1122       */
1123      public function test_can_configure_manually($settingcapability) {
1124          $this->resetAfterTest();
1125          $this->course = $this->getDataGenerator()->create_course();
1126  
1127          $this->quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $this->course->id]);
1128          $this->context = \context_module::instance($this->quiz->cmid);
1129          $this->setAdminUser();
1130  
1131          $this->assertTrue(settings_provider::can_configure_manually($this->context));
1132  
1133          $this->set_up_user_and_role();
1134  
1135          $this->assertFalse(settings_provider::can_configure_manually($this->context));
1136  
1137          assign_capability($settingcapability, CAP_ALLOW, $this->roleid, $this->context->id);
1138          $this->assertTrue(settings_provider::can_configure_manually($this->context));
1139      }
1140  
1141      /**
1142       * Test that we can check if the seb settings are locked.
1143       */
1144      public function test_is_seb_settings_locked() {
1145          $this->resetAfterTest();
1146  
1147          $this->course = $this->getDataGenerator()->create_course();
1148          $this->quiz = $this->create_test_quiz($this->course);
1149          $user = $this->getDataGenerator()->create_user();
1150  
1151          $this->assertFalse(settings_provider::is_seb_settings_locked($this->quiz->id));
1152  
1153          $this->attempt_quiz($this->quiz, $user);
1154          $this->assertTrue(settings_provider::is_seb_settings_locked($this->quiz->id));
1155      }
1156  
1157      /**
1158       * Test that we can check identify conflicting permissions if set to use template.
1159       */
1160      public function test_is_conflicting_permissions_for_manage_templates() {
1161          $this->resetAfterTest();
1162          $this->setAdminUser();
1163  
1164          $this->course = $this->getDataGenerator()->create_course();
1165          $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY);
1166          $this->context = \context_module::instance($this->quiz->cmid);
1167  
1168          // Create a template.
1169          $template = $this->create_template();
1170          $settings = quiz_settings::get_record(['quizid' => $this->quiz->id]);
1171          $settings->set('templateid', $template->get('id'));
1172          $settings->set('requiresafeexambrowser', settings_provider::USE_SEB_TEMPLATE);
1173          $settings->save();
1174  
1175          $this->assertFalse(settings_provider::is_conflicting_permissions($this->context));
1176  
1177          $this->set_up_user_and_role();
1178  
1179          $this->assertTrue(settings_provider::is_conflicting_permissions($this->context));
1180  
1181          assign_capability('quizaccess/seb:manage_seb_templateid', CAP_ALLOW, $this->roleid, $this->context->id);
1182          $this->assertFalse(settings_provider::is_conflicting_permissions($this->context));
1183      }
1184  
1185      /**
1186       * Test that we can check identify conflicting permissions if set to use own seb file.
1187       */
1188      public function test_is_conflicting_permissions_for_upload_seb_file() {
1189          $this->resetAfterTest();
1190          $this->setAdminUser();
1191  
1192          $this->course = $this->getDataGenerator()->create_course();
1193          $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY);
1194          $this->context = \context_module::instance($this->quiz->cmid);
1195  
1196          // Save file.
1197          $xml = file_get_contents(__DIR__ . '/fixtures/unencrypted.seb');
1198          $draftitemid = $this->create_test_draftarea_file($xml);
1199          settings_provider::save_filemanager_sebconfigfile_draftarea($draftitemid, $this->quiz->cmid);
1200          $settings = quiz_settings::get_record(['quizid' => $this->quiz->id]);
1201          $settings->set('requiresafeexambrowser', settings_provider::USE_SEB_UPLOAD_CONFIG);
1202          $settings->save();
1203  
1204          $this->assertFalse(settings_provider::is_conflicting_permissions($this->context));
1205  
1206          $this->set_up_user_and_role();
1207  
1208          assign_capability('quizaccess/seb:manage_filemanager_sebconfigfile', CAP_ALLOW, $this->roleid, $this->context->id);
1209          $this->assertFalse(settings_provider::is_conflicting_permissions($this->context));
1210      }
1211  
1212      /**
1213       * Test that we can check identify conflicting permissions if set to use own configure manually.
1214       *
1215       * @param string $settingcapability Setting capability to check manual option against.
1216       *
1217       * @dataProvider settings_capability_data_provider
1218       */
1219      public function test_is_conflicting_permissions_for_configure_manually($settingcapability) {
1220          $this->resetAfterTest();
1221          $this->setAdminUser();
1222  
1223          $this->course = $this->getDataGenerator()->create_course();
1224          $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY);
1225          $this->context = \context_module::instance($this->quiz->cmid);
1226  
1227          $this->assertFalse(settings_provider::is_conflicting_permissions($this->context));
1228  
1229          $this->set_up_user_and_role();
1230  
1231          assign_capability($settingcapability, CAP_ALLOW, $this->roleid, $this->context->id);
1232          $this->assertFalse(settings_provider::is_conflicting_permissions($this->context));
1233      }
1234  
1235      /**
1236       * Test add_prefix helper method.
1237       */
1238      public function test_add_prefix() {
1239          $this->assertEquals('seb_one', settings_provider::add_prefix('one'));
1240          $this->assertEquals('seb_two', settings_provider::add_prefix('seb_two'));
1241          $this->assertEquals('seb_seb_three', settings_provider::add_prefix('seb_seb_three'));
1242          $this->assertEquals('seb_', settings_provider::add_prefix('seb_'));
1243          $this->assertEquals('seb_', settings_provider::add_prefix(''));
1244          $this->assertEquals('seb_one_seb', settings_provider::add_prefix('one_seb'));
1245      }
1246  
1247      /**
1248       * Test filter_plugin_settings helper method.
1249       */
1250      public function test_filter_plugin_settings() {
1251          $test = new \stdClass();
1252          $test->one = 'one';
1253          $test->seb_two = 'two';
1254          $test->seb_seb_three = 'three';
1255          $test->four = 'four';
1256  
1257          $newsettings = (array)settings_provider::filter_plugin_settings($test);
1258  
1259          $this->assertFalse(key_exists('one', $newsettings));
1260          $this->assertFalse(key_exists('four', $newsettings));
1261  
1262          $this->assertCount(2, $newsettings);
1263          $this->assertEquals('two', $newsettings['two']);
1264          $this->assertEquals('three', $newsettings['seb_three']);
1265      }
1266  
1267      /**
1268       * Helper method to get a list of settings.
1269       *
1270       * @return \stdClass
1271       */
1272      protected function get_settings() {
1273          $allsettings = new \stdClass();
1274          $allsettings->seb_showsebdownloadlink = 0;
1275          $allsettings->seb_linkquitseb = 2;
1276          $allsettings->seb_userconfirmquit = 3;
1277          $allsettings->seb_allowuserquitseb = 4;
1278          $allsettings->seb_quitpassword = 5;
1279          $allsettings->seb_allowreloadinexam = 6;
1280          $allsettings->seb_showsebtaskbar = 7;
1281          $allsettings->seb_showreloadbutton = 8;
1282          $allsettings->seb_showtime = 9;
1283          $allsettings->seb_showkeyboardlayout = 10;
1284          $allsettings->seb_showwificontrol = 11;
1285          $allsettings->seb_enableaudiocontrol = 12;
1286          $allsettings->seb_muteonstartup = 13;
1287          $allsettings->seb_allowspellchecking = 14;
1288          $allsettings->seb_activateurlfiltering = 15;
1289          $allsettings->seb_filterembeddedcontent = 16;
1290          $allsettings->seb_expressionsallowed = 17;
1291          $allsettings->seb_regexallowed = 18;
1292          $allsettings->seb_expressionsblocked = 19;
1293          $allsettings->seb_regexblocked = 20;
1294          $allsettings->seb_templateid = 21;
1295          $allsettings->seb_allowedbrowserexamkeys = 22;
1296  
1297          return $allsettings;
1298      }
1299  
1300      /**
1301       * Helper method to assert results of filter_plugin_settings
1302       *
1303       * @param int $type Type of SEB usage.
1304       * @param array $notnulls A list of expected not null settings.
1305       */
1306      protected function assert_filter_plugin_settings(int $type, array $notnulls) {
1307          $allsettings = $this->get_settings();
1308          $allsettings->seb_requiresafeexambrowser = $type;
1309          $actual = settings_provider::filter_plugin_settings($allsettings);
1310  
1311          $expected = (array)$allsettings;
1312          foreach ($actual as $name => $value) {
1313              if (in_array($name, $notnulls)) {
1314                  $this->assertEquals($expected['seb_' . $name], $value);
1315              } else {
1316                  $this->assertNull($value);
1317              }
1318          }
1319      }
1320  
1321      /**
1322       * Test filter_plugin_settings method for no SEB case.
1323       */
1324      public function test_filter_plugin_settings_for_no_seb() {
1325          $notnulls = ['requiresafeexambrowser'];
1326          $this->assert_filter_plugin_settings(settings_provider::USE_SEB_NO, $notnulls);
1327      }
1328  
1329      /**
1330       * Test filter_plugin_settings method for using uploaded config.
1331       */
1332      public function test_filter_plugin_settings_for_uploaded_config() {
1333          $notnulls = ['requiresafeexambrowser', 'showsebdownloadlink', 'allowedbrowserexamkeys'];
1334          $this->assert_filter_plugin_settings(settings_provider::USE_SEB_UPLOAD_CONFIG, $notnulls);
1335      }
1336  
1337      /**
1338       * Test filter_plugin_settings method for using template.
1339       */
1340      public function test_filter_plugin_settings_for_template() {
1341          $notnulls = ['requiresafeexambrowser', 'showsebdownloadlink', 'allowuserquitseb', 'quitpassword', 'templateid'];
1342          $this->assert_filter_plugin_settings(settings_provider::USE_SEB_TEMPLATE, $notnulls);
1343      }
1344  
1345      /**
1346       * Test filter_plugin_settings method for using client config.
1347       */
1348      public function test_filter_plugin_settings_for_client_config() {
1349          $notnulls = ['requiresafeexambrowser', 'showsebdownloadlink', 'allowedbrowserexamkeys'];
1350          $this->assert_filter_plugin_settings(settings_provider::USE_SEB_CLIENT_CONFIG, $notnulls);
1351      }
1352  
1353      /**
1354       * Test filter_plugin_settings method for manually configured SEB.
1355       */
1356      public function test_filter_plugin_settings_for_configure_manually() {
1357          $allsettings = $this->get_settings();
1358          $allsettings->seb_requiresafeexambrowser = settings_provider::USE_SEB_CONFIG_MANUALLY;
1359          $actual = settings_provider::filter_plugin_settings($allsettings);
1360  
1361          // For manual it's easier to check nulls, as most of the settings are not null.
1362          $nulls = ['templateid', 'allowedbrowserexamkeys'];
1363  
1364          $expected = (array)$allsettings;
1365          foreach ($actual as $name => $value) {
1366              if (in_array($name, $nulls)) {
1367                  $this->assertNull($value);
1368              } else {
1369                  $this->assertEquals($expected['seb_' . $name], $value);
1370              }
1371          }
1372      }
1373  
1374      /**
1375       * Test settings map.
1376       */
1377      public function test_get_seb_settings_map() {
1378          $expected = [
1379              settings_provider::USE_SEB_NO => [
1380  
1381              ],
1382              settings_provider::USE_SEB_CONFIG_MANUALLY => [
1383                  'seb_showsebdownloadlink' => [],
1384                  'seb_linkquitseb' => [],
1385                  'seb_userconfirmquit' => [],
1386                  'seb_allowuserquitseb' => [
1387                      'seb_quitpassword' => []
1388                  ],
1389                  'seb_allowreloadinexam' => [],
1390                  'seb_showsebtaskbar' => [
1391                      'seb_showreloadbutton' => [],
1392                      'seb_showtime' => [],
1393                      'seb_showkeyboardlayout' => [],
1394                      'seb_showwificontrol' => [],
1395                  ],
1396                  'seb_enableaudiocontrol' => [
1397                      'seb_muteonstartup' => [],
1398                  ],
1399                  'seb_allowspellchecking' => [],
1400                  'seb_activateurlfiltering' => [
1401                      'seb_filterembeddedcontent' => [],
1402                      'seb_expressionsallowed' => [],
1403                      'seb_regexallowed' => [],
1404                      'seb_expressionsblocked' => [],
1405                      'seb_regexblocked' => [],
1406                  ],
1407              ],
1408              settings_provider::USE_SEB_TEMPLATE => [
1409                  'seb_templateid' => [],
1410                  'seb_showsebdownloadlink' => [],
1411                  'seb_allowuserquitseb' => [
1412                      'seb_quitpassword' => [],
1413                  ],
1414              ],
1415              settings_provider::USE_SEB_UPLOAD_CONFIG => [
1416                  'filemanager_sebconfigfile' => [],
1417                  'seb_showsebdownloadlink' => [],
1418                  'seb_allowedbrowserexamkeys' => [],
1419              ],
1420              settings_provider::USE_SEB_CLIENT_CONFIG => [
1421                  'seb_showsebdownloadlink' => [],
1422                  'seb_allowedbrowserexamkeys' => [],
1423              ],
1424          ];
1425  
1426          $this->assertEquals($expected, settings_provider::get_seb_settings_map());
1427      }
1428  
1429  }